root/source3/nmbd/nmbd_incomingdgrams.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tell_become_backup
  2. process_host_announce
  3. process_workgroup_announce
  4. process_local_master_announce
  5. process_master_browser_announce
  6. process_lm_host_announce
  7. send_backup_list_response
  8. process_get_backup_list_request
  9. process_reset_browser
  10. process_announce_request
  11. process_lm_announce_request

   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 
  25 extern 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 /****************************************************************************
  36 Tell a server to become a backup browser
  37 **************************************************************************/
  38 
  39 void tell_become_backup(void)
     /* [<][>][^][v][top][bottom][index][help] */
  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 
  95 void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
     /* [<][>][^][v][top][bottom][index][help] */
  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;
 186 done:
 187 
 188         END_PROFILE(host_announce);
 189 }
 190 
 191 /*******************************************************************
 192   Process an incoming WORKGROUP announcement packet.
 193 *******************************************************************/
 194 
 195 void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 243 done:
 244 
 245         END_PROFILE(workgroup_announce);
 246 }
 247 
 248 /*******************************************************************
 249   Process an incoming local master browser announcement packet.
 250 *******************************************************************/
 251 
 252 void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
     /* [<][>][^][v][top][bottom][index][help] */
 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 \
 307 a 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;
 354 done:
 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 
 366 void process_master_browser_announce(struct subnet_record *subrec, 
     /* [<][>][^][v][top][bottom][index][help] */
 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 \
 382 master - 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 
 409 done:
 410 
 411         END_PROFILE(master_browser_announce);
 412 }
 413 
 414 /*******************************************************************
 415   Process an incoming LanMan host announcement packet.
 416 *******************************************************************/
 417 
 418 void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len)
     /* [<][>][^][v][top][bottom][index][help] */
 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 \
 457 originate 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 
 528 done:
 529 
 530         END_PROFILE(lm_host_announce);
 531 }
 532 
 533 /****************************************************************************
 534   Send a backup list response.
 535 *****************************************************************************/
 536 
 537 static void send_backup_list_response(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 640 void process_get_backup_list_request(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
 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 \
 670 subnet %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 \
 686 and 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 \
 696 and 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 
 708 done:
 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 
 723 void process_reset_browser(struct subnet_record *subrec,
     /* [<][>][^][v][top][bottom][index][help] */
 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 \
 733 request 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 
 776 void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
     /* [<][>][^][v][top][bottom][index][help] */
 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;
 803 done:
 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 
 817 void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf, int len)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 844 done:
 845 
 846         END_PROFILE(lm_announce_request);
 847 }

/* [<][>][^][v][top][bottom][index][help] */