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