2 Unix SMB/CIFS implementation.
4 send out a name registration request
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 "libcli/nbt/libnbt.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/composite/composite.h"
27 #include "system/network.h"
30 send a nbt name registration request
32 struct nbt_name_request
*nbt_name_register_send(struct nbt_name_socket
*nbtsock
,
33 struct nbt_name_register
*io
)
35 struct nbt_name_request
*req
;
36 struct nbt_name_packet
*packet
;
38 packet
= talloc_zero(nbtsock
, struct nbt_name_packet
);
39 if (packet
== NULL
) return NULL
;
43 packet
->operation
= NBT_OPCODE_REGISTER
;
44 if (io
->in
.broadcast
) {
45 packet
->operation
|= NBT_FLAG_BROADCAST
;
47 if (io
->in
.register_demand
) {
48 packet
->operation
|= NBT_FLAG_RECURSION_DESIRED
;
51 packet
->questions
= talloc_array(packet
, struct nbt_name_question
, 1);
52 if (packet
->questions
== NULL
) goto failed
;
54 packet
->questions
[0].name
= io
->in
.name
;
55 packet
->questions
[0].question_type
= NBT_QTYPE_NETBIOS
;
56 packet
->questions
[0].question_class
= NBT_QCLASS_IP
;
58 packet
->additional
= talloc_array(packet
, struct nbt_res_rec
, 1);
59 if (packet
->additional
== NULL
) goto failed
;
61 packet
->additional
[0].name
= io
->in
.name
;
62 packet
->additional
[0].rr_type
= NBT_QTYPE_NETBIOS
;
63 packet
->additional
[0].rr_class
= NBT_QCLASS_IP
;
64 packet
->additional
[0].ttl
= io
->in
.ttl
;
65 packet
->additional
[0].rdata
.netbios
.length
= 6;
66 packet
->additional
[0].rdata
.netbios
.addresses
= talloc_array(packet
->additional
,
67 struct nbt_rdata_address
, 1);
68 if (packet
->additional
[0].rdata
.netbios
.addresses
== NULL
) goto failed
;
69 packet
->additional
[0].rdata
.netbios
.addresses
[0].nb_flags
= io
->in
.nb_flags
;
70 packet
->additional
[0].rdata
.netbios
.addresses
[0].ipaddr
= htonl(inet_addr(io
->in
.address
));
72 req
= nbt_name_request_send(nbtsock
, io
->in
.dest_addr
, lp_nbt_port(), packet
,
73 timeval_current_ofs(io
->in
.timeout
, 0), False
);
74 if (req
== NULL
) goto failed
;
85 wait for a registration reply
87 NTSTATUS
nbt_name_register_recv(struct nbt_name_request
*req
,
88 TALLOC_CTX
*mem_ctx
, struct nbt_name_register
*io
)
91 struct nbt_name_packet
*packet
;
95 status
= nbt_name_request_recv(req
);
96 if (!NT_STATUS_IS_OK(status
) ||
97 req
->num_replies
== 0) {
102 packet
= req
->replies
[0].packet
;
103 io
->out
.reply_from
= talloc_steal(mem_ctx
, req
->replies
[0].reply_addr
);
105 if (packet
->ancount
!= 1 ||
106 packet
->answers
[0].rr_type
!= NBT_QTYPE_NETBIOS
||
107 packet
->answers
[0].rr_class
!= NBT_QCLASS_IP
) {
109 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
112 io
->out
.rcode
= packet
->operation
& NBT_RCODE
;
113 io
->out
.name
= packet
->answers
[0].name
;
114 if (packet
->answers
[0].rdata
.netbios
.length
< 6) {
116 return NT_STATUS_INVALID_NETWORK_RESPONSE
;
118 in
.s_addr
= htonl(packet
->answers
[0].rdata
.netbios
.addresses
[0].ipaddr
);
119 addr
= inet_ntoa(in
);
122 return NT_STATUS_NO_MEMORY
;
124 io
->out
.reply_addr
= talloc_strdup(mem_ctx
, addr
);
125 talloc_steal(mem_ctx
, io
->out
.name
.name
);
126 talloc_steal(mem_ctx
, io
->out
.name
.scope
);
134 synchronous name registration request
136 NTSTATUS
nbt_name_register(struct nbt_name_socket
*nbtsock
,
137 TALLOC_CTX
*mem_ctx
, struct nbt_name_register
*io
)
139 struct nbt_name_request
*req
= nbt_name_register_send(nbtsock
, io
);
140 return nbt_name_register_recv(req
, mem_ctx
, io
);
145 a 4 step broadcast registration. 3 lots of name registration requests, followed by
146 a name registration demand
148 struct register_bcast_state
{
149 struct nbt_name_socket
*nbtsock
;
150 struct nbt_name_register
*io
;
152 struct nbt_name_request
*req
;
157 state handler for 4 stage name registration
159 static void name_register_handler(struct nbt_name_request
*req
)
161 struct composite_context
*c
= talloc_get_type(req
->async
.private, struct composite_context
);
162 struct register_bcast_state
*state
= talloc_get_type(c
->private, struct register_bcast_state
);
165 status
= nbt_name_register_recv(state
->req
, state
, state
->io
);
166 if (NT_STATUS_EQUAL(status
, NT_STATUS_IO_TIMEOUT
)) {
167 /* the registration timed out - good, send the next one */
169 if (state
->num_sends
== 4) {
171 c
->state
= SMBCLI_REQUEST_DONE
;
172 c
->status
= NT_STATUS_OK
;
175 if (state
->num_sends
== 3) {
176 state
->io
->in
.register_demand
= True
;
178 state
->req
= nbt_name_register_send(state
->nbtsock
, state
->io
);
179 if (state
->req
== NULL
) {
180 c
->state
= SMBCLI_REQUEST_ERROR
;
181 c
->status
= NT_STATUS_NO_MEMORY
;
183 state
->req
->async
.fn
= name_register_handler
;
184 state
->req
->async
.private = c
;
186 } else if (!NT_STATUS_IS_OK(status
)) {
187 c
->state
= SMBCLI_REQUEST_ERROR
;
190 c
->state
= SMBCLI_REQUEST_ERROR
;
191 c
->status
= NT_STATUS_CONFLICTING_ADDRESSES
;
192 DEBUG(3,("Name registration conflict from %s for %s<%02x> with ip %s - rcode %d\n",
193 state
->io
->out
.reply_from
,
194 state
->io
->out
.name
.name
,
195 state
->io
->out
.name
.type
,
196 state
->io
->out
.reply_addr
,
197 state
->io
->out
.rcode
));
201 if (c
->state
>= SMBCLI_REQUEST_DONE
&&
208 the async send call for a 4 stage name registration
210 struct composite_context
*nbt_name_register_bcast_send(struct nbt_name_socket
*nbtsock
,
211 struct nbt_name_register_bcast
*io
)
213 struct composite_context
*c
;
214 struct register_bcast_state
*state
;
216 c
= talloc_zero(nbtsock
, struct composite_context
);
217 if (c
== NULL
) goto failed
;
219 state
= talloc(c
, struct register_bcast_state
);
220 if (state
== NULL
) goto failed
;
222 state
->io
= talloc(state
, struct nbt_name_register
);
223 if (state
->io
== NULL
) goto failed
;
225 state
->io
->in
.name
= io
->in
.name
;
226 state
->io
->in
.dest_addr
= io
->in
.dest_addr
;
227 state
->io
->in
.address
= io
->in
.address
;
228 state
->io
->in
.nb_flags
= io
->in
.nb_flags
;
229 state
->io
->in
.register_demand
= False
;
230 state
->io
->in
.broadcast
= True
;
231 state
->io
->in
.ttl
= io
->in
.ttl
;
232 state
->io
->in
.timeout
= 1;
234 state
->num_sends
= 0;
235 state
->nbtsock
= nbtsock
;
237 state
->req
= nbt_name_register_send(nbtsock
, state
->io
);
238 if (state
->req
== NULL
) goto failed
;
240 state
->req
->async
.fn
= name_register_handler
;
241 state
->req
->async
.private = c
;
244 c
->state
= SMBCLI_REQUEST_SEND
;
245 c
->event_ctx
= nbtsock
->event_ctx
;
255 broadcast 4 part name register - recv
257 NTSTATUS
nbt_name_register_bcast_recv(struct composite_context
*c
)
260 status
= composite_wait(c
);
266 broadcast 4 part name register - sync interface
268 NTSTATUS
nbt_name_register_bcast(struct nbt_name_socket
*nbtsock
,
269 struct nbt_name_register_bcast
*io
)
271 struct composite_context
*c
= nbt_name_register_bcast_send(nbtsock
, io
);
272 return nbt_name_register_bcast_recv(c
);