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