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