This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[kai/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       fstrcpy(servrec->serv.comment,comment);
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       fstrcpy(servrec->serv.comment,comment);
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       fstrcpy(servrec->serv.comment,comment);
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   fstring myname;
563
564   memset(outbuf,'\0',sizeof(outbuf));
565
566   DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
567            work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
568   
569   p = outbuf;
570   
571   SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
572   p++;
573
574   countptr = p;
575   p++;
576
577   SIVAL(p,0,token); /* The sender's unique info. */
578   p += 4;
579   
580   /* We always return at least one name - our own. */
581   count = 1;
582   fstrcpy(myname, global_myname());
583   strupper(myname);
584   myname[15]='\0';
585   push_pstring_base(p, myname, outbuf);
586
587   p = skip_string(p,1);
588
589   /* Look for backup browsers in this workgroup. */
590
591 #if 0
592   /* we don't currently send become_backup requests so we should never
593      send any other servers names out as backups for our
594      workgroup. That's why this is commented out (tridge) */
595
596   /*
597    * NB. Note that the struct work_record here is not neccessarily
598    * attached to the subnet *subrec.
599    */
600
601   for (servrec = work->serverlist; servrec; servrec = servrec->next)
602   { 
603     int len = PTR_DIFF(p, outbuf);
604     if((sizeof(outbuf) - len) < 16)
605       break;
606
607     if(count >= (unsigned int)max_number_requested)
608       break;
609
610     if(strnequal(servrec->serv.name, global_myname(),15))
611       continue;
612
613     if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))
614       continue;
615
616     StrnCpy(p, servrec->serv.name, 15);
617     strupper(p);
618     count++;
619
620     DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",
621               p, count));
622
623     p = skip_string(p,1);
624   }
625 #endif
626
627   SCVAL(countptr, 0, count);
628
629   DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
630           send_to_name->name, inet_ntoa(sendto_ip), count));
631
632   send_mailslot(True, BROWSE_MAILSLOT,
633                 outbuf,PTR_DIFF(p,outbuf),
634                 global_myname(), 0, 
635                 send_to_name->name,0,
636                 sendto_ip, subrec->myip, port);
637 }
638
639 /*******************************************************************
640   Process a send backup list request packet.
641
642   A client sends a backup list request to ask for a list of servers on
643   the net that maintain server lists for a domain. A server is then
644   chosen from this list to send NetServerEnum commands to to list
645   available servers.
646
647 ********************************************************************/
648
649 void process_get_backup_list_request(struct subnet_record *subrec,
650                                      struct packet_struct *p,char *buf)
651 {
652   struct dgram_packet *dgram = &p->packet.dgram;
653   struct work_record *work;
654   unsigned char max_number_requested = CVAL(buf,0);
655   uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
656   int name_type = dgram->dest_name.name_type;
657   char *workgroup_name = dgram->dest_name.name;
658   struct subnet_record *search_subrec = subrec;
659
660   START_PROFILE(get_backup_list);
661   DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
662            nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
663            nmb_namestr(&dgram->dest_name)));
664   
665   /* We have to be a master browser, or a domain master browser
666      for the requested workgroup. That means it must be our
667      workgroup. */
668
669   if(strequal(workgroup_name, lp_workgroup()) == False)
670   {
671     DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
672            workgroup_name));
673     goto done;
674   }
675
676   if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL)
677   {
678     DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
679 subnet %s.\n", workgroup_name, search_subrec->subnet_name));
680     goto done;
681   }
682
683   /* 
684    * If the packet was sent to WORKGROUP<1b> instead
685    * of WORKGROUP<1d> then it was unicast to us a domain master
686    * browser. Change search subrec to unicast.
687    */
688
689   if(name_type == 0x1b)
690   {
691     /* We must be a domain master browser in order to
692        process this packet. */
693
694     if(!AM_DOMAIN_MASTER_BROWSER(work))
695     {
696       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
697 and I am not a domain master browser.\n", workgroup_name));
698       goto done;
699     }
700
701     search_subrec = unicast_subnet;
702   }
703   else if (name_type == 0x1d)
704   {
705     /* We must be a local master browser in order to
706        process this packet. */
707
708     if(!AM_LOCAL_MASTER_BROWSER(work))
709     {
710       DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
711 and I am not a local master browser.\n", workgroup_name));
712       goto done;
713     }
714   }
715   else
716   {
717     DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
718             name_type));
719     goto done;
720   }
721
722   send_backup_list_response(subrec, work, &dgram->source_name, 
723                             max_number_requested, token, p->ip, p->port);
724 done:
725   END_PROFILE(get_backup_list);
726 }
727
728 /*******************************************************************
729   Process a reset browser state packet.
730
731   Diagnostic packet:
732   0x1 - Stop being a master browser and become a backup browser.
733   0x2 - Discard browse lists, stop being a master browser, try again.
734   0x4 - Stop being a master browser forever.
735          
736 ******************************************************************/
737
738 void process_reset_browser(struct subnet_record *subrec,
739                                   struct packet_struct *p,char *buf)
740 {
741   struct dgram_packet *dgram = &p->packet.dgram;
742   int state = CVAL(buf,0);
743   struct subnet_record *sr;
744
745   START_PROFILE(reset_browser);
746   DEBUG(1,("process_reset_browser: received diagnostic browser reset \
747 request from %s IP %s state=0x%X\n",
748              nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));
749
750   /* Stop being a local master browser on all our broadcast subnets. */
751   if (state & 0x1)
752   {
753     for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr))
754     {
755       struct work_record *work;
756       for (work = sr->workgrouplist; work; work = work->next)
757       {
758         if (AM_LOCAL_MASTER_BROWSER(work))
759           unbecome_local_master_browser(sr, work, True);
760       }
761     }
762   }
763   
764   /* Discard our browse lists. */
765   if (state & 0x2)
766   {
767     /*
768      * Calling expire_workgroups_and_servers with a -1
769      * time causes all servers not marked with a PERMANENT_TTL
770      * on the workgroup lists to be discarded, and all 
771      * workgroups with empty server lists to be discarded.
772      * This means we keep our own server names and workgroup
773      * as these have a PERMANENT_TTL.
774      */
775
776     expire_workgroups_and_servers(-1);
777   }
778   
779   /* Request to stop browsing altogether. */
780   if (state & 0x4)
781     DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
782
783   END_PROFILE(reset_browser);
784 }
785
786 /*******************************************************************
787   Process an announcement request packet.
788   We don't respond immediately, we just check it's a request for
789   our workgroup and then set the flag telling the announce code
790   in nmbd_sendannounce.c:announce_my_server_names that an 
791   announcement is needed soon.
792 ******************************************************************/
793
794 void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
795 {
796   struct dgram_packet *dgram = &p->packet.dgram;
797   struct work_record *work;
798   char *workgroup_name = dgram->dest_name.name;
799  
800   START_PROFILE(announce_request);
801   DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
802            nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
803            nmb_namestr(&dgram->dest_name)));
804   
805   /* We only send announcement requests on our workgroup. */
806   if(strequal(workgroup_name, lp_workgroup()) == False)
807   {
808     DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
809            workgroup_name));
810     goto done;
811   }
812
813   if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
814   {
815     DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
816             workgroup_name));
817     goto done;
818   }
819
820   work->needannounce = True;
821 done:
822   END_PROFILE(lm_host_announce);
823 }
824
825 /*******************************************************************
826   Process a LanMan announcement request packet.
827   We don't respond immediately, we just check it's a request for
828   our workgroup and then set the flag telling that we have found
829   a LanMan client (DOS or OS/2) and that we will have to start
830   sending LanMan announcements (unless specifically disabled
831   through the "lm announce" parameter in smb.conf)
832 ******************************************************************/
833
834 void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
835 {
836   struct dgram_packet *dgram = &p->packet.dgram;
837   char *workgroup_name = dgram->dest_name.name;
838
839   START_PROFILE(lm_announce_request);
840   DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
841            nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
842            nmb_namestr(&dgram->dest_name)));
843
844   /* We only send announcement requests on our workgroup. */
845   if(strequal(workgroup_name, lp_workgroup()) == False)
846   {
847     DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
848            workgroup_name));
849     goto done;
850   }
851
852   if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL)
853   {
854     DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
855             workgroup_name));
856     goto done;
857   }
858
859   found_lm_clients = True;
860 done:
861   END_PROFILE(lm_host_announce);
862 }