2 Unix SMB/CIFS implementation.
4 nbt list of addresses name resolution module
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 3 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, see <http://www.gnu.org/licenses/>.
23 TODO: we should lower the timeout, and add retries for each name
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"
36 struct nbtlist_state
{
40 struct nbt_name_socket
*nbtsock
;
42 struct nbt_name_request
**queries
;
43 struct nbt_name_query
*io_queries
;
44 struct socket_address
**addrs
;
46 struct interface
*ifaces
;
50 handle events during nbtlist name resolution
52 static void nbtlist_handler(struct nbt_name_request
*req
)
54 struct composite_context
*c
= talloc_get_type(req
->async
.private_data
,
55 struct composite_context
);
56 struct nbtlist_state
*state
= talloc_get_type(c
->private_data
, struct nbtlist_state
);
57 struct nbt_name_query
*q
;
60 for (i
=0;i
<state
->num_queries
;i
++) {
61 if (req
== state
->queries
[i
]) break;
64 if (i
== state
->num_queries
) {
66 composite_error(c
, NT_STATUS_INTERNAL_ERROR
);
70 q
= &state
->io_queries
[i
];
72 c
->status
= nbt_name_query_recv(req
, state
, q
);
74 /* free the network resource directly */
75 talloc_free(state
->nbtsock
);
76 if (!composite_is_ok(c
)) return;
78 if (q
->out
.num_addrs
< 1) {
79 composite_error(c
, NT_STATUS_UNEXPECTED_NETWORK_ERROR
);
83 state
->addrs
= talloc_array(state
, struct socket_address
*,
84 q
->out
.num_addrs
+ 1);
85 if (composite_nomem(state
->addrs
, c
)) return;
87 state
->names
= talloc_array(state
, char *, q
->out
.num_addrs
+ 1);
88 if (composite_nomem(state
->names
, c
)) return;
90 for (i
=0;i
<q
->out
.num_addrs
;i
++) {
91 state
->addrs
[i
] = socket_address_from_strings(state
->addrs
,
93 q
->out
.reply_addrs
[i
],
95 if (composite_nomem(state
->addrs
[i
], c
)) return;
97 state
->names
[i
] = talloc_strdup(state
->names
, state
->name
.name
);
98 if (composite_nomem(state
->names
[i
], c
)) return;
100 state
->addrs
[i
] = NULL
;
101 state
->names
[i
] = NULL
;
107 nbtlist name resolution method - async send
109 struct composite_context
*resolve_name_nbtlist_send(TALLOC_CTX
*mem_ctx
,
110 struct tevent_context
*event_ctx
,
113 struct nbt_name
*name
,
114 const char **address_list
,
115 struct interface
*ifaces
,
121 struct composite_context
*c
;
122 struct nbtlist_state
*state
;
125 c
= composite_create(mem_ctx
, event_ctx
);
126 if (c
== NULL
) return NULL
;
128 if (flags
& RESOLVE_NAME_FLAG_FORCE_DNS
) {
129 composite_error(c
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
133 if (strlen(name
->name
) > 15) {
134 composite_error(c
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
138 state
= talloc(c
, struct nbtlist_state
);
139 if (composite_nomem(state
, c
)) return c
;
140 c
->private_data
= state
;
142 state
->flags
= flags
;
145 c
->status
= nbt_name_dup(state
, name
, &state
->name
);
146 if (!composite_is_ok(c
)) return c
;
148 state
->name
.name
= strupper_talloc(state
, state
->name
.name
);
149 if (composite_nomem(state
->name
.name
, c
)) return c
;
150 if (state
->name
.scope
) {
151 state
->name
.scope
= strupper_talloc(state
, state
->name
.scope
);
152 if (composite_nomem(state
->name
.scope
, c
)) return c
;
155 state
->ifaces
= talloc_reference(state
, ifaces
);
158 * we can't push long names on the wire,
159 * so bail out here to give a useful error message
161 if (strlen(state
->name
.name
) > 15) {
162 composite_error(c
, NT_STATUS_OBJECT_NAME_NOT_FOUND
);
166 state
->nbtsock
= nbt_name_socket_init(state
, event_ctx
);
167 if (composite_nomem(state
->nbtsock
, c
)) return c
;
169 /* count the address_list size */
170 for (i
=0;address_list
[i
];i
++) /* noop */ ;
172 state
->num_queries
= i
;
173 state
->io_queries
= talloc_array(state
, struct nbt_name_query
, state
->num_queries
);
174 if (composite_nomem(state
->io_queries
, c
)) return c
;
176 state
->queries
= talloc_array(state
, struct nbt_name_request
*, state
->num_queries
);
177 if (composite_nomem(state
->queries
, c
)) return c
;
179 for (i
=0;i
<state
->num_queries
;i
++) {
180 state
->io_queries
[i
].in
.name
= state
->name
;
181 state
->io_queries
[i
].in
.dest_addr
= talloc_strdup(state
->io_queries
, address_list
[i
]);
182 state
->io_queries
[i
].in
.dest_port
= nbt_port
;
183 if (composite_nomem(state
->io_queries
[i
].in
.dest_addr
, c
)) return c
;
185 state
->io_queries
[i
].in
.broadcast
= broadcast
;
186 state
->io_queries
[i
].in
.wins_lookup
= wins_lookup
;
187 state
->io_queries
[i
].in
.timeout
= nbt_timeout
;
188 state
->io_queries
[i
].in
.retries
= 2;
190 state
->queries
[i
] = nbt_name_query_send(state
->nbtsock
, &state
->io_queries
[i
]);
191 if (composite_nomem(state
->queries
[i
], c
)) return c
;
193 state
->queries
[i
]->async
.fn
= nbtlist_handler
;
194 state
->queries
[i
]->async
.private_data
= c
;
201 nbt list of addresses name resolution method - recv side
203 NTSTATUS
resolve_name_nbtlist_recv(struct composite_context
*c
,
205 struct socket_address
***addrs
,
210 status
= composite_wait(c
);
212 if (NT_STATUS_IS_OK(status
)) {
213 struct nbtlist_state
*state
= talloc_get_type(c
->private_data
, struct nbtlist_state
);
214 *addrs
= talloc_steal(mem_ctx
, state
->addrs
);
216 *names
= talloc_steal(mem_ctx
, state
->names
);