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