as a result of the writing of namework.doc, namework.c has been tidied up,
[kai/samba.git] / source3 / namework.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-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Revision History:
22
23    14 jan 96: lkcl@pires.co.uk
24    added multiple workgroup domain master support
25
26 */
27
28 #include "includes.h"
29
30 extern int ClientNMB;
31 extern int ClientDGRAM;
32
33 #define TEST_CODE /* want to debug unknown browse packets */
34
35 extern int DEBUGLEVEL;
36 extern pstring scope;
37 extern BOOL CanRecurse;
38
39 extern pstring myname;
40
41 extern int ClientNMB;
42 extern int ClientDGRAM;
43
44 extern struct in_addr ipzero;
45
46 extern int workgroup_count; /* total number of workgroups we know about */
47
48 /* this is our domain/workgroup/server database */
49 extern struct subnet_record *subnetlist;
50
51 /* machine comment for host announcements */
52 extern  pstring ServerComment;
53
54 extern int  updatecount;
55
56 /* what server type are we currently */
57 #define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \
58                 SV_TYPE_TIME_SOURCE | SV_TYPE_SERVER_UNIX |\
59                 SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER)
60
61 /* backup request types: which servers are to be included */
62 #define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
63 #define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL   )
64
65 extern time_t StartupTime;
66
67 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
68
69
70 /****************************************************************************
71 tell a server to become a backup browser
72 state - 0x01 become backup instead of master
73       - 0x02 remove all entries in browse list and become non-master
74       - 0x04 stop master browser service altogether. NT ignores this 
75 **************************************************************************/
76 void reset_server(char *name, int state, struct in_addr ip)
77 {
78   char outbuf[20];
79   char *p;
80
81   bzero(outbuf,sizeof(outbuf));
82   p = outbuf;
83
84   CVAL(p,0) = ANN_ResetBrowserState;
85   CVAL(p,2) = state; 
86   p += 2;
87
88   DEBUG(2,("sending reset to %s %s of state %d\n",
89            name,inet_ntoa(ip),state));
90
91   send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
92                       myname,name,0x20,0x1d,ip,*iface_ip(ip));
93 }
94
95
96 /****************************************************************************
97 tell a server to become a backup browser
98 **************************************************************************/
99 void tell_become_backup(void)
100 {
101   /* XXXX note: this function is currently unsuitable for use, as it
102      does not properly check that a server is in a fit state to become
103      a backup browser before asking it to be one.
104    */
105
106   struct subnet_record *d;
107   for (d = subnetlist; d; d = d->next)
108     {
109       struct work_record *work;
110       for (work = d->workgrouplist; work; work = work->next)
111         {
112           struct server_record *s;
113           int num_servers = 0;
114           int num_backups = 0;
115           
116           for (s = work->serverlist; s; s = s->next)
117             {
118               if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
119               
120               num_servers++;
121               
122               if (strequal(myname, s->serv.name)) continue;
123               
124               if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
125                 num_backups++;
126                 continue;
127               }
128               
129               if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
130               
131               if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
132               
133               DEBUG(3,("num servers: %d num backups: %d\n", 
134                        num_servers, num_backups));
135               
136               /* make first server a backup server. thereafter make every
137                  tenth server a backup server */
138               if (num_backups != 0 && (num_servers+9) / num_backups > 10)
139                 {
140                   continue;
141                 }
142               
143               DEBUG(2,("sending become backup to %s %s for %s\n",
144                        s->serv.name, inet_ntoa(d->bcast_ip),
145                        work->work_group));
146               
147               /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
148               do_announce_request(s->serv.name, work->work_group,
149                                   ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
150             }
151         }
152     }
153 }
154
155
156 /*******************************************************************
157   same context: scope. should check name_type as well, and makes sure
158   we don't process messages from ourselves
159   ******************************************************************/
160 BOOL same_context(struct dgram_packet *dgram)
161 {
162   if (!strequal(dgram->dest_name  .scope,scope )) return(True);
163   if ( strequal(dgram->source_name.name ,myname)) return(True);
164   
165   return(False);
166 }
167
168
169 /*******************************************************************
170   am I listening on a name. XXXX check the type of name as well.
171   ******************************************************************/
172 BOOL listening_name(struct work_record *work, struct nmb_name *n)
173 {
174   if (strequal(n->name,myname) ||
175       strequal(n->name,work->work_group) ||
176       strequal(n->name,MSBROWSE))
177     {
178       return(True);
179     }
180   
181   return(False);
182 }
183
184
185 /*******************************************************************
186   process a domain announcement frame
187
188   Announce frames come in 3 types. Servers send host announcements
189   (command=1) to let the master browswer know they are
190   available. Master browsers send local master announcements
191   (command=15) to let other masters and backups that they are the
192   master. They also send domain announcements (command=12) to register
193   the domain
194
195   The comment field of domain announcements contains the master
196   browser name. The servertype is used by NetServerEnum to select
197   resources. We just have to pass it to smbd (via browser.dat) and let
198   the client choose using bit masks.
199   ******************************************************************/
200 static void process_announce(struct packet_struct *p,int command,char *buf)
201 {
202   struct dgram_packet *dgram = &p->packet.dgram;
203   struct in_addr ip = dgram->header.source_ip;
204   struct subnet_record *d = find_subnet(ip); 
205   int update_count = CVAL(buf,0);
206   int ttl = IVAL(buf,1)/1000;
207   char *name = buf+5;
208   int osmajor=CVAL(buf,21);
209   int osminor=CVAL(buf,22);
210   uint32 servertype = IVAL(buf,23);
211   char *comment = buf+31;
212   struct work_record *work;
213   char *work_name;
214   char *serv_name = dgram->source_name.name;
215   BOOL add = False;
216
217   comment[43] = 0;
218   
219   DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
220   DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
221            namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
222            servertype,comment));
223   
224   name[15] = 0;  
225   
226   if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement)
227     {
228       DEBUG(2,("Announce to nametype(0) not supported yet\n"));
229       return;
230     }
231
232   if (command == ANN_DomainAnnouncement && 
233       ((!strequal(dgram->dest_name.name, MSBROWSE)) ||
234        dgram->dest_name.name_type != 0x1))
235     {
236       DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
237                 command, inet_ntoa(ip), namestr(&dgram->dest_name)));
238       return;
239     }
240   
241   if (same_context(dgram)) return;
242   
243   if (command == ANN_DomainAnnouncement) { 
244     /* XXXX if we are a master browser for the workgroup work_name,
245        then there is a local subnet configuration problem. only
246        we should be sending out such domain announcements, because
247        as the master browser, that is our job.
248
249        stop being a master browser, and force an election. this will
250        sort out the network problem. hopefully.
251      */
252
253     work_name = name;
254   } else {
255     work_name = dgram->dest_name.name;
256   }
257
258   /* we need some way of finding out about new workgroups
259      that appear to be sending packets to us. The name_type checks make
260      sure we don't add host names as workgroups */
261   if (command == ANN_HostAnnouncement &&
262       (dgram->dest_name.name_type == 0x1d ||
263        dgram->dest_name.name_type == 0x1e))
264     add = True;
265   
266   if (!(work = find_workgroupstruct(d, work_name,add)))
267     return;
268   
269   DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
270   
271   ttl = GET_TTL(ttl);
272   
273   /* add them to our browse list */
274   add_server_entry(d,work,name,servertype,ttl,comment,True);
275   
276 #if 0
277   /* the tell become backup code is broken, no great harm is done by
278      disabling it */
279   tell_become_backup();
280 #endif
281
282   /* XXXX over-kill: i don't think we should really be doing this,
283      but it doesn't do much harm other than to add extra network
284      traffic. to be more precise, we should (possibly) only
285      sync browse lists with a host that sends an
286      ANN_LocalMasterAnnouncement or an ANN_DomainAnnouncement.
287      possibly.
288    */
289
290   /* get their browse list from them and add it to ours. */
291   add_browser_entry(serv_name,dgram->dest_name.name_type,
292                     work->work_group,30,ip);
293 }
294
295 /*******************************************************************
296   process a master announcement frame
297   ******************************************************************/
298 static void process_master_announce(struct packet_struct *p,char *buf)
299 {
300   struct dgram_packet *dgram = &p->packet.dgram;
301   struct in_addr ip = dgram->header.source_ip;
302   struct subnet_record *d = find_subnet(ip);
303   struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
304   char *name = buf;
305   struct work_record *work;
306   name[15] = 0;
307   
308   DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
309   
310   if (same_context(dgram)) return;
311   
312   if (!d || !mydomain) return;
313   
314   if (!lp_domain_master()) return;
315   
316   for (work = mydomain->workgrouplist; work; work = work->next)
317     {
318       if (AM_MASTER(work))
319         {
320           /* merge browse lists with them */
321           add_browser_entry(name,0x1b, work->work_group,30,ip);
322         }
323     }
324 }
325
326 /*******************************************************************
327   process a receive backup list request
328   
329   we receive a list of servers, and we attempt to locate them all on
330   our local subnet, and sync browse lists with them on the workgroup
331   they are said to be in.
332
333   XXXX NOTE: this function is in overdrive. it should not really do
334   half of what it actually does (it should pick _one_ name from the
335   list received and sync with it at regular intervals, rather than
336   sync with them all only once!)
337
338   ******************************************************************/
339 static void process_rcv_backup_list(struct packet_struct *p,char *buf)
340 {
341   struct dgram_packet *dgram = &p->packet.dgram;
342   struct in_addr ip = dgram->header.source_ip;
343   int count = CVAL(buf,0);
344   int Index = IVAL(buf,1); /* caller's index representing workgroup */
345   char *buf1;
346   
347   DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n",
348            namestr(&dgram->dest_name), inet_ntoa(ip),
349            count, Index));
350   
351   if (same_context(dgram)) return;
352   
353   if (count <= 0) return;
354   
355   /* go through the list of servers attempting to sync browse lists */
356   for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
357     {
358       struct in_addr back_ip;
359       struct subnet_record *d;
360       
361       DEBUG(4,("Searching for backup browser %s at %s...\n",
362                buf1, inet_ntoa(ip)));
363       
364       /* XXXX assume name is a DNS name NOT a netbios name. a more complete
365              approach is to use reply_name_query functionality to find the name */
366       back_ip = *interpret_addr2(buf1);
367       
368       if (zero_ip(back_ip))
369         {
370           DEBUG(4,("Failed to find backup browser server using DNS\n"));
371           continue;
372         }
373       
374       DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
375       
376       if ((d = find_subnet(back_ip)))
377         {
378           struct subnet_record *d1;
379           for (d1 = subnetlist; d1; d1 = d1->next)
380             {
381               struct work_record *work;
382               for (work = d1->workgrouplist; work; work = work->next)
383                 {
384                   if (work->token == Index)
385                     {
386                       queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
387                                            work->work_group,0x1d,0,0,
388                                            False,False,back_ip);
389                       return;
390                     }
391                 }
392             }
393         }
394     }
395 }
396
397
398 /****************************************************************************
399   send a backup list response.
400   **************************************************************************/
401 static void send_backup_list(char *work_name, struct nmb_name *src_name,
402                              int info_count, int token, int info,
403                              int name_type, struct in_addr ip)
404 {                     
405   struct subnet_record *d;
406   char outbuf[1024];
407   char *p, *countptr, *nameptr;
408   int count = 0;
409   int i, j;
410   char *theirname = src_name->name;
411   
412   DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", 
413            work_name, inet_ntoa(ip),
414            myname,0x20,theirname,0x0));    
415   
416   if (name_type == 0x1d)
417     {
418       DEBUG(4,("master browsers: "));
419     }
420   else if (name_type == 0x1b)
421     {
422       DEBUG(4,("domain controllers: "));
423     }
424   else
425     {
426       DEBUG(0,("backup request for unknown type %0x\n", name_type));
427       return;
428     }
429   
430   bzero(outbuf,sizeof(outbuf));
431   p = outbuf;
432   
433   CVAL(p,0) = ANN_GetBackupListResp;    /* backup list response */
434   p++;
435   
436   countptr = p; /* count pointer */
437   
438   SSVAL(p,1,token); /* sender's workgroup index representation */
439   SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
440   p += 5;
441   
442   nameptr = p;
443   
444   for (d = subnetlist; d; d = d->next)
445     {
446       struct work_record *work;
447       
448       for (work = d->workgrouplist; work; work = work->next)
449         {
450           struct server_record *s;
451           
452           if (!strequal(work->work_group, work_name)) continue;
453           
454           for (s = work->serverlist; s; s = s->next)
455             { 
456               BOOL found = False;
457               char *n;
458               
459               if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
460               
461               for (n = nameptr; n < p; n = skip_string(n, 1))
462                 {
463                   if (strequal(n, s->serv.name)) found = True;
464                 }
465               
466               if (found) continue; /* exclude names already added */
467               
468               /* workgroup request: include all backup browsers in the list */
469               /* domain request: include all domain members in the list */
470               
471               if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
472                   (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
473                 {                          
474                   DEBUG(4, ("%s ", s->serv.name));
475                   
476                   count++;
477                   strcpy(p,s->serv.name);
478                   strupper(p);
479                   p = skip_string(p,1);
480                 }
481             }
482         }
483     }
484   
485   if (count == 0)
486     {
487       DEBUG(4, ("none\n"));
488       return;
489     }
490   else
491     {
492       DEBUG(4, (" - count %d\n", count));
493     }
494   
495   CVAL(countptr,0) = count; /* total number of backup browsers found */
496   
497   {
498     int len = PTR_DIFF(p, outbuf);
499     
500     for (i = 0; i < len; i+= 16)
501       {
502         DEBUG(4, ("%3x char ", i));
503         
504         for (j = 0; j < 16; j++)
505           {
506             unsigned char x = outbuf[i+j];
507             if (x < 32 || x > 127) x = '.';
508             
509             if (i+j >= len) break;
510             DEBUG(4, ("%c", x));
511           }
512         
513         DEBUG(4, (" hex ", i));
514         
515         for (j = 0; j < 16; j++)
516           {
517             if (i+j >= len) break;
518             DEBUG(4, (" %02x", outbuf[i+j]));
519           }
520         
521         DEBUG(4, ("\n"));
522       }
523     
524   }
525   send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
526                       myname,theirname,0x20,0x0,ip,*iface_ip(ip));
527 }
528
529
530 /*******************************************************************
531   process a send backup list request
532
533   A client sends a backup list request to ask for a list of servers on
534   the net that maintain server lists for a domain. A server is then
535   chosen from this list to send NetServerEnum commands to to list
536   available servers.
537
538   Currently samba only sends back one name in the backup list, its
539   own. For larger nets we'll have to add backups and send "become
540   backup" requests occasionally.
541   ******************************************************************/
542 static void process_send_backup_list(struct packet_struct *p,char *buf)
543 {
544   struct dgram_packet *dgram = &p->packet.dgram;
545   struct in_addr ip = dgram->header.source_ip;
546   struct subnet_record *d;
547   struct work_record *work;
548
549   int count = CVAL(buf,0);
550   int token = SVAL(buf,1); /* sender's key index for the workgroup? */
551   int info  = SVAL(buf,3); /* XXXX don't know: some sort of info */
552   int name_type = dgram->dest_name.name_type;
553
554   if (same_context(dgram)) return;
555   
556   if (count <= 0) return;
557   
558   if (name_type != 0x1b && name_type != 0x1d) {
559     DEBUG(0,("backup request to wrong type %d from %s\n",
560               name_type,inet_ntoa(ip)));
561     return;
562   }
563   
564   for (d = subnetlist; d; d = d->next)
565     {
566       for (work = d->workgrouplist; work; work = work->next)
567         {
568           if (strequal(work->work_group, dgram->dest_name.name))
569             {
570               DEBUG(2,("sending backup list to %s %s count=%d\n",
571                        namestr(&dgram->dest_name),inet_ntoa(ip),count));
572   
573               send_backup_list(work->work_group,&dgram->source_name,
574                                count,token,info,name_type,ip);
575               return;
576             }
577         } 
578     }
579 }
580
581
582 /*******************************************************************
583   process a reset browser state
584
585   diagnostic packet:
586   0x1 - stop being a master browser and become a backup browser.
587   0x2 - discard browse lists, stop being a master browser, try again.
588   0x4 - stop being a master browser forever. no way. ain't gonna.
589          
590   ******************************************************************/
591 static void process_reset_browser(struct packet_struct *p,char *buf)
592 {
593   struct dgram_packet *dgram = &p->packet.dgram;
594   int state = CVAL(buf,0);
595
596   DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n",
597            namestr(&dgram->dest_name), state));
598
599   /* stop being a master but still deal with being a backup browser */
600   if (state & 0x1)
601     {
602       struct subnet_record *d;
603       for (d = subnetlist; d; d = d->next)
604         {
605           struct work_record *work;
606           for (work = d->workgrouplist; work; work = work->next)
607             {
608               if (AM_MASTER(work))
609                 {
610                   become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
611                 }
612             }
613         }
614     }
615   
616   /* XXXX documentation inconsistency: the above description does not
617      exactly tally with what is implemented for state & 0x2
618    */
619
620   /* totally delete all servers and start afresh */
621   if (state & 0x2)
622     {
623       struct subnet_record *d;
624       for (d = subnetlist; d; d = d->next)
625         {
626           struct work_record *work;
627           for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
628         }
629       add_my_subnets(lp_workgroup());
630     }
631   
632   /* stop browsing altogether. i don't think this is a good idea! */
633   if (state & 0x4)
634     {
635       DEBUG(1,("ignoring request to stop being a browser. sorry!\n"));
636     }
637 }
638
639
640 /*******************************************************************
641   process a announcement request
642
643   clients send these when they want everyone to send an announcement
644   immediately. This can cause quite a storm of packets!
645   ******************************************************************/
646 static void process_announce_request(struct packet_struct *p,char *buf)
647 {
648   struct dgram_packet *dgram = &p->packet.dgram;
649   struct work_record *work;
650   struct in_addr ip = dgram->header.source_ip;
651   struct subnet_record *d = find_subnet(ip);
652   int token = CVAL(buf,0);
653   char *name = buf+1;
654   
655   name[15] = 0;
656   
657   DEBUG(3,("Announce request from %s to %s token=0x%X\n",
658            name,namestr(&dgram->dest_name), token));
659   
660   if (strequal(dgram->source_name.name,myname)) return;
661   
662   /* XXXX BUG or FEATURE?: need to ensure that we are a member of
663      this workgroup before announcing, particularly as we only
664      respond on local interfaces anyway.
665
666      if (strequal(dgram->dest_name, lp_workgroup()) return; ???
667    */
668
669   if (!d) return;
670   
671   if (!d->my_interface) return;
672   
673   for (work = d->workgrouplist; work; work = work->next)
674     {
675      /* XXXX BUG: the destination name type should also be checked,
676         not just the name. e.g if the name is WORKGROUP(0x1d) then
677         we should only respond if we own that name */
678     
679       if (strequal(dgram->dest_name.name,work->work_group)) 
680         {
681           work->needannounce = True;
682         }
683     }
684 }
685
686
687 /****************************************************************************
688 depending on what announce has been made, we are only going to
689 accept certain types of name announce. XXXX untested code
690
691 check listening name type
692 ****************************************************************************/
693 BOOL listening_type(struct packet_struct *p, int command)
694 {
695   struct dgram_packet *dgram = &p->packet.dgram;
696   int type = dgram->dest_name.name_type;
697
698   switch (command)
699     {
700     case ANN_HostAnnouncement:
701       {
702         if (type != 0x0 || type != 0x20) return (False);
703         break;
704       }
705       
706     case ANN_AnnouncementRequest:
707       {
708         return (True);
709         break;
710       }
711       
712     case ANN_Election:
713       {
714         return (True);
715         break;
716       }
717       
718     case ANN_GetBackupListReq:
719       {
720         return (True);
721         break;
722       }
723       
724     case ANN_GetBackupListResp:
725       {
726         return (True);
727         break;
728       }
729       
730     case ANN_DomainAnnouncement:
731       {
732         if (type != 0x1b || type != 0x1c) return (False);
733         break;
734       }
735       
736     case ANN_MasterAnnouncement:
737       {
738         if (type != 0x1d) return (False);
739         break;
740       }
741       
742     case ANN_LocalMasterAnnouncement:
743       {
744         if (type != 0x1c || type != 0x1d) return (False);
745         break;
746       }
747     }
748   return (True); /* we're not dealing with unknown packet types */
749 }
750
751
752 /****************************************************************************
753 process a browse frame
754 ****************************************************************************/
755 void process_browse_packet(struct packet_struct *p,char *buf,int len)
756 {
757   int command = CVAL(buf,0);
758   switch (command) 
759     {
760     case ANN_HostAnnouncement:
761     case ANN_DomainAnnouncement:
762     case ANN_LocalMasterAnnouncement:
763       {
764         process_announce(p,command,buf+1);
765         break;
766       }
767       
768     case ANN_AnnouncementRequest:
769       {
770         process_announce_request(p,buf+1);
771         break;
772       }
773       
774     case ANN_Election:
775       {
776         process_election(p,buf+1);
777         break;
778       }
779       
780     case ANN_GetBackupListReq:
781       {
782         process_send_backup_list(p,buf+1);
783         break;
784       }
785       
786     case ANN_GetBackupListResp:
787       {
788         process_rcv_backup_list(p, buf+1);
789         break;
790       }
791       
792     case ANN_ResetBrowserState:
793       {
794         process_reset_browser(p, buf+1);
795         break;
796       }
797       
798     case ANN_MasterAnnouncement:
799       {
800         process_master_announce(p,buf+1);
801         break;
802       }
803       
804     default:
805       {
806         struct dgram_packet *dgram = &p->packet.dgram;
807         DEBUG(4,("ignoring browse packet %d from %s %s to %s\n",
808                  command, namestr(&dgram->source_name), 
809                  inet_ntoa(p->ip), namestr(&dgram->dest_name)));
810       }
811     }
812 }
813
814
815 /****************************************************************************
816 process udp 138 datagrams
817 ****************************************************************************/
818 void process_dgram(struct packet_struct *p)
819 {
820   char *buf;
821   char *buf2;
822   int len;
823   struct dgram_packet *dgram = &p->packet.dgram;
824
825   if (dgram->header.msg_type != 0x10 &&
826       dgram->header.msg_type != 0x11 &&
827       dgram->header.msg_type != 0x12) {
828     /* don't process error packets etc yet */
829     return;
830   }
831
832   buf = &dgram->data[0];
833   buf -= 4; /* XXXX for the pseudo tcp length - 
834                someday I need to get rid of this */
835
836   if (CVAL(buf,smb_com) != SMBtrans) return;
837
838   len = SVAL(buf,smb_vwv11);
839   buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
840
841   DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
842            namestr(&dgram->source_name),namestr(&dgram->dest_name),
843            smb_buf(buf),CVAL(buf2,0),len));
844
845  
846   if (len <= 0) return;
847
848    /* datagram packet received for the browser mailslot */
849    if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
850      process_browse_packet(p,buf2,len);
851      return;
852    }
853
854    /* datagram packet received for the domain log on mailslot */
855    if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
856      process_logon_packet(p,buf2,len);
857      return;
858    }
859 }
860