trans2 query file/path info - unix change times being reported as dos create
[bbaumbach/samba-autobuild/.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-1997
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 extern fstring myworkgroup;
41
42 extern int ClientNMB;
43 extern int ClientDGRAM;
44
45 extern struct in_addr ipzero;
46
47 extern int workgroup_count; /* total number of workgroups we know about */
48
49 /* this is our domain/workgroup/server database */
50 extern struct subnet_record *subnetlist;
51
52 extern int  updatecount;
53
54 /* backup request types: which servers are to be included */
55 #define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
56 #define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL   )
57
58 extern time_t StartupTime;
59
60 extern BOOL updatedlists;
61
62 /****************************************************************************
63 tell a server to become a backup browser
64 state - 0x01 become backup instead of master
65       - 0x02 remove all entries in browse list and become non-master
66       - 0x04 stop master browser service altogether. NT ignores this 
67 **************************************************************************/
68 void reset_server(char *name, int state, struct in_addr ip)
69 {
70   char outbuf[20];
71   char *p;
72
73   bzero(outbuf,sizeof(outbuf));
74   p = outbuf;
75
76   CVAL(p,0) = ANN_ResetBrowserState;
77   CVAL(p,2) = state; 
78   p += 2;
79
80   DEBUG(2,("sending reset to %s %s of state %d\n",
81            name,inet_ntoa(ip),state));
82
83   send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
84               outbuf,PTR_DIFF(p,outbuf),
85                       myname,name,0x20,0x1d,ip,*iface_ip(ip));
86 }
87
88
89 /****************************************************************************
90 tell a server to become a backup browser
91 **************************************************************************/
92 void tell_become_backup(void)
93 {
94   /* XXXX note: this function is currently unsuitable for use, as it
95      does not properly check that a server is in a fit state to become
96      a backup browser before asking it to be one.
97    */
98
99   struct subnet_record *d;
100   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
101     {
102       struct work_record *work;
103       for (work = d->workgrouplist; work; work = work->next)
104         {
105           struct server_record *s;
106           int num_servers = 0;
107           int num_backups = 0;
108           
109           for (s = work->serverlist; s; s = s->next)
110             {
111               if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
112               
113               num_servers++;
114               
115               if (strequal(myname, s->serv.name)) continue;
116               
117               if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
118                 num_backups++;
119                 continue;
120               }
121               
122               if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
123               
124               if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
125               
126               DEBUG(3,("num servers: %d num backups: %d\n", 
127                        num_servers, num_backups));
128               
129               /* make first server a backup server. thereafter make every
130                  tenth server a backup server */
131               if (num_backups != 0 && (num_servers+9) / num_backups > 10)
132                 {
133                   continue;
134                 }
135               
136               DEBUG(2,("sending become backup to %s %s for %s\n",
137                        s->serv.name, inet_ntoa(d->bcast_ip),
138                        work->work_group));
139               
140               /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
141               do_announce_request(s->serv.name, work->work_group,
142                                   ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
143             }
144         }
145     }
146 }
147
148
149 /*******************************************************************
150   same context: scope. should check name_type as well, and makes sure
151   we don't process messages from ourselves
152   ******************************************************************/
153 BOOL same_context(struct dgram_packet *dgram)
154 {
155   if (!strequal(dgram->dest_name  .scope,scope )) return(True);
156   if ( strequal(dgram->source_name.name ,myname)) return(True);
157   
158   return(False);
159 }
160
161
162 /*******************************************************************
163   process a domain announcement frame
164
165   Announce frames come in 3 types. Servers send host announcements
166   (command=1) to let the master browswer know they are
167   available. Master browsers send local master announcements
168   (command=15) to let other masters and backups that they are the
169   master. They also send domain announcements (command=12) to register
170   the domain
171
172   The comment field of domain announcements contains the master
173   browser name. The servertype is used by NetServerEnum to select
174   resources. We just have to pass it to smbd (via browser.dat) and let
175   the client choose using bit masks.
176   ******************************************************************/
177 static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf)
178 {
179   struct dgram_packet *dgram = &p->packet.dgram;
180   struct subnet_record *d = find_subnet(p->ip);  /* Explicitly exclude WINS - local nets only */
181   int update_count = CVAL(buf,0);
182
183   int ttl = IVAL(buf,1)/1000;
184   char *name = buf+5;
185   int osmajor=CVAL(buf,21);
186   int osminor=CVAL(buf,22);
187   uint32 servertype = IVAL(buf,23);
188   uint32 browse_type= CVAL(buf,27);
189   uint32 browse_sig = CVAL(buf,29);
190   char *comment = buf+31;
191
192   struct work_record *work;
193   char *work_name;
194   char *serv_name = dgram->source_name.name;
195   BOOL add = False;
196
197   comment[43] = 0;
198   
199   DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
200   DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n",
201            namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
202            servertype,browse_type,browse_sig,comment));
203   
204   name[15] = 0;  
205   
206   if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement)
207     {
208       DEBUG(2,("Announce to nametype(0) not supported yet\n"));
209       return;
210     }
211
212   if (command == ANN_DomainAnnouncement && 
213       ((!strequal(dgram->dest_name.name, MSBROWSE)) ||
214        dgram->dest_name.name_type != 0x1))
215     {
216       DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
217                 command, inet_ntoa(p->ip), namestr(&dgram->dest_name)));
218       return;
219     }
220   
221   if (!strequal(dgram->dest_name.scope,scope )) return;
222   
223   if (command == ANN_DomainAnnouncement) { 
224     /* XXXX if we are a master browser for the workgroup work_name,
225        then there is a local subnet configuration problem. only
226        we should be sending out such domain announcements, because
227        as the master browser, that is our job.
228
229        stop being a master browser, and force an election. this will
230        sort out the network problem. hopefully.
231      */
232
233     work_name = name;
234     add = True;
235   } else {
236     work_name = dgram->dest_name.name;
237   }
238
239   /* we need some way of finding out about new workgroups
240      that appear to be sending packets to us. The name_type checks make
241      sure we don't add host names as workgroups */
242   if (command == ANN_HostAnnouncement &&
243       (dgram->dest_name.name_type == 0x1d ||
244        dgram->dest_name.name_type == 0x1e))
245     add = True;
246   
247   DEBUG(4,("search for workgroup: %s (add? %s)\n",
248             work_name, BOOLSTR(add)));
249
250   if (!(work = find_workgroupstruct(d, work_name,add)))
251     return;
252   
253   DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
254   
255   ttl = GET_TTL(ttl);
256   
257   /* add them to our browse list, and update the browse.dat file */
258   add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
259   updatedlists = True;
260
261 #if 0
262   /* the tell become backup code is broken, no great harm is done by
263      disabling it */
264   tell_become_backup();
265 #endif
266
267 #if 0 /* JRA TEST - I Think this code should not be here */
268   /* get the local_only browse list from the local master and add it 
269      to ours. */
270   if (command == ANN_LocalMasterAnnouncement)
271   {
272     add_browser_entry(serv_name,dgram->dest_name.name_type,
273                       work->work_group,30,p->ip,True);
274   }
275 #endif /* END JRA TEST */
276 }
277
278 /*******************************************************************
279   process a master announcement frame
280   Domain master browsers recieve these from local masters. The Domain
281   master should then issue a sync with the local master, asking for
282   that machines local server list.
283   ******************************************************************/
284 static void process_master_announce(struct packet_struct *p,char *buf)
285 {
286   struct dgram_packet *dgram = &p->packet.dgram;
287   char *name = buf;
288   struct work_record *work;
289   name[15] = 0;
290   
291   DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
292   
293   if (same_context(dgram)) return;
294   
295   if (!wins_subnet) 
296     {
297       DEBUG(3,("process_master_announce: No wins subnet !\n"));
298       return;
299     }
300   
301   if (!lp_domain_master()) 
302     {
303       DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n"));
304       return;
305     }
306   
307   for (work = wins_subnet->workgrouplist; work; work = work->next)
308   {
309     if (AM_MASTER(work) || AM_DOMMST(work))
310     {
311           /* merge browse lists with them */
312           add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True);
313     }
314   }
315 }
316
317 /*******************************************************************
318   process a receive backup list request
319   
320   we receive a list of servers, and we attempt to locate them all on
321   our local subnet, and sync browse lists with them on the workgroup
322   they are said to be in.
323
324   XXXX NOTE: this function is in overdrive. it should not really do
325   half of what it actually does (it should pick _one_ name from the
326   list received and sync with it at regular intervals, rather than
327   sync with them all only once!)
328
329   ******************************************************************/
330 static void process_rcv_backup_list(struct packet_struct *p,char *buf)
331 {
332   struct dgram_packet *dgram = &p->packet.dgram;
333   int count = CVAL(buf,0);
334   uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
335   char *buf1;
336   
337   DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
338            namestr(&dgram->dest_name), inet_ntoa(p->ip),
339            count, info));
340   
341   if (same_context(dgram)) return;
342   
343   if (count <= 0) return;
344   
345   /* go through the list of servers attempting to sync browse lists */
346   for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
347   {
348     struct in_addr back_ip;
349     /* struct subnet_record *d; */
350       
351     DEBUG(4,("Searching for backup browser %s at %s...\n",
352                buf1, inet_ntoa(p->ip)));
353       
354     /* XXXX assume name is a DNS name NOT a netbios name. a more complete
355            approach is to use reply_name_query functionality to find the name */
356
357     back_ip = *interpret_addr2(buf1);
358       
359     if (zero_ip(back_ip))
360         {
361           DEBUG(4,("Failed to find backup browser server using DNS\n"));
362           continue;
363         }
364       
365       DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
366       DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
367       
368 #if 0
369       /* XXXX function needs work */
370       continue;
371
372     if ((d = find_subnet(back_ip)))
373         {
374           struct subnet_record *d1;
375           for (d1 = subnetlist; d1; d1 = d1->next)
376           {
377               struct work_record *work;
378               for (work = d1->workgrouplist; work; work = work->next)
379                 {
380                   if (work->token == 0 /* token */)
381                   {
382                       queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
383                                            work->work_group,0x1d,
384                        0,0,0,NULL,NULL,
385                                            False,False,back_ip,back_ip);
386                       return;
387                   }
388                 }
389           }
390         }
391 #endif
392   }
393 }
394
395
396 /****************************************************************************
397   send a backup list response.
398   **************************************************************************/
399 static void send_backup_list(char *work_name, struct nmb_name *src_name,
400                              int token, uint32 info,
401                              int name_type, struct in_addr ip)
402 {                     
403   char outbuf[1024];
404   char *p, *countptr, *nameptr;
405   int count = 0;
406   char *theirname = src_name->name;
407   
408   DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n", 
409            work_name, inet_ntoa(ip),
410            myname,0x0,theirname,0x0));     
411   
412   if (name_type == 0x1d)
413     {
414       DEBUG(4,("master browsers: "));
415     }
416   else if (name_type == 0x1b)
417     {
418       DEBUG(4,("domain controllers: "));
419     }
420   else
421     {
422       DEBUG(0,("backup request for unknown type %0x\n", name_type));
423       return;
424     }
425   
426   bzero(outbuf,sizeof(outbuf));
427   p = outbuf;
428   
429   CVAL(p,0) = ANN_GetBackupListResp;    /* backup list response */
430   
431   p++;
432   countptr = p;
433
434   SIVAL(p,1,info); /* the sender's unique info */
435
436   p += 5;
437   
438   nameptr = p;
439
440 #if 0
441
442   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
443   {
444       struct work_record *work;
445       
446       for (work = d->workgrouplist; work; work = work->next)
447         {
448           struct server_record *s;
449           
450           if (!strequal(work->work_group, work_name)) continue;
451           
452           for (s = work->serverlist; s; s = s->next)
453             { 
454               BOOL found = False;
455               char *n;
456               
457               if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
458               
459               for (n = nameptr; n < p; n = skip_string(n, 1))
460                 {
461                   if (strequal(n, s->serv.name)) found = True;
462                 }
463               
464               if (found) continue; /* exclude names already added */
465               
466               /* workgroup request: include all backup browsers in the list */
467               /* domain request: include all domain members in the list */
468
469               if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
470                       (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
471                 {                          
472                   DEBUG(4, ("%s ", s->serv.name));
473                   
474                   count++;
475                   strcpy(p,s->serv.name);
476                   strupper(p);
477                   p = skip_string(p,1);
478                 }
479          }
480         }
481   }
482
483 #endif
484
485         count++;
486         strcpy(p,myname);
487         strupper(p);
488         p = skip_string(p,1);
489
490   if (count == 0)
491     {
492       DEBUG(4, ("none\n"));
493     }
494   else
495     {
496       DEBUG(4, (" - count %d\n", count));
497     }
498   
499   CVAL(countptr, 0) = count;
500
501   {
502     int len = PTR_DIFF(p, outbuf);
503     debug_browse_data(outbuf, len);
504   }
505   send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
506               outbuf,PTR_DIFF(p,outbuf),
507                       myname,theirname,0x0,0x0,ip,*iface_ip(ip));
508 }
509
510
511 /*******************************************************************
512   process a send backup list request
513
514   A client sends a backup list request to ask for a list of servers on
515   the net that maintain server lists for a domain. A server is then
516   chosen from this list to send NetServerEnum commands to to list
517   available servers.
518
519   Currently samba only sends back one name in the backup list, its
520   own. For larger nets we'll have to add backups and send "become
521   backup" requests occasionally.
522   ******************************************************************/
523 static void process_send_backup_list(struct packet_struct *p,char *buf)
524 {
525   struct dgram_packet *dgram = &p->packet.dgram;
526   struct in_addr ip = dgram->header.source_ip;
527   struct subnet_record *d;
528   struct work_record *work;
529
530   int    token = CVAL(buf,0); /* sender's key index for the workgroup */
531   uint32 info  = IVAL(buf,1); /* XXXX don't know: some sort of info */
532   int name_type = dgram->dest_name.name_type;
533
534   if (same_context(dgram)) return;
535   
536   if (name_type != 0x1b && name_type != 0x1d) {
537     DEBUG(0,("backup request to wrong type %d from %s\n",
538               name_type,inet_ntoa(ip)));
539     return;
540   }
541   
542   for (d = subnetlist; d; d = d->next)
543     {
544       for (work = d->workgrouplist; work; work = work->next)
545         {
546           if (strequal(work->work_group, dgram->dest_name.name))
547             {
548               DEBUG(2,("sending backup list to %s %s id=%x\n",
549                        namestr(&dgram->dest_name),inet_ntoa(ip),info));
550   
551               send_backup_list(work->work_group,&dgram->source_name,
552                                token,info,name_type,ip);
553               return;
554             }
555         } 
556     }
557 }
558
559
560 /*******************************************************************
561   process a reset browser state
562
563   diagnostic packet:
564   0x1 - stop being a master browser and become a backup browser.
565   0x2 - discard browse lists, stop being a master browser, try again.
566   0x4 - stop being a master browser forever. no way. ain't gonna.
567          
568   ******************************************************************/
569 static void process_reset_browser(struct packet_struct *p,char *buf)
570 {
571   struct dgram_packet *dgram = &p->packet.dgram;
572   int state = CVAL(buf,0);
573
574   DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n",
575            namestr(&dgram->dest_name), state));
576
577   /* stop being a master but still deal with being a backup browser */
578   if (state & 0x1)
579     {
580       struct subnet_record *d;
581       for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
582         {
583           struct work_record *work;
584           for (work = d->workgrouplist; work; work = work->next)
585             {
586               if (AM_MASTER(work))
587                 {
588                   unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
589                 }
590             }
591         }
592     }
593   
594   /* XXXX documentation inconsistency: the above description does not
595      exactly tally with what is implemented for state & 0x2
596    */
597
598   /* totally delete all servers and start afresh */
599   if (state & 0x2)
600     {
601       struct subnet_record *d;
602       for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
603         {
604           struct work_record *work;
605           for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
606         }
607       add_my_subnets(myworkgroup);
608     }
609   
610   /* stop browsing altogether. i don't think this is a good idea! */
611   if (state & 0x4)
612     {
613       DEBUG(1,("ignoring request to stop being a browser. sorry!\n"));
614     }
615 }
616
617 /*******************************************************************
618   process a announcement request
619
620   clients send these when they want everyone to send an announcement
621   immediately. This can cause quite a storm of packets!
622   ******************************************************************/
623 static void process_announce_request(struct packet_struct *p,char *buf)
624 {
625   struct dgram_packet *dgram = &p->packet.dgram;
626   struct work_record *work;
627   struct in_addr ip = dgram->header.source_ip;
628   struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */
629   int token = CVAL(buf,0);
630   char *name = buf+1;
631   
632   name[15] = 0;
633   
634   DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n",
635            name,namestr(&dgram->dest_name), token));
636   
637   if (strequal(dgram->source_name.name,myname)) return;
638   
639   /* XXXX BUG or FEATURE?: need to ensure that we are a member of
640      this workgroup before announcing, particularly as we only
641      respond on local interfaces anyway.
642
643      if (strequal(dgram->dest_name, myworkgroup) return; ???
644    */
645
646   if (!d) 
647     {
648       DEBUG(3,("process_announce_request: No local interface to announce to %s\n",
649                 name));
650       return;
651     }
652  
653   for (work = d->workgrouplist; work; work = work->next)
654     {
655      /* XXXX BUG: the destination name type should also be checked,
656         not just the name. e.g if the name is WORKGROUP(0x1d) then
657         we should only respond if we own that name */
658     
659       if (strequal(dgram->dest_name.name,work->work_group)) 
660         {
661           work->needannounce = True;
662         }
663     }
664 }
665
666
667
668 /****************************************************************************
669 process a browse frame
670 ****************************************************************************/
671 void process_browse_packet(struct packet_struct *p,char *buf,int len)
672 {
673   int command = CVAL(buf,0);
674   switch (command) 
675     {
676     case ANN_HostAnnouncement:
677     case ANN_DomainAnnouncement:
678     case ANN_LocalMasterAnnouncement:
679       {
680         debug_browse_data(buf, len);
681         process_localnet_announce(p,command,buf+1);
682         break;
683       }
684       
685     case ANN_AnnouncementRequest:
686       {
687         process_announce_request(p,buf+1);
688         break;
689       }
690       
691     case ANN_Election:
692       {
693         process_election(p,buf+1);
694         break;
695       }
696       
697     case ANN_GetBackupListReq:
698       {
699         debug_browse_data(buf, len);
700         process_send_backup_list(p,buf+1);
701         break;
702       }
703       
704     case ANN_GetBackupListResp:
705     {
706         debug_browse_data(buf, len);
707         process_rcv_backup_list(p, buf+1);
708         break;
709     }
710       
711     case ANN_ResetBrowserState:
712       {
713         process_reset_browser(p, buf+1);
714         break;
715       }
716       
717     case ANN_MasterAnnouncement:
718       {
719         process_master_announce(p,buf+1);
720         break;
721       }
722       
723     default:
724       {
725         struct dgram_packet *dgram = &p->packet.dgram;
726         DEBUG(4,("ignoring browse packet %d from %s %s to %s\n",
727                  command, namestr(&dgram->source_name), 
728                  inet_ntoa(p->ip), namestr(&dgram->dest_name)));
729       }
730     }
731 }
732
733