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