91215ec45d81325e72819ea1ab29bd1aafd7bac9
[samba.git] / source / 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 #include "loadparm.h"
30 #include "localnet.h"
31
32 #define TEST_CODE /* want to debug unknown browse packets */
33
34 extern int DEBUGLEVEL;
35 extern pstring scope;
36 extern BOOL CanRecurse;
37
38 extern struct in_addr myip;
39 extern struct in_addr bcast_ip;
40 extern struct in_addr Netmask;
41
42 extern pstring myname;
43
44 extern int ClientNMB;
45 extern int ClientDGRAM;
46
47 extern int workgroup_count; /* total number of workgroups we know about */
48
49 /* this is our browse cache database */
50 extern struct browse_cache_record *browserlist;
51
52 /* this is our domain/workgroup/server database */
53 extern struct domain_record *domainlist;
54
55 /* machine comment for host announcements */
56 extern  pstring ServerComment;
57
58 extern int  updatecount;
59
60 /* what server type are we currently */
61 #define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \
62                 SV_TYPE_TIME_SOURCE | SV_TYPE_SERVER_UNIX |\
63                 SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER)
64
65 /* backup request types: which servers are to be included */
66 #define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
67 #define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL   )
68
69 extern time_t StartupTime;
70
71 #define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
72 #define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
73
74 #define MSBROWSE "\001\002__MSBROWSE__\002"
75 #define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
76
77 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
78
79
80 /****************************************************************************
81 tell a server to become a backup browser
82 state - 0x01 become backup instead of master
83       - 0x02 remove all entries in browse list and become non-master
84       - 0x04 stop master browser service altogether. NT ignores this 
85 **************************************************************************/
86 void reset_server(char *name, int state, struct in_addr ip)
87 {
88         char outbuf[20];
89         char *p;
90
91         bzero(outbuf,sizeof(outbuf));
92         p = outbuf;
93
94         CVAL(p,0) = 14;    /* request reset browser state */
95         CVAL(p,2) = state; /* type of request */
96         p += 2;
97
98         send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
99                        myname,name,0x20,0x1d,ip,myip);
100 }
101
102 /****************************************************************************
103 tell a server to become a backup browser
104 **************************************************************************/
105 void tell_become_backup(void)
106 {
107         struct domain_record *d;
108         for (d = domainlist; d; d = d->next)
109         {
110                 struct work_record *work;
111                 for (work = d->workgrouplist; work; work = work->next)
112                 {
113                         struct server_record *s;
114                         int num_servers = 0;
115                         int num_backups = 0;
116
117                         for (s = work->serverlist; s; s = s->next)
118                         {
119                                 if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
120
121                                 num_servers++;
122
123                                 if (strequal(myname, s->serv.name)) continue;
124
125                                 if (s->serv.type & SV_TYPE_BACKUP_BROWSER)
126                                 {
127                                         num_backups++;
128                                         continue;
129                                 }
130
131                                 if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
132
133                                 if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
134
135                                 DEBUG(3,("num servers: %d num backups: %d\n", 
136                                      num_servers, num_backups));
137
138                                 /* make first server a backup server. thereafter make every
139                                    tenth server a backup server */
140                                 if (num_backups != 0 && (num_servers+9) / num_backups > 10)
141                                 {
142                                         continue;
143                                 }
144
145                                 DEBUG(3,("workgroup %s subnet %s: make backup: %s %8x \n", 
146                                          work->work_group, inet_ntoa(d->bcast_ip),
147                                                  s->serv.name, s->serv.type));
148                                                                
149                                 /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
150                                 do_announce_request(s->serv.name, work->work_group,
151                                                     11, 0x20, 0x1e, d->bcast_ip);
152                         }
153                 }
154         }
155 }
156
157 /****************************************************************************
158 find a server responsible for a workgroup, and sync browse lists
159 **************************************************************************/
160 static BOOL sync_browse_entry(struct browse_cache_record *b)
161 {                     
162         struct domain_record *d;
163         struct work_record *work;
164 /*
165         if (!strequal(serv_name, b->name))
166         {
167                 DEBUG(0, ("browser's netbios name (%s) does not match %s (%s)",
168                                 b->name, inet_ntoa(b->ip), serv_name));
169         }
170 */
171         if (!(d = find_domain(b->ip))) return False;
172         if (!(work = find_workgroupstruct(d, b->group, False))) return False;
173
174         sync_browse_lists(work,b->name,0x20,b->ip);
175         b->synced = True;
176         
177         return True;
178 }
179
180
181 /****************************************************************************
182 search through browser list for an entry to sync with
183 **************************************************************************/
184 void do_browser_lists(void)
185 {
186         struct browse_cache_record *b;
187         static time_t last = 0;
188         time_t t = time(NULL);
189
190         if (t-last < 4) return; /* don't do too many of these at once! */
191
192         last = t;
193
194         /* pick any entry in the list, preferably one whose time is up */
195         for (b = browserlist; b && b->next; b = b->next)
196         {
197                 if (b->sync_time < t && b->synced == False) break;
198         }
199
200         if (!b || b->synced || sync_browse_entry(b))
201         {
202                 /* leave entries (even ones already sync'd) for up to a minute.
203                    this stops them getting re-sync'd too often */
204                 expire_browse_cache(t - 60);
205         }
206 }
207
208
209 /****************************************************************************
210 find a server responsible for a workgroup, and sync browse lists
211 control ends up back here via response_name_query.
212 **************************************************************************/
213 void sync_server(enum cmd_type cmd, char *serv_name, char *work_name, int name_type,
214                  struct in_addr ip)
215 {                     
216         add_browser_entry(serv_name, name_type, work_name, 0, ip);
217
218         if (cmd == MASTER_SERVER_CHECK)
219         {
220                 /* announce ourselves as a master browser to serv_name */
221                 do_announce_request(myname, serv_name, 13, 0x20, 0, ip);
222         }
223 }
224
225
226 /****************************************************************************
227 update workgroup database from a name registration
228 **************************************************************************/
229 void update_from_reg(char *name, int type, struct in_addr ip)
230 {                     
231   /* default server type: minimum guess at requirement XXXX */
232
233   DEBUG(4,("update from registration: host %s ip %s type %0x\n",
234             name, inet_ntoa(ip), type));
235
236   /* workgroup types, but not a chat type */
237   if (type >= 0x1b && type <= 0x1e)
238     {
239       struct work_record *work;
240       struct domain_record *d;
241       
242       if (!(d    = find_domain(ip))) return;
243       if (!(work = find_workgroupstruct(d, name, False))) return;
244       
245       /* request the server to announce if on our subnet */
246       if (ip_equal(bcast_ip, d->bcast_ip)) announce_request(work, ip);
247       
248       /* domain master type or master browser type */
249       if (type == 0x1b || type == 0x1d)
250         {
251           struct hostent *hp = gethostbyaddr((char*)&ip, sizeof(ip), AF_INET);
252           if (hp) {
253             /* gethostbyaddr name may not match netbios name but who cares */
254             add_browser_entry(hp->h_name, type, work->work_group, 120, ip);
255           }
256         }
257     }
258 }
259
260
261 /****************************************************************************
262   add the default workgroup into my domain
263   **************************************************************************/
264 void add_my_domains(void)
265 {
266         /* add or find domain on our local subnet, in the default workgroup */
267
268         if (*lp_workgroup() != '*')
269         {
270                 add_domain_entry(bcast_ip,Netmask,lp_workgroup(), True);
271         }
272 }
273
274
275 /****************************************************************************
276   send a backup list response.
277   **************************************************************************/
278 static void send_backup_list(char *work_name, struct nmb_name *src_name,
279                              int info_count, int token, int info,
280                              int name_type, struct in_addr ip)
281 {                     
282         struct domain_record *d;
283         char outbuf[1024];
284         char *p, *countptr, *nameptr;
285         int count = 0;
286         int i, j;
287         char *theirname = src_name->name;
288
289         DEBUG(3,("Backup list of %s to %s: %s(%x) %s(%x)\n", 
290                   work_name, inet_ntoa(ip),
291                   myname,0x20,theirname,0x0));     
292                                                                
293         if (name_type == 0x1d)
294         {
295                 DEBUG(4,("master browsers: "));
296         }
297         else if (name_type == 0x1b)
298         {
299                 DEBUG(4,("domain controllers: "));
300         }
301         else
302         {
303                 DEBUG(0,("backup request for unknown type %0x\n", name_type));
304                 return;
305         }
306         
307         bzero(outbuf,sizeof(outbuf));
308         p = outbuf;
309
310         CVAL(p,0) = 10;    /* backup list response */
311         p++;
312
313         countptr = p; /* count pointer */
314         
315         SSVAL(p,1,token); /* sender's workgroup index representation */
316         SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
317         p += 5;
318
319         nameptr = p;
320
321         for (d = domainlist; d; d = d->next)
322         {
323                 struct work_record *work;
324
325                 for (work = d->workgrouplist; work; work = work->next)
326                 {
327                         struct server_record *s;
328                 
329                         if (!strequal(work->work_group, work_name)) continue;
330
331                         for (s = work->serverlist; s; s = s->next)
332                         { 
333                                 BOOL found = False;
334                                 char *n;
335
336                                 if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
337
338                                 for (n = nameptr; n < p; n = skip_string(n, 1))
339                                 {
340                                         if (strequal(n, s->serv.name)) found = True;
341                                 }
342
343                                 if (found) continue; /* exclude names already added */
344
345                                 /* workgroup request: include all backup browsers in the list */
346                                 /* domain request: include all domain members in the list */
347
348                                 if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
349                                         (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
350                                 {                          
351                                         DEBUG(4, ("%s ", s->serv.name));
352
353                                         count++;
354                                         strcpy(p,s->serv.name);
355                                         strupper(p);
356                                         p = skip_string(p,1);
357                                 }
358                         }
359                 }
360         }
361
362         if (count == 0)
363         {
364                 DEBUG(4, ("none\n"));
365                 return;
366         }
367         else
368         {
369                 DEBUG(4, (" - count %d\n", count));
370         }
371
372         CVAL(countptr,0) = count; /* total number of backup browsers found */
373
374         {
375                 int len = PTR_DIFF(p, outbuf);
376
377                 for (i = 0; i < len; i+= 16)
378                 {
379                         DEBUG(4, ("%3x char ", i));
380
381                         for (j = 0; j < 16; j++)
382                         {
383                                 unsigned char x = outbuf[i+j];
384                                 if (x < 32 || x > 127) x = '.';
385
386                                 if (i+j >= len) break;
387                                 DEBUG(4, ("%c", x));
388                         }
389
390                         DEBUG(4, (" hex ", i));
391
392                         for (j = 0; j < 16; j++)
393                         {
394                                 if (i+j >= len) break;
395                                 DEBUG(4, (" %02x", outbuf[i+j]));
396                         }
397
398                         DEBUG(4, ("\n"));
399                 }
400
401         }
402         send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
403                        myname,theirname,0x20,0,ip,myip);
404 }
405
406
407 /*******************************************************************
408   same context: scope. should check name_type as well, and makes sure
409   we don't process messages from ourselves
410   ******************************************************************/
411 BOOL same_context(struct dgram_packet *dgram)
412 {
413         if (!strequal(dgram->dest_name  .scope,scope )) return(True);
414         if ( strequal(dgram->source_name.name ,myname)) return(True);
415
416         return(False);
417 }
418
419
420 /*******************************************************************
421   am I listening on a name. XXXX check the type of name as well.
422   ******************************************************************/
423 BOOL listening_name(struct work_record *work, struct nmb_name *n)
424 {
425         if (strequal(n->name,myname) ||
426             strequal(n->name,work->work_group) ||
427             strequal(n->name,MSBROWSE))
428         {
429                 return(True);
430         }
431
432         return(False);
433 }
434
435
436 /*******************************************************************
437   process a domain announcement frame
438
439   Announce frames come in 3 types. Servers send host announcements
440   (command=1) to let the master browswer know they are
441   available. Master browsers send local master announcements
442   (command=15) to let other masters and backups that they are the
443   master. They also send domain announcements (command=12) to register
444   the domain
445
446   The comment field of domain announcements contains the master
447   browser name. The servertype is used by NetServerEnum to select
448   resources. We just have to pass it to smbd (via browser.dat) and let
449   the client choose using bit masks.
450   ******************************************************************/
451 static void process_announce(struct packet_struct *p,int command,char *buf)
452 {
453         struct dgram_packet *dgram = &p->packet.dgram;
454         struct in_addr ip = dgram->header.source_ip;
455         struct domain_record *d = find_domain(ip);
456
457         int update_count = CVAL(buf,0);
458         int ttl = IVAL(buf,1)/1000;
459         char *name = buf+5;
460         int osmajor=CVAL(buf,21);
461         int osminor=CVAL(buf,22);
462         uint32 servertype = IVAL(buf,23);
463         char *comment = buf+31;
464         struct work_record *work;
465         char *work_name;
466         char *serv_name = dgram->source_name.name;
467
468         comment[43] = 0;
469
470         DEBUG(3,("Announce(%d) %s(%x)",command,name,name[15]));
471         DEBUG(3,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
472            namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
473            servertype,comment));
474
475         name[15] = 0;  
476
477         if (dgram->dest_name.name_type == 0 && command == 1)
478         {
479                 DEBUG(2,("Announce to nametype(0) not supported yet\n"));
480                 return;
481         }
482         if (command == 12 && ((!strequal(dgram->dest_name.name, MSBROWSE)) ||
483             dgram->dest_name.name_type != 0x1))
484         {
485                 DEBUG(0, ("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
486                                         command, inet_ntoa(ip), namestr(&dgram->dest_name)));
487                 return;
488         }
489
490         if (same_context(dgram)) return;
491
492         if (command == 12)
493         {
494                 work_name = name;
495         }
496         else
497         {
498                 work_name = dgram->dest_name.name;
499         }
500
501         if (!(work = find_workgroupstruct(d, work_name, False))) return;
502
503         DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
504
505         ttl = GET_TTL(ttl);
506
507         /* add them to our browse list */
508         add_server_entry(d,work,name,servertype,ttl,comment,True);
509
510         /* make a selection of machines become backup browsers (1 in 10) */
511         tell_become_backup();
512
513         /* get their browse list from them and add it to ours. */
514         add_browser_entry(serv_name,dgram->dest_name.name_type,
515                           work->work_group,30,ip);
516 }
517
518 /*******************************************************************
519   process a master announcement frame
520   ******************************************************************/
521 static void process_master_announce(struct packet_struct *p,char *buf)
522 {
523         struct dgram_packet *dgram = &p->packet.dgram;
524         struct in_addr ip = dgram->header.source_ip;
525         struct domain_record *d = find_domain(ip);
526         struct domain_record *mydomain = find_domain(bcast_ip);
527         char *name = buf;
528         struct work_record *work;
529         name[15] = 0;
530
531         DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
532
533         if (same_context(dgram)) return;
534
535         if (!d || !mydomain) return;
536
537         if (!lp_domain_master()) return;
538
539     for (work = mydomain->workgrouplist; work; work = work->next)
540         {
541                 if (AM_MASTER(work))
542                 {
543                         /* merge browse lists with them */
544                         add_browser_entry(name,0x1b, work->work_group,30,ip);
545                 }
546         }
547 }
548
549 /*******************************************************************
550   process a receive backup list request
551   
552   we receive a list of servers, and we attempt to locate them all on
553   our local subnet, and sync browse lists with them on the workgroup
554   they are said to be in.
555   ******************************************************************/
556 static void process_rcv_backup_list(struct packet_struct *p,char *buf)
557 {
558         struct dgram_packet *dgram = &p->packet.dgram;
559         struct in_addr ip = dgram->header.source_ip;
560         int count = CVAL(buf,0);
561         int Index = IVAL(buf,1); /* caller's index representing workgroup */
562         char *buf1;
563
564         DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n",
565                                 namestr(&dgram->dest_name), inet_ntoa(ip),
566                                 count, Index));
567
568         if (same_context(dgram)) return;
569
570         if (count <= 0) return;
571
572         /* go through the list of servers attempting to sync browse lists */
573         for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
574         {
575                 struct in_addr back_ip;
576                 struct domain_record *d;
577
578                 DEBUG(4, ("Searching for backup browser %s at %s...\n",
579                                   buf1, inet_ntoa(ip)));
580
581                 /* XXXX assume name is a DNS name NOT a netbios name. a more complete
582                    approach is to use reply_name_query functionality to find the name */
583                 back_ip = *interpret_addr2(buf1);
584
585                 if (zero_ip(back_ip))
586                 {
587                         DEBUG(4,("Failed to find backup browser server using DNS\n"));
588                         continue;
589                 }
590
591                 DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
592
593                 if ((d = find_domain(back_ip)))
594                 {
595                         struct domain_record *d1;
596                         for (d1 = domainlist; d1; d1 = d1->next)
597                         {
598                                 struct work_record *work;
599                                 for (work = d1->workgrouplist; work; work = work->next)
600                                 {
601                                         if (work->token == Index)
602                                         {
603                                                 queue_netbios_packet(ClientNMB,NMB_QUERY,SERVER_CHECK,
604                                                                  work->work_group,0x1d,0,
605                                                  False,False,back_ip);
606                                                 return;
607                                         }
608                                 }
609                         }
610                 }
611         }
612 }
613
614 /*******************************************************************
615   process a send backup list request
616
617   A client send a backup list request to ask for a list of servers on
618   the net that maintain server lists for a domain. A server is then
619   chosen from this list to send NetServerEnum commands to to list
620   available servers.
621
622   Currently samba only sends back one name in the backup list, its
623   own. For larger nets we'll have to add backups and send "become
624   backup" requests occasionally.
625   ******************************************************************/
626 static void process_send_backup_list(struct packet_struct *p,char *buf)
627 {
628   struct dgram_packet *dgram = &p->packet.dgram;
629   struct in_addr ip = dgram->header.source_ip;
630   struct domain_record *d; /* = find_domain(ip); */
631   struct work_record *work;
632
633   int count = CVAL(buf,0);
634   int token = SVAL(buf,1); /* sender's key index for the workgroup? */
635   int info  = SVAL(buf,3); /* XXXX don't know: some sort of info */
636   int name_type = dgram->dest_name.name_type;
637
638   DEBUG(0,("Send Backup request to %s token=%d info = %x count=%d\n",
639            namestr(&dgram->dest_name), token, info, count));
640   
641   if (same_context(dgram)) return;
642   
643   if (count <= 0) return;
644   
645   if (name_type != 0x1b && name_type != 0x1d)
646     {
647       DEBUG(0, ("backup request to wrong type %d\n", name_type));
648       return;
649     }
650   
651   for (d = domainlist; d; d = d->next)
652     {
653       for (work = d->workgrouplist; work; work = work->next)
654         {
655           if (strequal(work->work_group, dgram->dest_name.name))
656             {
657               DEBUG(3, ("found workgroup %s(%d)\n",
658                         work->work_group, work->token));
659               send_backup_list(work->work_group,&dgram->source_name,
660                                count,token,info,name_type,ip);
661               return;
662             }
663         } 
664     }
665 }
666
667
668 /*******************************************************************
669   process a reset browser state
670
671   diagnostic packet:
672   0x1 - stop being a master browser
673   0x2 - discard browse lists, stop being a master browser, try again.
674   0x4 - stop being a master browser forever. no way. ain't gonna.
675          
676   ******************************************************************/
677 static void process_reset_browser(struct packet_struct *p,char *buf)
678 {
679         struct dgram_packet *dgram = &p->packet.dgram;
680         int state = CVAL(buf,0);
681
682         DEBUG(1,("Diagnostic browser reset request to %s state=0x%X\n",
683                   namestr(&dgram->dest_name), state));
684
685         /* stop being a master but still deal with being a backup browser */
686         if (state & 0x1)
687         {
688                 struct domain_record *d;
689                 for (d = domainlist; d; d = d->next)
690                 {
691                         struct work_record *work;
692                         for (work = d->workgrouplist; work; work = work->next)
693                         {
694                                 if (AM_MASTER(work))
695                                 {
696                                         become_nonmaster(d,work);
697                                 }
698                         }
699                 }
700         }
701
702         /* totally delete all servers and start afresh */
703         if (state & 0x2)
704         {
705                 struct domain_record *d;
706                 for (d = domainlist; d; d = d->next)
707                 {
708                         struct work_record *work;
709                         for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
710                 }
711                 add_my_domains();
712         }
713
714         /* stop browsing altogether. i don't think this is a good idea! */
715         if (state & 0x4)
716         {
717                 DEBUG(1, ("ignoring request to stop being a browser. sorry!\n"));
718         }
719 }
720
721
722 /*******************************************************************
723   process a announcement request
724
725   clients send these when they want everyone to send an announcement
726   immediately. This can cause quite a storm of packets!
727   ******************************************************************/
728 static void process_announce_request(struct packet_struct *p,char *buf)
729 {
730         struct dgram_packet *dgram = &p->packet.dgram;
731         struct work_record *work;
732         struct in_addr ip = dgram->header.source_ip;
733         struct domain_record *d = find_domain(ip);
734         int token = CVAL(buf,0);
735         char *name = buf+1;
736
737         name[15] = 0;
738
739         DEBUG(3,("Announce request from %s to %s token=0x%X\n",
740                   name,namestr(&dgram->dest_name), token));
741
742         if (strequal(dgram->source_name.name,myname)) return;
743
744         if (!d) return;
745
746         if (!ip_equal(bcast_ip, d->bcast_ip)) return;
747
748         for (work = d->workgrouplist; work; work = work->next)
749         {
750                 if (strequal(dgram->dest_name.name,work->work_group)) 
751                 {
752                         work->needannounce = True;
753                 }
754         }
755 }
756
757
758 /****************************************************************************
759    process a domain logon packet
760    **************************************************************************/
761 void process_logon_packet(struct packet_struct *p,char *buf,int len)
762 {
763         struct dgram_packet *dgram = &p->packet.dgram;
764         struct in_addr ip = dgram->header.source_ip;
765         struct domain_record *d = find_domain(ip);
766         char *logname,*q;
767         char *reply_name;
768         BOOL add_slashes = False;
769         pstring outbuf;
770         int code,reply_code;
771         struct work_record *work;
772
773         if (!d) return;
774
775         if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) 
776           return;
777
778    if (!lp_domain_logons()) {
779      DEBUG(3,("No domain logons\n"));
780      return;
781    }
782    if (!listening_name(work, &dgram->dest_name))
783    {
784      DEBUG(4,("Not listening to that domain\n"));
785      return;
786    }
787  
788    code = SVAL(buf,0);
789    switch (code) {
790    case 0:    
791      {
792        char *machine = buf+2;
793        char *user = skip_string(machine,1);
794        logname = skip_string(user,1);
795        reply_code = 6;
796        reply_name = myname;
797        add_slashes = True;
798        DEBUG(3,("Domain login request from %s(%s) user=%s\n",
799                machine,inet_ntoa(p->ip),user));
800      }
801      break;
802    case 7:    
803      {
804        char *machine = buf+2;
805        logname = skip_string(machine,1);
806        reply_code = 7;
807        reply_name = lp_domain_controller();
808        if (!*reply_name) {
809         DEBUG(3,("No domain controller configured\n"));
810         return;
811        }
812        DEBUG(3,("GETDC request from %s(%s)\n",
813                machine,inet_ntoa(p->ip)));
814      }
815      break;
816    default:
817      DEBUG(3,("Unknown domain request %d\n",code));
818      return;
819    }
820  
821    bzero(outbuf,sizeof(outbuf));
822    q = outbuf;
823    SSVAL(q,0,reply_code);
824    q += 2;
825    if (add_slashes) {
826      strcpy(q,"\\\\");
827      q += 2;
828    }
829    StrnCpy(q,reply_name,16);
830    strupper(q);
831    q = skip_string(q,1);
832    SSVAL(q,0,0xFFFF);
833    q += 2;
834  
835    send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
836                       myname,&dgram->source_name.name[0],0x20,0,p->ip,myip);  
837  }
838  
839
840 /****************************************************************************
841 depending on what announce has been made, we are only going to
842 accept certain types of name announce. XXXX untested code
843
844 check listening name type
845 ****************************************************************************/
846 BOOL listening_type(struct packet_struct *p, int command)
847 {
848         struct dgram_packet *dgram = &p->packet.dgram;
849         int type = dgram->dest_name.name_type;
850
851         switch (command)
852         {
853                 case 1: /* host announce */
854                 {
855                         if (type != 0x0 || type != 0x20) return (False);
856                         break;
857                 }
858
859                 case 2: /* announce request */
860                 {
861                         return (True);
862                         break;
863                 }
864
865                 case 8: /* election */
866                 {
867                         return (True);
868                         break;
869                 }
870
871                 case 9: /* get backup list */
872                 {
873                         return (True);
874                         break;
875                 }
876
877                 case 10: /* receive backup list */
878                 {
879                         return (True);
880                         break;
881                 }
882
883                 case 12: /* domain announce */
884                 {
885                         if (type != 0x1b || type != 0x1c) return (False);
886                         break;
887                 }
888
889                 case 13: /* master announcement */
890                 {
891                         if (type != 0x1d) return (False);
892                         break;
893                 }
894
895                 case 15: /* local master announce */
896                 {
897                         if (type != 0x1c || type != 0x1d) return (False);
898                         break;
899                 }
900         }
901         return (True); /* we're not dealing with unknown packet types */
902 }
903
904
905 /****************************************************************************
906 process a browse frame
907 ****************************************************************************/
908 void process_browse_packet(struct packet_struct *p,char *buf,int len)
909 {
910         int command = CVAL(buf,0);
911         switch (command) 
912         {
913                 case 1: /* host announce */
914                 case 12: /* domain announce */
915                 case 15: /* local master announce */
916                 {
917                         process_announce(p,command,buf+1);
918                         break;
919                 }
920
921                 case 2: /* announce request */
922                 {
923                         process_announce_request(p,buf+1);
924                         break;
925                 }
926
927                 case 8: /* election */
928                 {
929                         process_election(p,buf+1);
930                         break;
931                 }
932
933                 case 9: /* get backup list */
934                 {
935                         process_send_backup_list(p,buf+1);
936                         break;
937                 }
938
939                 case 10: /* receive backup list */
940                 {
941 #ifdef TEST_CODE
942                         struct dgram_packet *dgram = &p->packet.dgram;
943                         int i, j;
944
945                         DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n",
946                                    command, namestr(&dgram->source_name), 
947                                    inet_ntoa(p->ip), namestr(&dgram->dest_name)));
948
949                         for (i = 0; i < len; i+= 16)
950                         {
951                                 DEBUG(4, ("%3x char ", i));
952
953                                 for (j = 0; j < 16; j++)
954                                 {
955                                         unsigned char x = buf[i+j];
956                                         if (x < 32 || x > 127) x = '.';
957
958                                         if (i+j >= len) break;
959                                         DEBUG(4, ("%c", x));
960                                 }
961
962                                 DEBUG(4, (" hex ", i));
963
964                                 for (j = 0; j < 16; j++)
965                                 {
966                                         if (i+j >= len) break;
967                                         DEBUG(4, (" %02x", buf[i+j]));
968                                 }
969
970                                 DEBUG(4, ("\n"));
971                         }
972
973 #endif /* TEST_CODE */
974                         process_rcv_backup_list(p, buf+1);
975                         break;
976                 }
977
978                 case 11: /* reset browser state */
979                 {
980                         process_reset_browser(p, buf+1);
981                         break;
982                 }
983
984                 case 13: /* master announcement */
985                 {
986                         process_master_announce(p,buf+1);
987                         break;
988                 }
989
990 #ifdef TEST_CODE
991                 default:
992                 {
993                         struct dgram_packet *dgram = &p->packet.dgram;
994                         int i, j;
995
996                         DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n",
997                                    command, namestr(&dgram->source_name), 
998                                    inet_ntoa(p->ip), namestr(&dgram->dest_name)));
999
1000                         for (i = 0; i < len; i+= 16)
1001                         {
1002                                 DEBUG(4, ("%3x char ", i));
1003
1004                                 for (j = 0; j < 16; j++)
1005                                 {
1006                                         unsigned char x = buf[i+j];
1007                                         if (x < 32 || x > 127) x = '.';
1008
1009                                         if (i+j >= len) break;
1010                                         DEBUG(4, ("%c", x));
1011                                 }
1012
1013                                 DEBUG(4, (" hex ", i));
1014
1015                                 for (j = 0; j < 16; j++)
1016                                 {
1017                                         if (i+j >= len) break;
1018                                         DEBUG(4, (" %02x", buf[i+j]));
1019                                 }
1020
1021                                 DEBUG(4, ("\n"));
1022                         }
1023
1024                 }
1025 #endif /* TEST_CODE */
1026         }
1027 }
1028
1029
1030 /****************************************************************************
1031 process udp 138 datagrams
1032 ****************************************************************************/
1033 void process_dgram(struct packet_struct *p)
1034 {
1035   char *buf;
1036   char *buf2;
1037   int len;
1038   struct dgram_packet *dgram = &p->packet.dgram;
1039
1040   if (dgram->header.msg_type != 0x10 &&
1041       dgram->header.msg_type != 0x11 &&
1042       dgram->header.msg_type != 0x12) {
1043     /* don't process error packets etc yet */
1044     return;
1045   }
1046
1047   buf = &dgram->data[0];
1048   buf -= 4; /* XXXX for the pseudo tcp length - 
1049                someday I need to get rid of this */
1050
1051   if (CVAL(buf,smb_com) != SMBtrans) return;
1052
1053   len = SVAL(buf,smb_vwv11);
1054   buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
1055
1056   DEBUG(3,("datagram from %s to %s for %s of type %d len=%d\n",
1057            namestr(&dgram->source_name),namestr(&dgram->dest_name),
1058            smb_buf(buf),CVAL(buf2,0),len));
1059
1060  
1061   if (len <= 0) return;
1062
1063    if (strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
1064    {
1065      process_browse_packet(p,buf2,len);
1066    } else if (strequal(smb_buf(buf),"\\MAILSLOT\\NET\\NETLOGON")) {
1067      process_logon_packet(p,buf2,len);
1068    }
1069 }
1070