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-1998 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 BOOL found_lm_clients; 27 28#if 0 29 30/* XXXX note: This function is currently unsuitable for use, as it 31 does not properly check that a server is in a fit state to become 32 a backup browser before asking it to be one. 33 The code is left here to be worked on at a later date. 34*/ 35 36/**************************************************************************** 37Tell a server to become a backup browser 38**************************************************************************/ 39 40void tell_become_backup(void) 41{ 42 struct subnet_record *subrec; 43 for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) 44 { 45 struct work_record *work; 46 for (work = subrec->workgrouplist; work; work = work->next) 47 { 48 struct server_record *servrec; 49 int num_servers = 0; 50 int num_backups = 0; 51 52 for (servrec = work->serverlist; servrec; servrec = servrec->next) 53 { 54 num_servers++; 55 56 if (is_myname(servrec->serv.name)) 57 continue; 58 59 if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER) 60 { 61 num_backups++; 62 continue; 63 } 64 65 if (servrec->serv.type & SV_TYPE_MASTER_BROWSER) 66 continue; 67 68 if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER)) 69 continue; 70 71 DEBUG(3,("num servers: %d num backups: %d\n", 72 num_servers, num_backups)); 73 74 /* make first server a backup server. thereafter make every 75 tenth server a backup server */ 76 if (num_backups != 0 && (num_servers+9) / num_backups > 10) 77 continue; 78 79 DEBUG(2,("sending become backup to %s %s for %s\n", 80 servrec->serv.name, inet_ntoa(subrec->bcast_ip), 81 work->work_group)); 82 83 /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ 84 do_announce_request(servrec->serv.name, work->work_group, 85 ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip); 86 } 87 } 88 } 89} 90#endif 91 92/******************************************************************* 93 Process an incoming host announcement packet. 94*******************************************************************/ 95 96void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) 97{ 98 struct dgram_packet *dgram = &p->packet.dgram; 99 int ttl = IVAL(buf,1)/1000; 100 unstring announce_name; 101 uint32 servertype = IVAL(buf,23); 102 fstring comment; 103 struct work_record *work; 104 struct server_record *servrec; 105 unstring work_name; 106 unstring source_name; 107 108 START_PROFILE(host_announce); 109 110 pull_ascii_fstring(comment, buf+31); 111 comment[42] = 0; 112 113 pull_ascii_nstring(announce_name, sizeof(announce_name), buf+5); 114 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); 115 116 DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \ 117%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), 118 nmb_namestr(&dgram->dest_name),announce_name)); 119 120 DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n", 121 ttl, servertype,comment)); 122 123 /* Filter servertype to remove impossible bits. */ 124 servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); 125 126 /* A host announcement must be sent to the name WORKGROUP<1d>. */ 127 if(dgram->dest_name.name_type != 0x1d) { 128 DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \ 129(was %02x) should be 0x1d. Allowing packet anyway.\n", 130 inet_ntoa(p->ip), dgram->dest_name.name_type)); 131 /* Change it so it was. */ 132 dgram->dest_name.name_type = 0x1d; 133 } 134 135 /* For a host announce the workgroup name is the destination name. */ 136 pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name); 137 138 /* 139 * Syntax servers version 5.1 send HostAnnounce packets to 140 * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> 141 * instead of WORKGROUP<1d> name. So to fix this we check if 142 * the workgroup name is our own name, and if so change it 143 * to be our primary workgroup name. 144 */ 145 146 if(strequal(work_name, global_myname())) 147 unstrcpy(work_name,lp_workgroup()); 148 149 /* 150 * We are being very agressive here in adding a workgroup 151 * name on the basis of a host announcing itself as being 152 * in that workgroup. Maybe we should wait for the workgroup 153 * announce instead ? JRA. 154 */ 155 156 work = find_workgroup_on_subnet(subrec, work_name); 157 158 if(servertype != 0) { 159 if (work ==NULL ) { 160 /* We have no record of this workgroup. Add it. */ 161 if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) 162 goto done; 163 } 164 165 if((servrec = find_server_in_workgroup( work, announce_name))==NULL) { 166 /* If this server is not already in the workgroup, add it. */ 167 create_server_on_workgroup(work, announce_name, 168 servertype|SV_TYPE_LOCAL_LIST_ONLY, 169 ttl, comment); 170 } else { 171 /* Update the record. */ 172 servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; 173 update_server_ttl( servrec, ttl); 174 fstrcpy(servrec->serv.comment,comment); 175 } 176 } else { 177 /* 178 * This server is announcing it is going down. Remove it from the 179 * workgroup. 180 */ 181 if(!is_myname(announce_name) && (work != NULL) && 182 ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) { 183 remove_server_from_workgroup( work, servrec); 184 } 185 } 186 187 subrec->work_changed = True; 188done: 189 190 END_PROFILE(host_announce); 191} 192 193/******************************************************************* 194 Process an incoming WORKGROUP announcement packet. 195*******************************************************************/ 196 197void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) 198{ 199 struct dgram_packet *dgram = &p->packet.dgram; 200 int ttl = IVAL(buf,1)/1000; 201 unstring workgroup_announce_name; 202 unstring master_name; 203 uint32 servertype = IVAL(buf,23); 204 struct work_record *work; 205 unstring source_name; 206 unstring dest_name; 207 208 START_PROFILE(workgroup_announce); 209 210 pull_ascii_nstring(workgroup_announce_name,sizeof(workgroup_announce_name),buf+5); 211 pull_ascii_nstring(master_name,sizeof(master_name),buf+31); 212 pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name); 213 pull_ascii_nstring(dest_name,sizeof(dest_name),dgram->dest_name.name); 214 215 DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \ 216%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip), 217 nmb_namestr(&dgram->dest_name),workgroup_announce_name)); 218 219 DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n", 220 ttl, servertype, master_name)); 221 222 /* Workgroup announcements must only go to the MSBROWSE name. */ 223 if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) { 224 DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n", 225 inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); 226 goto done; 227 } 228 229 if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) { 230 /* We have no record of this workgroup. Add it. */ 231 if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL) 232 goto done; 233 } else { 234 /* Update the workgroup death_time. */ 235 update_workgroup_ttl(work, ttl); 236 } 237 238 if(*work->local_master_browser_name == '\0') { 239 /* Set the master browser name. */ 240 set_workgroup_local_master_browser_name( work, master_name ); 241 } 242 243 subrec->work_changed = True; 244 245done: 246 247 END_PROFILE(workgroup_announce); 248} 249 250/******************************************************************* 251 Process an incoming local master browser announcement packet. 252*******************************************************************/ 253 254void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) 255{ 256 struct dgram_packet *dgram = &p->packet.dgram; 257 int ttl = IVAL(buf,1)/1000; 258 unstring server_name; 259 uint32 servertype = IVAL(buf,23); 260 fstring comment; 261 unstring work_name; 262 struct work_record *work; 263 struct server_record *servrec; 264 unstring source_name; 265 266 START_PROFILE(local_master_announce); 267 268 pull_ascii_nstring(server_name,sizeof(server_name),buf+5); 269 pull_ascii_fstring(comment, buf+31); 270 comment[42] = 0; 271 pull_ascii_nstring(source_name, sizeof(source_name), dgram->source_name.name); 272 pull_ascii_nstring(work_name, sizeof(work_name), dgram->dest_name.name); 273 274 DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \ 275%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), 276 nmb_namestr(&dgram->dest_name),server_name)); 277 278 DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n", 279 ttl, servertype, comment)); 280 281 /* A local master announcement must be sent to the name WORKGROUP<1e>. */ 282 if(dgram->dest_name.name_type != 0x1e) { 283 DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \ 284(was %02x) should be 0x1e. Ignoring packet.\n", 285 inet_ntoa(p->ip), dgram->dest_name.name_type)); 286 goto done; 287 } 288 289 /* Filter servertype to remove impossible bits. */ 290 servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); 291 292 /* For a local master announce the workgroup name is the destination name. */ 293 294 if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) { 295 /* Don't bother adding if it's a local master release announce. */ 296 if(servertype == 0) 297 goto done; 298 299 /* We have no record of this workgroup. Add it. */ 300 if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) 301 goto done; 302 } 303 304 /* If we think we're the local master browser for this workgroup, 305 we should never have got this packet. We don't see our own 306 packets. 307 */ 308 if(AM_LOCAL_MASTER_BROWSER(work)) { 309 DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \ 310a local master browser for workgroup %s and we think we are master. Forcing election.\n", 311 server_name, inet_ntoa(p->ip), work_name)); 312 313 /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when 314 they have become a local master browser once, they will never 315 stop sending local master announcements. To fix this we send 316 them a reset browser packet, with level 0x2 on the __SAMBA__ 317 name that only they should be listening to. */ 318 319 send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip); 320 321 /* We should demote ourself and force an election. */ 322 323 unbecome_local_master_browser( subrec, work, True); 324 325 /* The actual election requests are handled in nmbd_election.c */ 326 goto done; 327 } 328 329 /* Find the server record on this workgroup. If it doesn't exist, add it. */ 330 331 if(servertype != 0) { 332 if((servrec = find_server_in_workgroup( work, server_name))==NULL) { 333 /* If this server is not already in the workgroup, add it. */ 334 create_server_on_workgroup(work, server_name, 335 servertype|SV_TYPE_LOCAL_LIST_ONLY, 336 ttl, comment); 337 } else { 338 /* Update the record. */ 339 servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; 340 update_server_ttl(servrec, ttl); 341 fstrcpy(servrec->serv.comment,comment); 342 } 343 344 set_workgroup_local_master_browser_name( work, server_name ); 345 } else { 346 /* 347 * This server is announcing it is going down. Remove it from the 348 * workgroup. 349 */ 350 if(!is_myname(server_name) && (work != NULL) && 351 ((servrec = find_server_in_workgroup( work, server_name))!=NULL)) { 352 remove_server_from_workgroup( work, servrec); 353 } 354 } 355 356 subrec->work_changed = True; 357done: 358 359 END_PROFILE(local_master_announce); 360} 361 362/******************************************************************* 363 Process a domain master announcement frame. 364 Domain master browsers receive these from local masters. The Domain 365 master should then issue a sync with the local master, asking for 366 that machines local server list. 367******************************************************************/ 368 369void process_master_browser_announce(struct subnet_record *subrec, 370 struct packet_struct *p,char *buf) 371{ 372 unstring local_master_name; 373 struct work_record *work; 374 struct browse_cache_record *browrec; 375 376 START_PROFILE(master_browser_announce); 377 378 pull_ascii_nstring(local_master_name,sizeof(local_master_name),buf); 379 380 DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n", 381 local_master_name, inet_ntoa(p->ip))); 382 383 if (!lp_domain_master()) { 384 DEBUG(0,("process_master_browser_announce: Not configured as domain \ 385master - ignoring master announce.\n")); 386 goto done; 387 } 388 389 if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) { 390 DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n", 391 lp_workgroup(), subrec->subnet_name)); 392 goto done; 393 } 394 395 if(!AM_DOMAIN_MASTER_BROWSER(work)) { 396 DEBUG(0,("process_master_browser_announce: Local master announce made to us from \ 397%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip))); 398 goto done; 399 } 400 401 /* Add this host as a local master browser entry on the browse lists. 402 This causes a sync request to be made to it at a later date. 403 */ 404 405 if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) { 406 /* Add it. */ 407 create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip); 408 } else { 409 update_browser_death_time(browrec); 410 } 411 412done: 413 414 END_PROFILE(master_browser_announce); 415} 416 417/******************************************************************* 418 Process an incoming LanMan host announcement packet. 419*******************************************************************/ 420 421void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) 422{ 423 struct dgram_packet *dgram = &p->packet.dgram; 424 uint32 servertype = IVAL(buf,1); 425 int osmajor=CVAL(buf,5); /* major version of node software */ 426 int osminor=CVAL(buf,6); /* minor version of node software */ 427 int ttl = SVAL(buf,7); 428 unstring announce_name; 429 struct work_record *work; 430 struct server_record *servrec; 431 unstring work_name; 432 unstring source_name; 433 fstring comment; 434 char *s = buf+9; 435 436 START_PROFILE(lm_host_announce); 437 s = skip_string(s,1); 438 pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE); 439 440 pull_ascii_nstring(announce_name,sizeof(announce_name),buf+9); 441 pull_ascii_nstring(source_name,sizeof(source_name),dgram->source_name.name); 442 /* For a LanMan host announce the workgroup name is the destination name. */ 443 pull_ascii_nstring(work_name,sizeof(work_name),dgram->dest_name.name); 444 445 DEBUG(3,("process_lm_host_announce: LM Announcement from %s IP %s to \ 446%s for server %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), 447 nmb_namestr(&dgram->dest_name),announce_name)); 448 449 DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n", 450 osmajor, osminor, ttl, servertype,comment)); 451 452 if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) { 453 DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \ 454originate from OS/2 Warp client. Ignoring packet.\n")); 455 /* Could have been from a Windows machine (with its LM Announce enabled), 456 or a Samba server. Then don't disrupt the current browse list. */ 457 goto done; 458 } 459 460 /* Filter servertype to remove impossible bits. */ 461 servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); 462 463 /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */ 464 if(dgram->dest_name.name_type != 0x00) { 465 DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \ 466(was %02x) should be 0x00. Allowing packet anyway.\n", 467 inet_ntoa(p->ip), dgram->dest_name.name_type)); 468 /* Change it so it was. */ 469 dgram->dest_name.name_type = 0x00; 470 } 471 472 /* 473 * Syntax servers version 5.1 send HostAnnounce packets to 474 * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> 475 * instead of WORKGROUP<1d> name. So to fix this we check if 476 * the workgroup name is our own name, and if so change it 477 * to be our primary workgroup name. This code is probably 478 * not needed in the LanMan announce code, but it won't hurt. 479 */ 480 481 if(strequal(work_name, global_myname())) 482 unstrcpy(work_name,lp_workgroup()); 483 484 /* 485 * We are being very agressive here in adding a workgroup 486 * name on the basis of a host announcing itself as being 487 * in that workgroup. Maybe we should wait for the workgroup 488 * announce instead ? JRA. 489 */ 490 491 work = find_workgroup_on_subnet(subrec, work_name); 492 493 if(servertype != 0) { 494 if (work == NULL) { 495 /* We have no record of this workgroup. Add it. */ 496 if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) 497 goto done; 498 } 499 500 if((servrec = find_server_in_workgroup( work, announce_name))==NULL) { 501 /* If this server is not already in the workgroup, add it. */ 502 create_server_on_workgroup(work, announce_name, 503 servertype|SV_TYPE_LOCAL_LIST_ONLY, 504 ttl, comment); 505 } else { 506 /* Update the record. */ 507 servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; 508 update_server_ttl( servrec, ttl); 509 fstrcpy(servrec->serv.comment,comment); 510 } 511 } else { 512 /* 513 * This server is announcing it is going down. Remove it from the 514 * workgroup. 515 */ 516 if(!is_myname(announce_name) && (work != NULL) && 517 ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) { 518 remove_server_from_workgroup( work, servrec); 519 } 520 } 521 522 subrec->work_changed = True; 523 found_lm_clients = True; 524 525done: 526 527 END_PROFILE(lm_host_announce); 528} 529 530/**************************************************************************** 531 Send a backup list response. 532*****************************************************************************/ 533 534static void send_backup_list_response(struct subnet_record *subrec, 535 struct work_record *work, 536 struct nmb_name *send_to_name, 537 unsigned char max_number_requested, 538 uint32 token, struct in_addr sendto_ip, 539 int port) 540{ 541 char outbuf[1024]; 542 char *p, *countptr; 543 unsigned int count = 0; 544 unstring send_to_namestr; 545#if 0 546 struct server_record *servrec; 547#endif 548 unstring myname; 549 550 memset(outbuf,'\0',sizeof(outbuf)); 551 552 DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n", 553 work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip))); 554 555 p = outbuf; 556 557 SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */ 558 p++; 559 560 countptr = p; 561 p++; 562 563 SIVAL(p,0,token); /* The sender's unique info. */ 564 p += 4; 565 566 /* We always return at least one name - our own. */ 567 count = 1; 568 unstrcpy(myname, global_myname()); 569 strupper_m(myname); 570 myname[15]='\0'; 571 push_pstring_base(p, myname, outbuf); 572 573 p = skip_string(p,1); 574 575 /* Look for backup browsers in this workgroup. */ 576 577#if 0 578 /* we don't currently send become_backup requests so we should never 579 send any other servers names out as backups for our 580 workgroup. That's why this is commented out (tridge) */ 581 582 /* 583 * NB. Note that the struct work_record here is not neccessarily 584 * attached to the subnet *subrec. 585 */ 586 587 for (servrec = work->serverlist; servrec; servrec = servrec->next) 588 { 589 int len = PTR_DIFF(p, outbuf); 590 if((sizeof(outbuf) - len) < 16) 591 break; 592 593 if(count >= (unsigned int)max_number_requested) 594 break; 595 596 if(strnequal(servrec->serv.name, global_myname(),15)) 597 continue; 598 599 if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER)) 600 continue; 601 602 StrnCpy(p, servrec->serv.name, 15); 603 strupper_m(p); 604 count++; 605 606 DEBUG(5,("send_backup_list_response: Adding server %s number %d\n", 607 p, count)); 608 609 p = skip_string(p,1); 610 } 611#endif 612 613 SCVAL(countptr, 0, count); 614 615 pull_ascii_nstring(send_to_namestr, sizeof(send_to_namestr), send_to_name->name); 616 617 DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n", 618 send_to_namestr, inet_ntoa(sendto_ip), count)); 619 620 send_mailslot(True, BROWSE_MAILSLOT, 621 outbuf,PTR_DIFF(p,outbuf), 622 global_myname(), 0, 623 send_to_namestr,0, 624 sendto_ip, subrec->myip, port); 625} 626 627/******************************************************************* 628 Process a send backup list request packet. 629 630 A client sends a backup list request to ask for a list of servers on 631 the net that maintain server lists for a domain. A server is then 632 chosen from this list to send NetServerEnum commands to to list 633 available servers. 634 635********************************************************************/ 636 637void process_get_backup_list_request(struct subnet_record *subrec, 638 struct packet_struct *p,char *buf) 639{ 640 struct dgram_packet *dgram = &p->packet.dgram; 641 struct work_record *work; 642 unsigned char max_number_requested = CVAL(buf,0); 643 uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */ 644 int name_type = dgram->dest_name.name_type; 645 unstring workgroup_name; 646 struct subnet_record *search_subrec = subrec; 647 648 START_PROFILE(get_backup_list); 649 pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name); 650 651 DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n", 652 nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), 653 nmb_namestr(&dgram->dest_name))); 654 655 /* We have to be a master browser, or a domain master browser 656 for the requested workgroup. That means it must be our 657 workgroup. */ 658 659 if(strequal(workgroup_name, lp_workgroup()) == False) { 660 DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n", 661 workgroup_name)); 662 goto done; 663 } 664 665 if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) { 666 DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \ 667subnet %s.\n", workgroup_name, search_subrec->subnet_name)); 668 goto done; 669 } 670 671 /* 672 * If the packet was sent to WORKGROUP<1b> instead 673 * of WORKGROUP<1d> then it was unicast to us a domain master 674 * browser. Change search subrec to unicast. 675 */ 676 677 if(name_type == 0x1b) { 678 /* We must be a domain master browser in order to 679 process this packet. */ 680 681 if(!AM_DOMAIN_MASTER_BROWSER(work)) { 682 DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ 683and I am not a domain master browser.\n", workgroup_name)); 684 goto done; 685 } 686 687 search_subrec = unicast_subnet; 688 } else if (name_type == 0x1d) { 689 /* We must be a local master browser in order to process this packet. */ 690 691 if(!AM_LOCAL_MASTER_BROWSER(work)) { 692 DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ 693and I am not a local master browser.\n", workgroup_name)); 694 goto done; 695 } 696 } else { 697 DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n", 698 name_type)); 699 goto done; 700 } 701 702 send_backup_list_response(subrec, work, &dgram->source_name, 703 max_number_requested, token, p->ip, p->port); 704 705done: 706 707 END_PROFILE(get_backup_list); 708} 709 710/******************************************************************* 711 Process a reset browser state packet. 712 713 Diagnostic packet: 714 0x1 - Stop being a master browser and become a backup browser. 715 0x2 - Discard browse lists, stop being a master browser, try again. 716 0x4 - Stop being a master browser forever. 717 718******************************************************************/ 719 720void process_reset_browser(struct subnet_record *subrec, 721 struct packet_struct *p,char *buf) 722{ 723 struct dgram_packet *dgram = &p->packet.dgram; 724 int state = CVAL(buf,0); 725 struct subnet_record *sr; 726 727 START_PROFILE(reset_browser); 728 729 DEBUG(1,("process_reset_browser: received diagnostic browser reset \ 730request from %s IP %s state=0x%X\n", 731 nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state)); 732 733 /* Stop being a local master browser on all our broadcast subnets. */ 734 if (state & 0x1) { 735 for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) { 736 struct work_record *work; 737 for (work = sr->workgrouplist; work; work = work->next) { 738 if (AM_LOCAL_MASTER_BROWSER(work)) 739 unbecome_local_master_browser(sr, work, True); 740 } 741 } 742 } 743 744 /* Discard our browse lists. */ 745 if (state & 0x2) { 746 /* 747 * Calling expire_workgroups_and_servers with a -1 748 * time causes all servers not marked with a PERMANENT_TTL 749 * on the workgroup lists to be discarded, and all 750 * workgroups with empty server lists to be discarded. 751 * This means we keep our own server names and workgroup 752 * as these have a PERMANENT_TTL. 753 */ 754 755 expire_workgroups_and_servers(-1); 756 } 757 758 /* Request to stop browsing altogether. */ 759 if (state & 0x4) 760 DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n")); 761 762 END_PROFILE(reset_browser); 763} 764 765/******************************************************************* 766 Process an announcement request packet. 767 We don't respond immediately, we just check it's a request for 768 our workgroup and then set the flag telling the announce code 769 in nmbd_sendannounce.c:announce_my_server_names that an 770 announcement is needed soon. 771******************************************************************/ 772 773void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) 774{ 775 struct dgram_packet *dgram = &p->packet.dgram; 776 struct work_record *work; 777 unstring workgroup_name; 778 779 START_PROFILE(announce_request); 780 781 pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name); 782 DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n", 783 nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), 784 nmb_namestr(&dgram->dest_name))); 785 786 /* We only send announcement requests on our workgroup. */ 787 if(strequal(workgroup_name, lp_workgroup()) == False) { 788 DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n", 789 workgroup_name)); 790 goto done; 791 } 792 793 if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) { 794 DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", 795 workgroup_name)); 796 goto done; 797 } 798 799 work->needannounce = True; 800done: 801 802 END_PROFILE(lm_host_announce); 803} 804 805/******************************************************************* 806 Process a LanMan announcement request packet. 807 We don't respond immediately, we just check it's a request for 808 our workgroup and then set the flag telling that we have found 809 a LanMan client (DOS or OS/2) and that we will have to start 810 sending LanMan announcements (unless specifically disabled 811 through the "lm announce" parameter in smb.conf) 812******************************************************************/ 813 814void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) 815{ 816 struct dgram_packet *dgram = &p->packet.dgram; 817 unstring workgroup_name; 818 819 START_PROFILE(lm_announce_request); 820 821 pull_ascii_nstring(workgroup_name, sizeof(workgroup_name), dgram->dest_name.name); 822 DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n", 823 nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), 824 nmb_namestr(&dgram->dest_name))); 825 826 /* We only send announcement requests on our workgroup. */ 827 if(strequal(workgroup_name, lp_workgroup()) == False) { 828 DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n", 829 workgroup_name)); 830 goto done; 831 } 832 833 if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) { 834 DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", 835 workgroup_name)); 836 goto done; 837 } 838 839 found_lm_clients = True; 840 841done: 842 843 END_PROFILE(lm_host_announce); 844} 845