2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-2003
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/>.
24 #include "nmbd/nmbd.h"
25 #include "lib/util/string_wrappers.h"
27 /* forward declarations */
28 static void wins_next_registration(struct response_record
*rrec
);
31 /****************************************************************************
32 Deal with a response packet when registering one of our names.
33 ****************************************************************************/
35 static void register_name_response(struct subnet_record
*subrec
,
36 struct response_record
*rrec
, struct packet_struct
*p
)
39 * If we are registering broadcast, then getting a response is an
40 * error - we do not have the name. If we are registering unicast,
41 * then we expect to get a response.
44 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
45 bool bcast
= nmb
->header
.nm_flags
.bcast
;
47 struct nmb_name
*question_name
= &rrec
->packet
->packet
.nmb
.question
.question_name
;
48 struct nmb_name
*answer_name
= &nmb
->answers
->rr_name
;
49 struct nmb_packet
*sent_nmb
= &rrec
->packet
->packet
.nmb
;
51 uint16_t nb_flags
= 0;
52 struct in_addr register_ip
;
55 putip(®ister_ip
,&sent_nmb
->additional
->rdata
[2]);
56 fstrcpy(reg_name
, inet_ntoa(register_ip
));
58 if (subrec
== unicast_subnet
) {
59 /* we know that this wins server is definitely alive - for the moment! */
60 wins_srv_alive(rrec
->packet
->ip
, register_ip
);
63 /* Sanity check. Ensure that the answer name in the incoming packet is the
64 same as the requested name in the outgoing packet. */
66 if(!question_name
|| !answer_name
) {
67 DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
68 question_name
? "question_name" : "answer_name" ));
72 if(!nmb_name_equal(question_name
, answer_name
)) {
73 DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n",
74 nmb_namestr(answer_name
), nmb_namestr(question_name
)));
80 * Special hack to cope with old Samba nmbd's.
81 * Earlier versions of Samba (up to 1.9.16p11) respond
82 * to a broadcast name registration of WORKGROUP<1b> when
83 * they should not. Hence, until these versions are gone,
84 * we should treat such errors as success for this particular
85 * case only. jallison@whistle.com.
88 #if 1 /* OLD_SAMBA_SERVER_HACK */
90 pull_ascii_nstring(ans_name
, sizeof(ans_name
), answer_name
->name
);
91 if((nmb
->header
.rcode
== ACT_ERR
) && strequal(lp_workgroup(), ans_name
) &&
92 (answer_name
->name_type
== 0x1b)) {
93 /* Pretend we did not get this. */
96 DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n",
97 nmb_namestr(answer_name
)));
100 #endif /* OLD_SAMBA_SERVER_HACK */
102 /* Someone else has the name. Log the problem. */
103 DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
104 nmb_namestr(answer_name
),
106 subrec
->subnet_name
, nmb
->header
.rcode
, inet_ntoa(p
->ip
)));
109 if (!ip_equal_v4(rrec
->packet
->ip
, p
->ip
)) {
110 DEBUG(5,("register_name_response: Ignoring WINS server response "
111 "from IP %s, for name %s. We sent to IP %s\n",
113 nmb_namestr(answer_name
),
114 inet_ntoa(rrec
->packet
->ip
)));
117 /* Unicast - check to see if the response allows us to have the name. */
118 if (nmb
->header
.opcode
== NMB_WACK_OPCODE
) {
119 /* WINS server is telling us to wait. Pretend we didn't get
120 the response but don't send out any more register requests. */
122 DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
123 inet_ntoa(p
->ip
), nmb_namestr(answer_name
), reg_name
));
125 rrec
->repeat_count
= 0;
126 /* How long we should wait for. */
127 rrec
->repeat_time
= p
->timestamp
+ nmb
->answers
->ttl
;
130 } else if (nmb
->header
.rcode
!= 0) {
131 /* Error code - we didn't get the name. */
134 DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
135 subrec
==unicast_subnet
?"WINS ":"",
137 nmb_namestr(answer_name
),
142 /* Get the data we need to pass to the success function. */
143 nb_flags
= get_nb_flags(nmb
->answers
->rdata
);
144 ttl
= nmb
->answers
->ttl
;
146 /* send off a registration for the next IP, if any */
147 wins_next_registration(rrec
);
151 DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
152 success
? "success" : "failure",
153 subrec
==unicast_subnet
?"WINS ":"",
154 nmb_namestr(answer_name
),
156 inet_ntoa(rrec
->packet
->ip
)));
159 /* Enter the registered name into the subnet name database before calling
160 the success function. */
161 standard_success_register(subrec
, rrec
->userdata
, answer_name
, nb_flags
, ttl
, register_ip
);
162 if( rrec
->success_fn
)
163 (*(register_name_success_function
)rrec
->success_fn
)(subrec
, rrec
->userdata
, answer_name
, nb_flags
, ttl
, register_ip
);
165 struct nmb_name qname
= *question_name
;
167 (*(register_name_fail_function
)rrec
->fail_fn
)(subrec
, rrec
, question_name
);
168 /* Remove the name. */
169 standard_fail_register( subrec
, &qname
);
172 /* Ensure we don't retry. */
173 remove_response_record(subrec
, rrec
);
176 /****************************************************************************
177 Deal with a timeout of a WINS registration request
178 ****************************************************************************/
180 static void wins_registration_timeout(struct subnet_record
*subrec
,
181 struct response_record
*rrec
)
183 struct userdata_struct
*userdata
= rrec
->userdata
;
184 struct nmb_packet
*sent_nmb
= &rrec
->packet
->packet
.nmb
;
185 struct nmb_name
*nmbname
= &sent_nmb
->question
.question_name
;
186 struct in_addr register_ip
;
189 putip(®ister_ip
,&sent_nmb
->additional
->rdata
[2]);
191 fstrcpy(src_addr
, inet_ntoa(register_ip
));
193 DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
194 inet_ntoa(rrec
->packet
->ip
), src_addr
));
196 /* mark it temporarily dead for this source address */
197 wins_srv_died(rrec
->packet
->ip
, register_ip
);
199 /* if we have some userdata then use that to work out what
200 wins server to try next */
202 const char *tag
= (const char *)userdata
->data
;
204 /* try the next wins server in our failover list for
206 rrec
->packet
->ip
= wins_srv_ip_tag(tag
, register_ip
);
209 /* if we have run out of wins servers for this tag then they
210 must all have timed out. We treat this as *success*, not
211 failure, and go into our standard name refresh mode. This
212 copes with all the wins servers being down */
213 if (wins_srv_is_dead(rrec
->packet
->ip
, register_ip
)) {
214 uint16_t nb_flags
= get_nb_flags(sent_nmb
->additional
->rdata
);
215 int ttl
= sent_nmb
->additional
->ttl
;
217 standard_success_register(subrec
, userdata
, nmbname
, nb_flags
, ttl
, register_ip
);
218 if(rrec
->success_fn
) {
219 (*(register_name_success_function
)rrec
->success_fn
)(subrec
,
227 /* send off a registration for the next IP, if any */
228 wins_next_registration(rrec
);
230 /* don't need to send this packet any more */
231 remove_response_record(subrec
, rrec
);
235 /* we will be moving to the next WINS server for this group,
236 send it immediately */
237 rrec
->repeat_count
= 2;
238 rrec
->repeat_time
= time(NULL
) + 1;
239 rrec
->in_expiration_processing
= False
;
241 DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
242 nmb_namestr(nmbname
), src_addr
, inet_ntoa(rrec
->packet
->ip
)));
244 /* notice that we don't remove the response record. This keeps
245 us trying to register with each of our failover wins servers */
248 /****************************************************************************
249 Deal with a timeout when registering one of our names.
250 ****************************************************************************/
252 static void register_name_timeout_response(struct subnet_record
*subrec
,
253 struct response_record
*rrec
)
256 * If we are registering unicast, then NOT getting a response is an
257 * error - we do not have the name. If we are registering broadcast,
258 * then we don't expect to get a response.
261 struct nmb_packet
*sent_nmb
= &rrec
->packet
->packet
.nmb
;
262 bool bcast
= sent_nmb
->header
.nm_flags
.bcast
;
263 bool success
= False
;
264 struct nmb_name
*question_name
= &sent_nmb
->question
.question_name
;
265 uint16_t nb_flags
= 0;
267 struct in_addr registered_ip
;
270 if(rrec
->num_msgs
== 0) {
271 /* Not receiving a message is success for broadcast registration. */
274 /* Pull the success values from the original request packet. */
275 nb_flags
= get_nb_flags(sent_nmb
->additional
->rdata
);
276 ttl
= sent_nmb
->additional
->ttl
;
277 putip(®istered_ip
,&sent_nmb
->additional
->rdata
[2]);
280 /* wins timeouts are special */
281 wins_registration_timeout(subrec
, rrec
);
285 DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
286 success
? "success" : "failure", nmb_namestr(question_name
), subrec
->subnet_name
));
288 /* Enter the registered name into the subnet name database before calling
289 the success function. */
290 standard_success_register(subrec
, rrec
->userdata
, question_name
, nb_flags
, ttl
, registered_ip
);
291 if( rrec
->success_fn
)
292 (*(register_name_success_function
)rrec
->success_fn
)(subrec
, rrec
->userdata
, question_name
, nb_flags
, ttl
, registered_ip
);
294 struct nmb_name qname
= *question_name
;
296 (*(register_name_fail_function
)rrec
->fail_fn
)(subrec
, rrec
, question_name
);
297 /* Remove the name. */
298 standard_fail_register( subrec
, &qname
);
301 /* Ensure we don't retry. */
302 remove_response_record(subrec
, rrec
);
305 /****************************************************************************
306 Initiate one multi-homed name registration packet.
307 ****************************************************************************/
309 static void multihomed_register_one(struct nmb_name
*nmbname
,
311 register_name_success_function success_fn
,
312 register_name_fail_function fail_fn
,
316 struct userdata_struct
*userdata
;
317 struct in_addr wins_ip
= wins_srv_ip_tag(tag
, ip
);
320 userdata
= (struct userdata_struct
*)SMB_MALLOC(sizeof(*userdata
) + strlen(tag
) + 1);
322 DEBUG(0,("Failed to allocate userdata structure!\n"));
325 ZERO_STRUCTP(userdata
);
326 userdata
->userdata_len
= strlen(tag
) + 1;
327 strlcpy(userdata
->data
, tag
, userdata
->userdata_len
);
329 fstrcpy(ip_str
, inet_ntoa(ip
));
331 DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
332 nmb_namestr(nmbname
), ip_str
, inet_ntoa(wins_ip
), tag
));
334 if (queue_register_multihomed_name(unicast_subnet
,
335 register_name_response
,
336 register_name_timeout_response
,
344 DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
345 nmb_namestr(nmbname
), inet_ntoa(ip
)));
351 /****************************************************************************
352 We have finished the registration of one IP and need to see if we have
353 any more IPs left to register with this group of wins server for this name.
354 ****************************************************************************/
356 static void wins_next_registration(struct response_record
*rrec
)
358 struct nmb_packet
*sent_nmb
= &rrec
->packet
->packet
.nmb
;
359 struct nmb_name
*nmbname
= &sent_nmb
->question
.question_name
;
360 uint16_t nb_flags
= get_nb_flags(sent_nmb
->additional
->rdata
);
361 struct userdata_struct
*userdata
= rrec
->userdata
;
363 struct in_addr last_ip
;
364 struct subnet_record
*subrec
;
366 putip(&last_ip
,&sent_nmb
->additional
->rdata
[2]);
369 /* it wasn't multi-homed */
373 tag
= (const char *)userdata
->data
;
375 for (subrec
= FIRST_SUBNET
; subrec
; subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
)) {
376 if (ip_equal_v4(last_ip
, subrec
->myip
)) {
377 subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
);
387 switch (sent_nmb
->header
.opcode
) {
388 case NMB_NAME_MULTIHOMED_REG_OPCODE
:
389 multihomed_register_one(nmbname
, nb_flags
, NULL
, NULL
, subrec
->myip
, tag
);
391 case NMB_NAME_REFRESH_OPCODE_8
:
392 queue_wins_refresh(nmbname
,
393 register_name_response
,
394 register_name_timeout_response
,
395 nb_flags
, subrec
->myip
, tag
);
400 /****************************************************************************
401 Try and register one of our names on the unicast subnet - multihomed.
402 ****************************************************************************/
404 static void multihomed_register_name(struct nmb_name
*nmbname
, uint16_t nb_flags
,
405 register_name_success_function success_fn
,
406 register_name_fail_function fail_fn
)
409 If we are adding a group name, we just send multiple
410 register name packets to the WINS server (this is an
413 If we are adding a unique name, We need first to add
414 our names to the unicast subnet namelist. This is
415 because when a WINS server receives a multihomed
416 registration request, the first thing it does is to
417 send a name query to the registering machine, to see
418 if it has put the name in it's local namelist.
419 We need the name there so the query response code in
420 nmbd_incomingrequests.c will find it.
422 We are adding this name prematurely (we don't really
423 have it yet), but as this is on the unicast subnet
424 only we will get away with this (only the WINS server
425 will ever query names from us on this subnet).
429 struct subnet_record
*subrec
;
431 struct in_addr
*ip_list
;
434 for(subrec
= FIRST_SUBNET
; subrec
; subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
) )
437 if((ip_list
= SMB_MALLOC_ARRAY(struct in_addr
, num_ips
))==NULL
) {
438 DEBUG(0,("multihomed_register_name: malloc fail !\n"));
442 for (subrec
= FIRST_SUBNET
, i
= 0;
444 subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
), i
++ ) {
445 ip_list
[i
] = subrec
->myip
;
448 pull_ascii_nstring(name
, sizeof(name
), nmbname
->name
);
449 add_name_to_subnet(unicast_subnet
, name
, nmbname
->name_type
,
450 nb_flags
, lp_max_ttl(), SELF_NAME
,
453 /* get the list of wins tags - we try to register for each of them */
454 wins_tags
= wins_srv_tags();
456 /* Now try and register the name for each wins tag. Note that
457 at this point we only register our first IP with each wins
458 group. We will register the rest from
459 wins_next_registration() when we get the reply for this
460 one. That follows the way W2K does things (tridge)
462 for (t
=0; wins_tags
&& wins_tags
[t
]; t
++) {
463 multihomed_register_one(nmbname
, nb_flags
,
469 wins_srv_tags_free(wins_tags
);
474 /****************************************************************************
475 Try and register one of our names.
476 ****************************************************************************/
478 void register_name(struct subnet_record
*subrec
,
479 const char *name
, int type
, uint16_t nb_flags
,
480 register_name_success_function success_fn
,
481 register_name_fail_function fail_fn
,
482 struct userdata_struct
*userdata
)
484 struct nmb_name nmbname
;
486 size_t converted_size
;
489 converted_size
= push_ascii_nstring(nname
, name
);
490 if (converted_size
!= (size_t)-1) {
492 make_nmb_name(&nmbname
, name
, type
);
493 } else if (errno
== E2BIG
) {
495 * Name converted to CH_DOS is too large.
498 char *converted_str_dos
= NULL
;
499 char *converted_str_unix
= NULL
;
504 ok
= convert_string_talloc(talloc_tos(),
512 DEBUG(0,("register_name: NetBIOS name %s cannot be "
513 "converted. Failing to register name.\n",
519 * As it's now CH_DOS codepage
520 * we truncate by writing '\0' at
521 * MAX_NETBIOSNAME_LEN-1 and then
522 * convert back to CH_UNIX which we
523 * need for the make_nmb_name() call.
525 if (converted_size
>= MAX_NETBIOSNAME_LEN
) {
526 converted_str_dos
[MAX_NETBIOSNAME_LEN
-1] = '\0';
529 ok
= convert_string_talloc(talloc_tos(),
533 strlen(converted_str_dos
)+1,
537 DEBUG(0,("register_name: NetBIOS name %s cannot be "
538 "converted back to CH_UNIX. "
539 "Failing to register name.\n",
541 TALLOC_FREE(converted_str_dos
);
545 make_nmb_name(&nmbname
, converted_str_unix
, type
);
547 TALLOC_FREE(converted_str_dos
);
548 TALLOC_FREE(converted_str_unix
);
551 * Generic conversion error. Fail to register.
553 DEBUG(0,("register_name: NetBIOS name %s cannot be "
554 "converted (%s). Failing to register name.\n",
555 name
, strerror(errno
)));
559 /* Always set the NB_ACTIVE flag on the name we are
560 registering. Doesn't make sense without it.
563 nb_flags
|= NB_ACTIVE
;
565 if (subrec
== unicast_subnet
) {
566 /* we now always do multi-homed registration if we are
567 registering to a WINS server. This copes much
568 better with complex WINS setups */
569 multihomed_register_name(&nmbname
, nb_flags
,
570 success_fn
, fail_fn
);
574 if (queue_register_name(subrec
,
575 register_name_response
,
576 register_name_timeout_response
,
582 DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
583 nmb_namestr(&nmbname
)));
587 /****************************************************************************
588 Try and refresh one of our names. This is *only* called for WINS refresh
589 ****************************************************************************/
591 void wins_refresh_name(struct name_record
*namerec
)
596 /* get the list of wins tags - we try to refresh for each of them */
597 wins_tags
= wins_srv_tags();
599 for (t
=0; wins_tags
&& wins_tags
[t
]; t
++) {
600 queue_wins_refresh(&namerec
->name
,
601 register_name_response
,
602 register_name_timeout_response
,
603 namerec
->data
.nb_flags
,
604 namerec
->data
.ip
[0], wins_tags
[t
]);
607 wins_srv_tags_free(wins_tags
);