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