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