2 Unix SMB/CIFS implementation.
4 general name resolution interface
6 Copyright (C) Andrew Tridgell 2005
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "lib/events/events.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/composite/composite.h"
28 struct resolve_state
{
31 struct composite_context
*req
;
32 const char *reply_addr
;
35 static struct composite_context
*setup_next_method(struct composite_context
*c
);
37 /* pointers to the resolver backends */
38 static const struct resolve_method
{
40 struct composite_context
*(*send_fn
)(struct nbt_name
*, struct event_context
*);
41 NTSTATUS (*recv_fn
)(struct composite_context
*, TALLOC_CTX
*, const char **);
44 { "bcast", resolve_name_bcast_send
, resolve_name_bcast_recv
},
45 { "wins", resolve_name_wins_send
, resolve_name_wins_recv
},
46 { "host", resolve_name_host_send
, resolve_name_host_recv
}
51 find a matching backend
53 static const struct resolve_method
*find_method(const char *name
)
56 if (name
== NULL
) return NULL
;
57 for (i
=0;i
<ARRAY_SIZE(methods
);i
++) {
58 if (strcasecmp(name
, methods
[i
].name
) == 0) {
66 handle completion of one name resolve method
68 static void resolve_handler(struct composite_context
*req
)
70 struct composite_context
*c
= req
->async
.private;
71 struct resolve_state
*state
= talloc_get_type(c
->private, struct resolve_state
);
72 const struct resolve_method
*method
= find_method(state
->methods
[0]);
74 c
->status
= method
->recv_fn(req
, state
, &state
->reply_addr
);
76 if (!NT_STATUS_IS_OK(c
->status
)) {
78 state
->req
= setup_next_method(c
);
79 if (state
->req
!= NULL
) {
84 if (!NT_STATUS_IS_OK(c
->status
)) {
85 c
->state
= SMBCLI_REQUEST_ERROR
;
87 c
->state
= SMBCLI_REQUEST_DONE
;
95 static struct composite_context
*setup_next_method(struct composite_context
*c
)
97 struct resolve_state
*state
= talloc_get_type(c
->private, struct resolve_state
);
98 struct composite_context
*req
= NULL
;
101 const struct resolve_method
*method
= find_method(state
->methods
[0]);
103 req
= method
->send_fn(&state
->name
, c
->event_ctx
);
105 if (req
== NULL
&& state
->methods
[0]) state
->methods
++;
106 } while (!req
&& state
->methods
[0]);
109 req
->async
.fn
= resolve_handler
;
110 req
->async
.private = c
;
117 general name resolution - async send
119 struct composite_context
*resolve_name_send(struct nbt_name
*name
, struct event_context
*event_ctx
,
120 const char **methods
)
122 struct composite_context
*c
;
123 struct resolve_state
*state
;
126 c
= talloc_zero(NULL
, struct composite_context
);
127 if (c
== NULL
) goto failed
;
129 state
= talloc(c
, struct resolve_state
);
130 if (state
== NULL
) goto failed
;
132 status
= nbt_name_dup(state
, name
, &state
->name
);
133 if (!NT_STATUS_IS_OK(status
)) goto failed
;
135 if (methods
== NULL
) goto failed
;
136 state
->methods
= methods
;
138 c
->state
= SMBCLI_REQUEST_SEND
;
140 if (event_ctx
== NULL
) {
141 c
->event_ctx
= event_context_init(c
);
142 if (c
->event_ctx
== NULL
) goto failed
;
144 c
->event_ctx
= talloc_reference(c
, event_ctx
);
147 state
->req
= setup_next_method(c
);
148 if (state
->req
== NULL
) goto failed
;
158 general name resolution method - recv side
160 NTSTATUS
resolve_name_recv(struct composite_context
*c
,
161 TALLOC_CTX
*mem_ctx
, const char **reply_addr
)
165 status
= composite_wait(c
);
167 if (NT_STATUS_IS_OK(status
)) {
168 struct resolve_state
*state
= talloc_get_type(c
->private, struct resolve_state
);
169 *reply_addr
= talloc_steal(mem_ctx
, state
->reply_addr
);
177 general name resolution - sync call
179 NTSTATUS
resolve_name(struct nbt_name
*name
, TALLOC_CTX
*mem_ctx
, const char **reply_addr
)
181 struct composite_context
*c
= resolve_name_send(name
, NULL
, lp_name_resolve_order());
182 return resolve_name_recv(c
, mem_ctx
, reply_addr
);
185 /* Initialise a struct nbt_name with a NULL scope */
187 void make_nbt_name(struct nbt_name
*nbt
, const char *name
, int type
)
194 /* Initialise a struct nbt_name with a NBT_NAME_CLIENT (0x00) name */
196 void make_nbt_name_client(struct nbt_name
*nbt
, const char *name
)
198 make_nbt_name(nbt
, name
, NBT_NAME_CLIENT
);
201 /* Initialise a struct nbt_name with a NBT_NAME_SERVER (0x20) name */
203 void make_nbt_name_server(struct nbt_name
*nbt
, const char *name
)
205 make_nbt_name(nbt
, name
, NBT_NAME_SERVER
);