1/* 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 7 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. 12 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. 17 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. 21 22*/ 23 24#include "includes.h" 25 26extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ 27 28/******************************************************************* 29 Utility function to add a name to the unicast subnet, or add in 30 our IP address if it already exists. 31******************************************************************/ 32 33void insert_permanent_name_into_unicast( struct subnet_record *subrec, 34 struct nmb_name *nmbname, uint16 nb_type ) 35{ 36 unstring name; 37 struct name_record *namerec; 38 39 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) { 40 pull_ascii_nstring(name, sizeof(name), nmbname->name); 41 /* The name needs to be created on the unicast subnet. */ 42 (void)add_name_to_subnet( unicast_subnet, name, 43 nmbname->name_type, nb_type, 44 PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip); 45 } else { 46 /* The name already exists on the unicast subnet. Add our local 47 IP for the given broadcast subnet to the name. */ 48 add_ip_to_name_record( namerec, subrec->myip); 49 } 50} 51 52/******************************************************************* 53 Utility function to remove a name from the unicast subnet. 54******************************************************************/ 55 56static void remove_permanent_name_from_unicast( struct subnet_record *subrec, 57 struct nmb_name *nmbname ) 58{ 59 struct name_record *namerec; 60 61 if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) { 62 /* Remove this broadcast subnet IP address from the name. */ 63 remove_ip_from_name_record( namerec, subrec->myip); 64 if(namerec->data.num_ips == 0) 65 remove_name_from_namelist( unicast_subnet, namerec); 66 } 67} 68 69/******************************************************************* 70 Utility function always called to set our workgroup and server 71 state back to potential browser, or none. 72******************************************************************/ 73 74static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name, 75 BOOL force_new_election ) 76{ 77 struct work_record *work; 78 struct server_record *servrec; 79 struct nmb_name nmbname; 80 81 if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) { 82 DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \ 83subnet %s.\n", workgroup_name, subrec->subnet_name )); 84 return; 85 } 86 87 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { 88 DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \ 89in workgroup %s on subnet %s\n", 90 global_myname(), work->work_group, subrec->subnet_name)); 91 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; 92 return; 93 } 94 95 /* Update our server status - remove any master flag and replace 96 it with the potential browser flag. */ 97 servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER; 98 servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0); 99 100 /* Tell the namelist writer to write out a change. */ 101 subrec->work_changed = True; 102 103 /* Reset our election flags. */ 104 work->ElectionCriterion &= ~0x4; 105 106 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; 107 108 /* Forget who the local master browser was for 109 this workgroup. */ 110 111 set_workgroup_local_master_browser_name( work, ""); 112 113 /* 114 * Ensure the IP address of this subnet is not registered as one 115 * of the IP addresses of the WORKGROUP<1d> name on the unicast 116 * subnet. This undoes what we did below when we became a local 117 * master browser. 118 */ 119 120 make_nmb_name(&nmbname, work->work_group, 0x1d); 121 122 remove_permanent_name_from_unicast( subrec, &nmbname); 123 124 if(force_new_election) 125 work->needelection = True; 126} 127 128/******************************************************************* 129 Unbecome the local master browser name release success function. 130******************************************************************/ 131 132static void unbecome_local_master_success(struct subnet_record *subrec, 133 struct userdata_struct *userdata, 134 struct nmb_name *released_name, 135 struct in_addr released_ip) 136{ 137 BOOL force_new_election = False; 138 unstring relname; 139 140 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); 141 142 DEBUG(3,("unbecome_local_master_success: released name %s.\n", 143 nmb_namestr(released_name))); 144 145 /* Now reset the workgroup and server state. */ 146 pull_ascii_nstring(relname, sizeof(relname), released_name->name); 147 reset_workgroup_state( subrec, relname, force_new_election ); 148 149 if( DEBUGLVL( 0 ) ) { 150 dbgtext( "*****\n\n" ); 151 dbgtext( "Samba name server %s ", global_myname() ); 152 dbgtext( "has stopped being a local master browser " ); 153 dbgtext( "for workgroup %s ", relname ); 154 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); 155 } 156 157} 158 159/******************************************************************* 160 Unbecome the local master browser name release fail function. 161******************************************************************/ 162 163static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec, 164 struct nmb_name *fail_name) 165{ 166 struct name_record *namerec; 167 struct userdata_struct *userdata = rrec->userdata; 168 BOOL force_new_election = False; 169 unstring failname; 170 171 memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); 172 173 DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \ 174Removing from namelist anyway.\n", nmb_namestr(fail_name))); 175 176 /* Do it anyway. */ 177 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); 178 if(namerec) 179 remove_name_from_namelist(subrec, namerec); 180 181 /* Now reset the workgroup and server state. */ 182 pull_ascii_nstring(failname, sizeof(failname), fail_name->name); 183 reset_workgroup_state( subrec, failname, force_new_election ); 184 185 if( DEBUGLVL( 0 ) ) { 186 dbgtext( "*****\n\n" ); 187 dbgtext( "Samba name server %s ", global_myname() ); 188 dbgtext( "has stopped being a local master browser " ); 189 dbgtext( "for workgroup %s ", failname ); 190 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); 191 } 192} 193 194/******************************************************************* 195 Utility function to remove the WORKGROUP<1d> name. 196******************************************************************/ 197 198static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name, 199 BOOL force_new_election) 200{ 201 struct nmb_name nmbname; 202 struct name_record *namerec; 203 204 make_nmb_name(&nmbname, workgroup_name, 0x1d); 205 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) { 206 struct userdata_struct *userdata; 207 size_t size = sizeof(struct userdata_struct) + sizeof(BOOL); 208 209 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) { 210 DEBUG(0,("release_1d_name: malloc fail.\n")); 211 return; 212 } 213 214 userdata->copy_fn = NULL; 215 userdata->free_fn = NULL; 216 userdata->userdata_len = sizeof(BOOL); 217 memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL)); 218 219 release_name(subrec, namerec, 220 unbecome_local_master_success, 221 unbecome_local_master_fail, 222 userdata); 223 224 zero_free(userdata, size); 225 } 226} 227 228/******************************************************************* 229 Unbecome the local master browser MSBROWSE name release success function. 230******************************************************************/ 231 232static void release_msbrowse_name_success(struct subnet_record *subrec, 233 struct userdata_struct *userdata, 234 struct nmb_name *released_name, 235 struct in_addr released_ip) 236{ 237 DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.", 238 nmb_namestr(released_name), subrec->subnet_name )); 239 240 /* Remove the permanent MSBROWSE name added into the unicast subnet. */ 241 remove_permanent_name_from_unicast( subrec, released_name); 242} 243 244/******************************************************************* 245 Unbecome the local master browser MSBROWSE name release fail function. 246******************************************************************/ 247 248static void release_msbrowse_name_fail( struct subnet_record *subrec, 249 struct response_record *rrec, 250 struct nmb_name *fail_name) 251{ 252 struct name_record *namerec; 253 254 DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.", 255 nmb_namestr(fail_name), subrec->subnet_name )); 256 257 /* Release the name anyway. */ 258 namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); 259 if(namerec) 260 remove_name_from_namelist(subrec, namerec); 261 262 /* Remove the permanent MSBROWSE name added into the unicast subnet. */ 263 remove_permanent_name_from_unicast( subrec, fail_name); 264} 265 266/******************************************************************* 267 Unbecome the local master browser. If force_new_election is true, restart 268 the election process after we've unbecome the local master. 269******************************************************************/ 270 271void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work, 272 BOOL force_new_election) 273{ 274 struct name_record *namerec; 275 struct nmb_name nmbname; 276 277 /* Sanity check. */ 278 279 DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \ 280on subnet %s\n",work->work_group, subrec->subnet_name)); 281 282 if(find_server_in_workgroup( work, global_myname()) == NULL) { 283 DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \ 284in workgroup %s on subnet %s\n", 285 global_myname(), work->work_group, subrec->subnet_name)); 286 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; 287 return; 288 } 289 290 /* Set the state to unbecoming. */ 291 work->mst_state = MST_UNBECOMING_MASTER; 292 293 /* 294 * Release the WORKGROUP<1d> name asap to allow another machine to 295 * claim it. 296 */ 297 298 release_1d_name( subrec, work->work_group, force_new_election); 299 300 /* Deregister any browser names we may have. */ 301 make_nmb_name(&nmbname, MSBROWSE, 0x1); 302 if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) { 303 release_name(subrec, namerec, 304 release_msbrowse_name_success, 305 release_msbrowse_name_fail, 306 NULL); 307 } 308 309 /* 310 * Ensure we have sent and processed these release packets 311 * before returning - we don't want to process any election 312 * packets before dealing with the 1d release. 313 */ 314 315 retransmit_or_expire_response_records(time(NULL)); 316} 317 318/**************************************************************************** 319 Success in registering the WORKGROUP<1d> name. 320 We are now *really* a local master browser. 321 ****************************************************************************/ 322 323static void become_local_master_stage2(struct subnet_record *subrec, 324 struct userdata_struct *userdata, 325 struct nmb_name *registered_name, 326 uint16 nb_flags, 327 int ttl, struct in_addr registered_ip) 328{ 329 int i = 0; 330 struct server_record *sl; 331 struct work_record *work; 332 struct server_record *servrec; 333 unstring regname; 334 335 pull_ascii_nstring(regname, sizeof(regname), registered_name->name); 336 work = find_workgroup_on_subnet( subrec, regname); 337 338 if(!work) { 339 DEBUG(0,("become_local_master_stage2: Error - cannot find \ 340workgroup %s on subnet %s\n", regname, subrec->subnet_name)); 341 return; 342 } 343 344 if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { 345 DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \ 346in workgroup %s on subnet %s\n", 347 global_myname(), regname, subrec->subnet_name)); 348 work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; 349 return; 350 } 351 352 DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \ 353on subnet %s\n", work->work_group, subrec->subnet_name)); 354 355 work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */ 356 357 /* update our server status */ 358 servrec->serv.type |= SV_TYPE_MASTER_BROWSER; 359 servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER; 360 361 /* Tell the namelist writer to write out a change. */ 362 subrec->work_changed = True; 363 364 /* Add this name to the workgroup as local master browser. */ 365 set_workgroup_local_master_browser_name( work, global_myname()); 366 367 /* Count the number of servers we have on our list. If it's 368 less than 10 (just a heuristic) request the servers 369 to announce themselves. 370 */ 371 for( sl = work->serverlist; sl != NULL; sl = sl->next) 372 i++; 373 374 if (i < 10) { 375 /* Ask all servers on our local net to announce to us. */ 376 broadcast_announce_request(subrec, work); 377 } 378 379 /* 380 * Now we are a local master on a broadcast subnet, we need to add 381 * the WORKGROUP<1d> name to the unicast subnet so that we can answer 382 * unicast requests sent to this name. We can create this name directly on 383 * the unicast subnet as a WINS server always returns true when registering 384 * this name, and discards the registration. We use the number of IP 385 * addresses registered to this name as a reference count, as we 386 * remove this broadcast subnet IP address from it when we stop becoming a local 387 * master browser for this broadcast subnet. 388 */ 389 390 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); 391 392 /* Reset the announce master browser timer so that we try and tell a domain 393 master browser as soon as possible that we are a local master browser. */ 394 reset_announce_timer(); 395 396 if( DEBUGLVL( 0 ) ) { 397 dbgtext( "*****\n\n" ); 398 dbgtext( "Samba name server %s ", global_myname() ); 399 dbgtext( "is now a local master browser " ); 400 dbgtext( "for workgroup %s ", work->work_group ); 401 dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); 402 } 403} 404 405/**************************************************************************** 406 Failed to register the WORKGROUP<1d> name. 407 ****************************************************************************/ 408 409static void become_local_master_fail2(struct subnet_record *subrec, 410 struct response_record *rrec, 411 struct nmb_name *fail_name) 412{ 413 unstring failname; 414 struct work_record *work; 415 416 DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \ 417Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name)); 418 419 pull_ascii_nstring(failname, sizeof(failname), fail_name->name); 420 work = find_workgroup_on_subnet( subrec, failname); 421 422 if(!work) { 423 DEBUG(0,("become_local_master_fail2: Error - cannot find \ 424workgroup %s on subnet %s\n", failname, subrec->subnet_name)); 425 return; 426 } 427 428 /* Roll back all the way by calling unbecome_local_master_browser(). */ 429 unbecome_local_master_browser(subrec, work, False); 430} 431 432/**************************************************************************** 433 Success in registering the MSBROWSE name. 434 ****************************************************************************/ 435 436static void become_local_master_stage1(struct subnet_record *subrec, 437 struct userdata_struct *userdata, 438 struct nmb_name *registered_name, 439 uint16 nb_flags, 440 int ttl, struct in_addr registered_ip) 441{ 442 char *work_name = userdata->data; 443 struct work_record *work = find_workgroup_on_subnet( subrec, work_name); 444 445 if(!work) { 446 DEBUG(0,("become_local_master_stage1: Error - cannot find \ 447 %s on subnet %s\n", work_name, subrec->subnet_name)); 448 return; 449 } 450 451 DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n", 452 work->work_group)); 453 454 work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */ 455 456 /* 457 * We registered the MSBROWSE name on a broadcast subnet, now need to add 458 * the MSBROWSE name to the unicast subnet so that we can answer 459 * unicast requests sent to this name. We create this name directly on 460 * the unicast subnet. 461 */ 462 463 insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); 464 465 /* Attempt to register the WORKGROUP<1d> name. */ 466 register_name(subrec, work->work_group,0x1d,samba_nb_type, 467 become_local_master_stage2, 468 become_local_master_fail2, 469 NULL); 470} 471 472/**************************************************************************** 473 Failed to register the MSBROWSE name. 474 ****************************************************************************/ 475 476static void become_local_master_fail1(struct subnet_record *subrec, 477 struct response_record *rrec, 478 struct nmb_name *fail_name) 479{ 480 char *work_name = rrec->userdata->data; 481 struct work_record *work = find_workgroup_on_subnet(subrec, work_name); 482 483 if(!work) { 484 DEBUG(0,("become_local_master_fail1: Error - cannot find \ 485workgroup %s on subnet %s\n", work_name, subrec->subnet_name)); 486 return; 487 } 488 489 if(find_server_in_workgroup(work, global_myname()) == NULL) { 490 DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \ 491in workgroup %s on subnet %s\n", 492 global_myname(), work->work_group, subrec->subnet_name)); 493 return; 494 } 495 496 reset_workgroup_state( subrec, work->work_group, False ); 497 498 DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \ 499workgroup %s on subnet %s. Couldn't register name %s.\n", 500 work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); 501} 502 503/****************************************************************** 504 Become the local master browser on a subnet. 505 This gets called if we win an election on this subnet. 506 507 Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1. 508 Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>. 509 Stage 3: mst_state was MST_MSB - go to MST_BROWSER. 510******************************************************************/ 511 512void become_local_master_browser(struct subnet_record *subrec, struct work_record *work) 513{ 514 struct userdata_struct *userdata; 515 size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1; 516 517 /* Sanity check. */ 518 if (!lp_local_master()) { 519 DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n")); 520 return; 521 } 522 523 if(!AM_POTENTIAL_MASTER_BROWSER(work)) { 524 DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n", 525 work->mst_state )); 526 return; 527 } 528 529 if(find_server_in_workgroup( work, global_myname()) == NULL) { 530 DEBUG(0,("become_local_master_browser: Error - cannot find server %s \ 531in workgroup %s on subnet %s\n", 532 global_myname(), work->work_group, subrec->subnet_name)); 533 return; 534 } 535 536 DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \ 537%s on subnet %s\n", work->work_group, subrec->subnet_name)); 538 539 DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n")); 540 work->mst_state = MST_BACKUP; /* an election win was successful */ 541 542 work->ElectionCriterion |= 0x5; 543 544 /* Tell the namelist writer to write out a change. */ 545 subrec->work_changed = True; 546 547 /* Setup the userdata_struct. */ 548 if((userdata = (struct userdata_struct *)SMB_MALLOC(size)) == NULL) { 549 DEBUG(0,("become_local_master_browser: malloc fail.\n")); 550 return; 551 } 552 553 userdata->copy_fn = NULL; 554 userdata->free_fn = NULL; 555 userdata->userdata_len = strlen(work->work_group)+1; 556 overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); 557 558 /* Register the special browser group name. */ 559 register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP, 560 become_local_master_stage1, 561 become_local_master_fail1, 562 userdata); 563 564 zero_free(userdata, size); 565} 566 567/*************************************************************** 568 Utility function to set the local master browser name. Does 569 some sanity checking as old versions of Samba seem to sometimes 570 say that the master browser name for a workgroup is the same 571 as the workgroup name. 572****************************************************************/ 573 574void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname) 575{ 576 DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \ 577for workgroup %s.\n", newname, work->work_group )); 578 579#if 0 580 /* 581 * Apparently some sites use the workgroup name as the local 582 * master browser name. Arrrrggghhhhh ! (JRA). 583 */ 584 if(strequal( work->work_group, newname)) 585 { 586 DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \ 587local_master_browser_name for workgroup %s to workgroup name.\n", 588 work->work_group )); 589 return; 590 } 591#endif 592 593 unstrcpy(work->local_master_browser_name, newname); 594} 595