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 "lib/events/events.h"
25 #include "libcli/composite/composite.h"
26 #include "libcli/resolve/resolve.h"
27 #include "librpc/gen_ndr/ndr_nbt.h"
28 #include "system/network.h"
29 #include "../lib/util/dlinklist.h"
31 struct resolve_state {
32 struct resolve_context *ctx;
33 struct resolve_method *method;
35 struct composite_context *creq;
36 const char *reply_addr;
39 static struct composite_context *setup_next_method(struct composite_context *c);
42 struct resolve_context {
43 struct resolve_method {
44 resolve_name_send_fn send_fn;
45 resolve_name_recv_fn recv_fn;
47 struct resolve_method *prev, *next;
52 * Initialize a resolve context
54 struct resolve_context *resolve_context_init(TALLOC_CTX *mem_ctx)
56 return talloc_zero(mem_ctx, struct resolve_context);
60 * Add a resolve method
62 bool resolve_context_add_method(struct resolve_context *ctx, resolve_name_send_fn send_fn,
63 resolve_name_recv_fn recv_fn, void *userdata)
65 struct resolve_method *method = talloc_zero(ctx, struct resolve_method);
70 method->send_fn = send_fn;
71 method->recv_fn = recv_fn;
72 method->privdata = userdata;
73 DLIST_ADD_END(ctx->methods, method, struct resolve_method *);
78 handle completion of one name resolve method
80 static void resolve_handler(struct composite_context *creq)
82 struct composite_context *c = (struct composite_context *)creq->async.private_data;
83 struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
84 const struct resolve_method *method = state->method;
86 c->status = method->recv_fn(creq, state, &state->reply_addr);
88 if (!NT_STATUS_IS_OK(c->status)) {
89 state->method = state->method->next;
90 state->creq = setup_next_method(c);
91 if (state->creq != NULL) {
96 if (!NT_STATUS_IS_OK(c->status)) {
97 c->state = COMPOSITE_STATE_ERROR;
99 c->state = COMPOSITE_STATE_DONE;
107 static struct composite_context *setup_next_method(struct composite_context *c)
109 struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
110 struct composite_context *creq = NULL;
114 creq = state->method->send_fn(c, c->event_ctx, state->method->privdata, &state->name);
116 if (creq == NULL && state->method) state->method = state->method->next;
118 } while (!creq && state->method);
121 creq->async.fn = resolve_handler;
122 creq->async.private_data = c;
129 general name resolution - async send
131 struct composite_context *resolve_name_send(struct resolve_context *ctx,
132 struct nbt_name *name,
133 struct event_context *event_ctx)
135 struct composite_context *c;
136 struct resolve_state *state;
138 if (ctx == NULL || event_ctx == NULL) {
142 c = composite_create(ctx, event_ctx);
143 if (c == NULL) return NULL;
145 if (composite_nomem(c->event_ctx, c)) return c;
147 state = talloc(c, struct resolve_state);
148 if (composite_nomem(state, c)) return c;
149 c->private_data = state;
151 c->status = nbt_name_dup(state, name, &state->name);
152 if (!composite_is_ok(c)) return c;
154 state->ctx = talloc_reference(state, ctx);
155 if (composite_nomem(state->ctx, c)) return c;
157 if (is_ipaddress(state->name.name) ||
158 strcasecmp(state->name.name, "localhost") == 0) {
159 struct in_addr ip = interpret_addr2(state->name.name);
160 state->reply_addr = talloc_strdup(state, inet_ntoa(ip));
161 if (composite_nomem(state->reply_addr, c)) return c;
166 state->method = ctx->methods;
167 if (state->method == NULL) {
168 composite_error(c, NT_STATUS_BAD_NETWORK_NAME);
171 state->creq = setup_next_method(c);
172 if (composite_nomem(state->creq, c)) return c;
178 general name resolution method - recv side
180 NTSTATUS resolve_name_recv(struct composite_context *c,
181 TALLOC_CTX *mem_ctx, const char **reply_addr)
185 status = composite_wait(c);
187 if (NT_STATUS_IS_OK(status)) {
188 struct resolve_state *state = talloc_get_type(c->private_data, struct resolve_state);
189 *reply_addr = talloc_steal(mem_ctx, state->reply_addr);
197 general name resolution - sync call
199 NTSTATUS resolve_name(struct resolve_context *ctx, struct nbt_name *name, TALLOC_CTX *mem_ctx, const char **reply_addr, struct event_context *ev)
201 struct composite_context *c = resolve_name_send(ctx, name, ev);
202 return resolve_name_recv(c, mem_ctx, reply_addr);
205 /* Initialise a struct nbt_name with a NULL scope */
207 void make_nbt_name(struct nbt_name *nbt, const char *name, int type)
214 /* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
216 void make_nbt_name_client(struct nbt_name *nbt, const char *name)
218 make_nbt_name(nbt, name, NBT_NAME_CLIENT);
221 /* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
223 void make_nbt_name_server(struct nbt_name *nbt, const char *name)
225 make_nbt_name(nbt, name, NBT_NAME_SERVER);