patch to fix NetServerEnum with multiple workgroup lists kindly supplied.
[Samba.git] / source / namework.c
blobf0fca0071e3bc2d7f1b31ace9a60d15ce45b2976
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
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.
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.
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.
21 Revision History:
23 14 jan 96: lkcl@pires.co.uk
24 added multiple workgroup domain master support
28 #include "includes.h"
30 extern int ClientNMB;
31 extern int ClientDGRAM;
33 #define TEST_CODE /* want to debug unknown browse packets */
35 extern int DEBUGLEVEL;
36 extern pstring scope;
37 extern BOOL CanRecurse;
39 extern pstring myname;
41 extern int ClientNMB;
42 extern int ClientDGRAM;
44 extern struct in_addr ipzero;
46 extern int workgroup_count; /* total number of workgroups we know about */
48 /* this is our browse cache database */
49 extern struct browse_cache_record *browserlist;
51 /* this is our domain/workgroup/server database */
52 extern struct interface *local_interfaces;
54 /* this is our domain/workgroup/server database */
55 extern struct subnet_record *subnetlist;
57 /* machine comment for host announcements */
58 extern pstring ServerComment;
60 extern int updatecount;
62 /* what server type are we currently */
63 #define DFLT_SERVER_TYPE (SV_TYPE_WORKSTATION | SV_TYPE_SERVER | \
64 SV_TYPE_TIME_SOURCE | SV_TYPE_SERVER_UNIX |\
65 SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER)
67 /* backup request types: which servers are to be included */
68 #define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
69 #define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL )
71 extern time_t StartupTime;
73 #define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
75 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
78 /****************************************************************************
79 tell a server to become a backup browser
80 state - 0x01 become backup instead of master
81 - 0x02 remove all entries in browse list and become non-master
82 - 0x04 stop master browser service altogether. NT ignores this
83 **************************************************************************/
84 void reset_server(char *name, int state, struct in_addr ip)
86 char outbuf[20];
87 char *p;
89 bzero(outbuf,sizeof(outbuf));
90 p = outbuf;
92 CVAL(p,0) = ANN_ResetBrowserState;
93 CVAL(p,2) = state;
94 p += 2;
96 DEBUG(2,("sending reset to %s %s of state %d\n",
97 name,inet_ntoa(ip),state));
99 send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
100 myname,name,0x20,0x1d,ip,*iface_ip(ip));
104 /****************************************************************************
105 tell a server to become a backup browser
106 **************************************************************************/
107 void tell_become_backup(void)
109 struct subnet_record *d;
110 for (d = subnetlist; d; d = d->next)
112 struct work_record *work;
113 for (work = d->workgrouplist; work; work = work->next)
115 struct server_record *s;
116 int num_servers = 0;
117 int num_backups = 0;
119 for (s = work->serverlist; s; s = s->next)
121 if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
123 num_servers++;
125 if (strequal(myname, s->serv.name)) continue;
127 if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
128 num_backups++;
129 continue;
132 if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
134 if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
136 DEBUG(3,("num servers: %d num backups: %d\n",
137 num_servers, num_backups));
139 /* make first server a backup server. thereafter make every
140 tenth server a backup server */
141 if (num_backups != 0 && (num_servers+9) / num_backups > 10)
143 continue;
146 DEBUG(2,("sending become backup to %s %s for %s\n",
147 s->serv.name, inet_ntoa(d->bcast_ip),
148 work->work_group));
150 /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
151 do_announce_request(s->serv.name, work->work_group,
152 ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
158 /****************************************************************************
159 find a server responsible for a workgroup, and sync browse lists
160 **************************************************************************/
161 static void start_sync_browse_entry(struct browse_cache_record *b)
163 struct subnet_record *d;
164 struct work_record *work;
166 if (!(d = find_subnet(b->ip))) return;
168 /* only sync if we are the master */
169 if (AM_MASTER(work)) {
171 /* first check whether the group we intend to sync with exists. if it
172 doesn't, the server must have died. o dear. */
174 /* see response_netbios_packet() or expire_netbios_response_entries() */
175 queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SYNC,
176 b->group,0x20,0,0,
177 False,False,b->ip);
180 b->synced = True;
184 /****************************************************************************
185 search through browser list for an entry to sync with
186 **************************************************************************/
187 void do_browser_lists(void)
189 struct browse_cache_record *b;
190 static time_t last = 0;
191 time_t t = time(NULL);
193 if (t-last < 20) return; /* don't do too many of these at once! */
194 /* XXXX equally this period should not be too long
195 the server may die in the intervening gap */
197 last = t;
199 /* pick any entry in the list, preferably one whose time is up */
200 for (b = browserlist; b && b->next; b = b->next)
202 if (b->sync_time < t && b->synced == False) break;
205 if (b && !b->synced)
207 /* sync with the selected entry then remove some dead entries */
208 start_sync_browse_entry(b);
209 expire_browse_cache(t - 60);
215 /****************************************************************************
216 find a server responsible for a workgroup, and sync browse lists
217 control ends up back here via response_name_query.
218 **************************************************************************/
219 void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
220 int name_type,
221 struct in_addr ip)
223 add_browser_entry(serv_name, name_type, work_name, 0, ip);
225 if (cmd == NAME_QUERY_MST_SRV_CHK)
227 /* announce ourselves as a master browser to serv_name */
228 do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
229 0x20, 0, ip);
234 /****************************************************************************
235 add the default workgroup into my domain
236 **************************************************************************/
237 void add_my_subnets(char *group)
239 struct interface *i;
241 /* add or find domain on our local subnet, in the default workgroup */
243 if (*group == '*') return;
245 /* the coding choice is up to you, andrew: i can see why you don't want
246 global access to the local_interfaces structure: so it can't get
247 messed up! */
248 for (i = local_interfaces; i; i = i->next)
250 add_subnet_entry(i->bcast,i->nmask,group, True, False);
255 /****************************************************************************
256 send a backup list response.
257 **************************************************************************/
258 static void send_backup_list(char *work_name, struct nmb_name *src_name,
259 int info_count, int token, int info,
260 int name_type, struct in_addr ip)
262 struct subnet_record *d;
263 char outbuf[1024];
264 char *p, *countptr, *nameptr;
265 int count = 0;
266 int i, j;
267 char *theirname = src_name->name;
269 DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
270 work_name, inet_ntoa(ip),
271 myname,0x20,theirname,0x0));
273 if (name_type == 0x1d)
275 DEBUG(4,("master browsers: "));
277 else if (name_type == 0x1b)
279 DEBUG(4,("domain controllers: "));
281 else
283 DEBUG(0,("backup request for unknown type %0x\n", name_type));
284 return;
287 bzero(outbuf,sizeof(outbuf));
288 p = outbuf;
290 CVAL(p,0) = 10; /* backup list response */
291 p++;
293 countptr = p; /* count pointer */
295 SSVAL(p,1,token); /* sender's workgroup index representation */
296 SSVAL(p,3,info); /* XXXX clueless: info, usually zero */
297 p += 5;
299 nameptr = p;
301 for (d = subnetlist; d; d = d->next)
303 struct work_record *work;
305 for (work = d->workgrouplist; work; work = work->next)
307 struct server_record *s;
309 if (!strequal(work->work_group, work_name)) continue;
311 for (s = work->serverlist; s; s = s->next)
313 BOOL found = False;
314 char *n;
316 if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
318 for (n = nameptr; n < p; n = skip_string(n, 1))
320 if (strequal(n, s->serv.name)) found = True;
323 if (found) continue; /* exclude names already added */
325 /* workgroup request: include all backup browsers in the list */
326 /* domain request: include all domain members in the list */
328 if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
329 (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
331 DEBUG(4, ("%s ", s->serv.name));
333 count++;
334 strcpy(p,s->serv.name);
335 strupper(p);
336 p = skip_string(p,1);
342 if (count == 0)
344 DEBUG(4, ("none\n"));
345 return;
347 else
349 DEBUG(4, (" - count %d\n", count));
352 CVAL(countptr,0) = count; /* total number of backup browsers found */
355 int len = PTR_DIFF(p, outbuf);
357 for (i = 0; i < len; i+= 16)
359 DEBUG(4, ("%3x char ", i));
361 for (j = 0; j < 16; j++)
363 unsigned char x = outbuf[i+j];
364 if (x < 32 || x > 127) x = '.';
366 if (i+j >= len) break;
367 DEBUG(4, ("%c", x));
370 DEBUG(4, (" hex ", i));
372 for (j = 0; j < 16; j++)
374 if (i+j >= len) break;
375 DEBUG(4, (" %02x", outbuf[i+j]));
378 DEBUG(4, ("\n"));
382 send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
383 myname,theirname,0x20,0,ip,*iface_ip(ip));
387 /*******************************************************************
388 same context: scope. should check name_type as well, and makes sure
389 we don't process messages from ourselves
390 ******************************************************************/
391 BOOL same_context(struct dgram_packet *dgram)
393 if (!strequal(dgram->dest_name .scope,scope )) return(True);
394 if ( strequal(dgram->source_name.name ,myname)) return(True);
396 return(False);
400 /*******************************************************************
401 am I listening on a name. XXXX check the type of name as well.
402 ******************************************************************/
403 BOOL listening_name(struct work_record *work, struct nmb_name *n)
405 if (strequal(n->name,myname) ||
406 strequal(n->name,work->work_group) ||
407 strequal(n->name,MSBROWSE))
409 return(True);
412 return(False);
416 /*******************************************************************
417 process a domain announcement frame
419 Announce frames come in 3 types. Servers send host announcements
420 (command=1) to let the master browswer know they are
421 available. Master browsers send local master announcements
422 (command=15) to let other masters and backups that they are the
423 master. They also send domain announcements (command=12) to register
424 the domain
426 The comment field of domain announcements contains the master
427 browser name. The servertype is used by NetServerEnum to select
428 resources. We just have to pass it to smbd (via browser.dat) and let
429 the client choose using bit masks.
430 ******************************************************************/
431 static void process_announce(struct packet_struct *p,int command,char *buf)
433 struct dgram_packet *dgram = &p->packet.dgram;
434 struct in_addr ip = dgram->header.source_ip;
435 struct subnet_record *d = find_subnet(ip);
436 int update_count = CVAL(buf,0);
437 int ttl = IVAL(buf,1)/1000;
438 char *name = buf+5;
439 int osmajor=CVAL(buf,21);
440 int osminor=CVAL(buf,22);
441 uint32 servertype = IVAL(buf,23);
442 char *comment = buf+31;
443 struct work_record *work;
444 char *work_name;
445 char *serv_name = dgram->source_name.name;
446 BOOL add = False;
448 comment[43] = 0;
450 DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
451 DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
452 namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
453 servertype,comment));
455 name[15] = 0;
457 if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement)
459 DEBUG(2,("Announce to nametype(0) not supported yet\n"));
460 return;
463 if (command == ANN_DomainAnnouncement &&
464 ((!strequal(dgram->dest_name.name, MSBROWSE)) ||
465 dgram->dest_name.name_type != 0x1))
467 DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
468 command, inet_ntoa(ip), namestr(&dgram->dest_name)));
469 return;
472 if (same_context(dgram)) return;
474 if (command == ANN_DomainAnnouncement) {
475 work_name = name;
476 } else {
477 work_name = dgram->dest_name.name;
480 /* we need some way of finding out about new workgroups
481 that appear to be sending packets to us. The name_type checks make
482 sure we don't add host names as workgroups */
483 if (command == ANN_HostAnnouncement &&
484 (dgram->dest_name.name_type == 0x1d ||
485 dgram->dest_name.name_type == 0x1e))
486 add = True;
488 if (!(work = find_workgroupstruct(d, work_name,add)))
489 return;
491 DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
493 ttl = GET_TTL(ttl);
495 /* add them to our browse list */
496 add_server_entry(d,work,name,servertype,ttl,comment,True);
498 #if 0
499 /* the tell become backup code is broken, no great harm is done by
500 disabling it */
501 tell_become_backup();
502 #endif
504 /* get their browse list from them and add it to ours. */
505 add_browser_entry(serv_name,dgram->dest_name.name_type,
506 work->work_group,30,ip);
509 /*******************************************************************
510 process a master announcement frame
511 ******************************************************************/
512 static void process_master_announce(struct packet_struct *p,char *buf)
514 struct dgram_packet *dgram = &p->packet.dgram;
515 struct in_addr ip = dgram->header.source_ip;
516 struct subnet_record *d = find_subnet(ip);
517 struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
518 char *name = buf;
519 struct work_record *work;
520 name[15] = 0;
522 DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
524 if (same_context(dgram)) return;
526 if (!d || !mydomain) return;
528 if (!lp_domain_master()) return;
530 for (work = mydomain->workgrouplist; work; work = work->next)
532 if (AM_MASTER(work))
534 /* merge browse lists with them */
535 add_browser_entry(name,0x1b, work->work_group,30,ip);
540 /*******************************************************************
541 process a receive backup list request
543 we receive a list of servers, and we attempt to locate them all on
544 our local subnet, and sync browse lists with them on the workgroup
545 they are said to be in.
546 ******************************************************************/
547 static void process_rcv_backup_list(struct packet_struct *p,char *buf)
549 struct dgram_packet *dgram = &p->packet.dgram;
550 struct in_addr ip = dgram->header.source_ip;
551 int count = CVAL(buf,0);
552 int Index = IVAL(buf,1); /* caller's index representing workgroup */
553 char *buf1;
555 DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n",
556 namestr(&dgram->dest_name), inet_ntoa(ip),
557 count, Index));
559 if (same_context(dgram)) return;
561 if (count <= 0) return;
563 /* go through the list of servers attempting to sync browse lists */
564 for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
566 struct in_addr back_ip;
567 struct subnet_record *d;
569 DEBUG(4,("Searching for backup browser %s at %s...\n",
570 buf1, inet_ntoa(ip)));
572 /* XXXX assume name is a DNS name NOT a netbios name. a more complete
573 approach is to use reply_name_query functionality to find the name */
574 back_ip = *interpret_addr2(buf1);
576 if (zero_ip(back_ip))
578 DEBUG(4,("Failed to find backup browser server using DNS\n"));
579 continue;
582 DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
584 if ((d = find_subnet(back_ip)))
586 struct subnet_record *d1;
587 for (d1 = subnetlist; d1; d1 = d1->next)
589 struct work_record *work;
590 for (work = d1->workgrouplist; work; work = work->next)
592 if (work->token == Index)
594 queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
595 work->work_group,0x1d,0,0,
596 False,False,back_ip);
597 return;
605 /*******************************************************************
606 process a send backup list request
608 A client send a backup list request to ask for a list of servers on
609 the net that maintain server lists for a domain. A server is then
610 chosen from this list to send NetServerEnum commands to to list
611 available servers.
613 Currently samba only sends back one name in the backup list, its
614 own. For larger nets we'll have to add backups and send "become
615 backup" requests occasionally.
616 ******************************************************************/
617 static void process_send_backup_list(struct packet_struct *p,char *buf)
619 struct dgram_packet *dgram = &p->packet.dgram;
620 struct in_addr ip = dgram->header.source_ip;
621 struct subnet_record *d;
622 struct work_record *work;
624 int count = CVAL(buf,0);
625 int token = SVAL(buf,1); /* sender's key index for the workgroup? */
626 int info = SVAL(buf,3); /* XXXX don't know: some sort of info */
627 int name_type = dgram->dest_name.name_type;
629 if (same_context(dgram)) return;
631 if (count <= 0) return;
633 if (name_type != 0x1b && name_type != 0x1d) {
634 DEBUG(0,("backup request to wrong type %d from %s\n",
635 name_type,inet_ntoa(ip)));
636 return;
639 for (d = subnetlist; d; d = d->next)
641 for (work = d->workgrouplist; work; work = work->next)
643 if (strequal(work->work_group, dgram->dest_name.name))
645 DEBUG(2,("sending backup list to %s %s count=%d\n",
646 namestr(&dgram->dest_name),inet_ntoa(ip),count));
648 send_backup_list(work->work_group,&dgram->source_name,
649 count,token,info,name_type,ip);
650 return;
657 /*******************************************************************
658 process a reset browser state
660 diagnostic packet:
661 0x1 - stop being a master browser
662 0x2 - discard browse lists, stop being a master browser, try again.
663 0x4 - stop being a master browser forever. no way. ain't gonna.
665 ******************************************************************/
666 static void process_reset_browser(struct packet_struct *p,char *buf)
668 struct dgram_packet *dgram = &p->packet.dgram;
669 int state = CVAL(buf,0);
671 DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n",
672 namestr(&dgram->dest_name), state));
674 /* stop being a master but still deal with being a backup browser */
675 if (state & 0x1)
677 struct subnet_record *d;
678 for (d = subnetlist; d; d = d->next)
680 struct work_record *work;
681 for (work = d->workgrouplist; work; work = work->next)
683 if (AM_MASTER(work))
685 become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
691 /* totally delete all servers and start afresh */
692 if (state & 0x2)
694 struct subnet_record *d;
695 for (d = subnetlist; d; d = d->next)
697 struct work_record *work;
698 for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
700 add_my_subnets(lp_workgroup());
703 /* stop browsing altogether. i don't think this is a good idea! */
704 if (state & 0x4)
706 DEBUG(1,("ignoring request to stop being a browser. sorry!\n"));
711 /*******************************************************************
712 process a announcement request
714 clients send these when they want everyone to send an announcement
715 immediately. This can cause quite a storm of packets!
716 ******************************************************************/
717 static void process_announce_request(struct packet_struct *p,char *buf)
719 struct dgram_packet *dgram = &p->packet.dgram;
720 struct work_record *work;
721 struct in_addr ip = dgram->header.source_ip;
722 struct subnet_record *d = find_subnet(ip);
723 int token = CVAL(buf,0);
724 char *name = buf+1;
726 name[15] = 0;
728 DEBUG(3,("Announce request from %s to %s token=0x%X\n",
729 name,namestr(&dgram->dest_name), token));
731 if (strequal(dgram->source_name.name,myname)) return;
733 if (!d) return;
735 if (!d->my_interface) return;
737 for (work = d->workgrouplist; work; work = work->next)
739 if (strequal(dgram->dest_name.name,work->work_group))
741 work->needannounce = True;
747 /****************************************************************************
748 process a domain logon packet
749 **************************************************************************/
750 void process_logon_packet(struct packet_struct *p,char *buf,int len)
752 struct dgram_packet *dgram = &p->packet.dgram;
753 struct in_addr ip = dgram->header.source_ip;
754 struct subnet_record *d = find_subnet(ip);
755 char *logname,*q;
756 char *reply_name;
757 BOOL add_slashes = False;
758 pstring outbuf;
759 int code,reply_code;
760 struct work_record *work;
762 if (!d) return;
764 if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
765 return;
767 if (!lp_domain_logons()) {
768 DEBUG(3,("No domain logons\n"));
769 return;
771 if (!listening_name(work, &dgram->dest_name))
773 DEBUG(4,("Not listening to that domain\n"));
774 return;
777 code = SVAL(buf,0);
778 switch (code) {
779 case 0:
781 char *machine = buf+2;
782 char *user = skip_string(machine,1);
783 logname = skip_string(user,1);
784 reply_code = 6;
785 reply_name = myname;
786 add_slashes = True;
787 DEBUG(3,("Domain login request from %s(%s) user=%s\n",
788 machine,inet_ntoa(p->ip),user));
790 break;
791 case 7:
793 char *machine = buf+2;
794 logname = skip_string(machine,1);
795 reply_code = 7;
796 reply_name = lp_domain_controller();
797 if (!*reply_name) {
798 DEBUG(3,("No domain controller configured\n"));
799 return;
801 DEBUG(3,("GETDC request from %s(%s)\n",
802 machine,inet_ntoa(p->ip)));
804 break;
805 default:
806 DEBUG(3,("Unknown domain request %d\n",code));
807 return;
810 bzero(outbuf,sizeof(outbuf));
811 q = outbuf;
812 SSVAL(q,0,reply_code);
813 q += 2;
814 if (add_slashes) {
815 strcpy(q,"\\\\");
816 q += 2;
818 StrnCpy(q,reply_name,16);
819 strupper(q);
820 q = skip_string(q,1);
821 SSVAL(q,0,0xFFFF);
822 q += 2;
824 send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
825 myname,&dgram->source_name.name[0],0x20,0,p->ip,
826 *iface_ip(p->ip));
830 /****************************************************************************
831 depending on what announce has been made, we are only going to
832 accept certain types of name announce. XXXX untested code
834 check listening name type
835 ****************************************************************************/
836 BOOL listening_type(struct packet_struct *p, int command)
838 struct dgram_packet *dgram = &p->packet.dgram;
839 int type = dgram->dest_name.name_type;
841 switch (command)
843 case ANN_HostAnnouncement:
845 if (type != 0x0 || type != 0x20) return (False);
846 break;
849 case ANN_AnnouncementRequest:
851 return (True);
852 break;
855 case ANN_Election:
857 return (True);
858 break;
861 case ANN_GetBackupListReq:
863 return (True);
864 break;
867 case ANN_GetBackupListResp:
869 return (True);
870 break;
873 case ANN_DomainAnnouncement:
875 if (type != 0x1b || type != 0x1c) return (False);
876 break;
879 case ANN_MasterAnnouncement:
881 if (type != 0x1d) return (False);
882 break;
885 case ANN_LocalMasterAnnouncement:
887 if (type != 0x1c || type != 0x1d) return (False);
888 break;
891 return (True); /* we're not dealing with unknown packet types */
895 /****************************************************************************
896 process a browse frame
897 ****************************************************************************/
898 void process_browse_packet(struct packet_struct *p,char *buf,int len)
900 int command = CVAL(buf,0);
901 switch (command)
903 case ANN_HostAnnouncement:
904 case ANN_DomainAnnouncement:
905 case ANN_LocalMasterAnnouncement:
907 process_announce(p,command,buf+1);
908 break;
911 case ANN_AnnouncementRequest:
913 process_announce_request(p,buf+1);
914 break;
917 case ANN_Election:
919 process_election(p,buf+1);
920 break;
923 case ANN_GetBackupListReq:
925 process_send_backup_list(p,buf+1);
926 break;
929 case ANN_GetBackupListResp:
931 process_rcv_backup_list(p, buf+1);
932 break;
935 case ANN_ResetBrowserState:
937 process_reset_browser(p, buf+1);
938 break;
941 case ANN_MasterAnnouncement:
943 process_master_announce(p,buf+1);
944 break;
947 default:
949 struct dgram_packet *dgram = &p->packet.dgram;
950 DEBUG(4,("ignoring browse packet %d from %s %s to %s\n",
951 command, namestr(&dgram->source_name),
952 inet_ntoa(p->ip), namestr(&dgram->dest_name)));
958 /****************************************************************************
959 process udp 138 datagrams
960 ****************************************************************************/
961 void process_dgram(struct packet_struct *p)
963 char *buf;
964 char *buf2;
965 int len;
966 struct dgram_packet *dgram = &p->packet.dgram;
968 if (dgram->header.msg_type != 0x10 &&
969 dgram->header.msg_type != 0x11 &&
970 dgram->header.msg_type != 0x12) {
971 /* don't process error packets etc yet */
972 return;
975 buf = &dgram->data[0];
976 buf -= 4; /* XXXX for the pseudo tcp length -
977 someday I need to get rid of this */
979 if (CVAL(buf,smb_com) != SMBtrans) return;
981 len = SVAL(buf,smb_vwv11);
982 buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
984 DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n",
985 namestr(&dgram->source_name),namestr(&dgram->dest_name),
986 smb_buf(buf),CVAL(buf2,0),len));
989 if (len <= 0) return;
991 if (strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
993 process_browse_packet(p,buf2,len);
994 } else if (strequal(smb_buf(buf),"\\MAILSLOT\\NET\\NETLOGON")) {
995 process_logon_packet(p,buf2,len);