7b72f93952a079e369107b41c5ef51f9f55b3dff
[samba.git] / source / nameserv.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1995
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Revision History:
22
23    14 jan 96: lkcl@pires.co.uk
24    added multiple workgroup domain master support
25
26 */
27
28 #include "includes.h"
29
30 extern int ClientNMB;
31 extern int ClientDGRAM;
32
33 #define FIND_SELF  0x01
34 #define FIND_WINS  0x02
35 #define FIND_LOCAL 0x04
36
37 extern int DEBUGLEVEL;
38
39 extern pstring scope;
40 extern BOOL CanRecurse;
41 extern pstring myname;
42 extern struct in_addr ipzero;
43 extern struct in_addr ipgrp;
44
45 extern struct subnet_record *subnetlist;
46
47 #define WINS_LIST "wins.dat"
48
49 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
50
51 /****************************************************************************
52   finds the appropriate subnet structure. directed packets (non-bcast) are
53   assumed to come from a point-to-point (P or M node), and so the subnet we
54   return in this instance is the WINS 'pseudo-subnet' with ip 255.255.255.255
55   ****************************************************************************/
56 static struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast)
57 {
58   if (bcast)
59   {
60     /* identify the subnet the broadcast request came from */
61     return find_subnet(*iface_bcast(ip));
62   }
63   /* find the subnet under the pseudo-ip of 255.255.255.255 */
64   return find_subnet(ipgrp);
65 }
66
67 /****************************************************************************
68   true if two netbios names are equal
69 ****************************************************************************/
70 static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
71 {
72   if (n1->name_type != n2->name_type) return(False);
73
74   return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
75 }
76
77 /****************************************************************************
78   add a netbios name into the namelist
79   **************************************************************************/
80 static void add_name(struct subnet_record *d, struct name_record *n)
81 {
82   struct name_record *n2;
83
84   if (!d) return;
85
86   if (!d->namelist)
87   {
88     d->namelist = n;
89     n->prev = NULL;
90     n->next = NULL;
91     return;
92   }
93
94   for (n2 = d->namelist; n2->next; n2 = n2->next) ;
95
96   n2->next = n;
97   n->next = NULL;
98   n->prev = n2;
99 }
100
101 /****************************************************************************
102   remove a name from the namelist. The pointer must be an element just 
103   retrieved
104   **************************************************************************/
105 void remove_name(struct subnet_record *d, struct name_record *n)
106 {
107   struct name_record *nlist;
108   if (!d) return;
109
110   nlist = d->namelist;
111
112   while (nlist && nlist != n) nlist = nlist->next;
113
114   if (nlist)
115   {
116     if (nlist->next) nlist->next->prev = nlist->prev;
117     if (nlist->prev) nlist->prev->next = nlist->next;
118     free(nlist);
119   }
120 }
121
122
123 /****************************************************************************
124   find a name in a namelist 
125   **************************************************************************/
126 static struct name_record *find_name(struct name_record *n,
127                         struct nmb_name *name,
128                         int search, struct in_addr ip)
129 {
130   struct name_record *ret;
131   
132         for (ret = n; ret; ret = ret->next)
133     {
134                 if (name_equal(&ret->name,name))
135                 {
136                         /* self search: self names only */
137                         if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
138                                 continue;
139       
140                         if (zero_ip(ip) || ip_equal(ip, ret->ip))
141                         {
142       return ret;
143     }
144                 }
145         }
146     return NULL;
147 }
148
149
150 /****************************************************************************
151   find a name in the domain database namelist 
152   search can be any of:
153   FIND_SELF - look exclusively for names the samba server has added for itself
154   FIND_LOCAL - look for names in the local subnet record.
155   FIND_WINS - look for names in the WINS record
156   **************************************************************************/
157 static struct name_record *find_name_search(struct subnet_record **d,
158                         struct nmb_name *name,
159                         int search, struct in_addr ip)
160 {
161         if (d == NULL) return NULL; /* bad error! */
162   
163     if ((search & FIND_LOCAL) == FIND_LOCAL)
164         {
165                 if (*d != NULL)
166         {
167                         return find_name((*d)->namelist, name, search, ip);
168                 }
169         else
170         {
171                         DEBUG(4,("local find_name_search with a NULL subnet pointer\n"));
172   return NULL;
173 }
174         }
175
176         if ((search & FIND_WINS) != FIND_WINS) return NULL;
177
178         if (*d == NULL)
179         {
180                 /* find WINS subnet record */
181                 *d = find_subnet(ipgrp);
182     }
183
184         if (*d == NULL) return NULL;
185
186         return find_name((*d)->namelist, name, search, ip);
187 }
188
189
190 /****************************************************************************
191   dump a copy of the name table
192   **************************************************************************/
193 void dump_names(void)
194 {
195   struct name_record *n;
196   struct subnet_record *d;
197   fstring fname, fnamenew;
198   time_t t = time(NULL);
199   
200   FILE *f;
201   
202   strcpy(fname,lp_lockdir());
203   trim_string(fname,NULL,"/");
204   strcat(fname,"/");
205   strcat(fname,WINS_LIST);
206   strcpy(fnamenew,fname);
207   strcat(fnamenew,".");
208   
209   f = fopen(fnamenew,"w");
210   
211   if (!f)
212   {
213     DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
214   }
215   
216   DEBUG(3,("Dump of local name table:\n"));
217   
218   for (d = subnetlist; d; d = d->next)
219    for (n = d->namelist; n; n = n->next)
220     {
221       if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER)
222       {
223         fstring data;
224
225       /* XXXX i have little imagination as to how to output nb_flags as
226          anything other than a hexadecimal number :-) */
227
228         sprintf(data, "%s#%02x %s %ld %2x",
229                n->name.name,n->name.name_type, /* XXXX ignore the scope for now */
230                inet_ntoa(n->ip),
231                n->death_time,
232                n->nb_flags);
233             fprintf(f, "%s\n", data);
234       }
235
236           DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip)));
237           DEBUG(3,("%15s ", inet_ntoa(d->mask_ip)));
238       DEBUG(3,("%s %15s TTL=%15d NBFLAGS=%2x\n",
239                namestr(&n->name),
240                inet_ntoa(n->ip),
241                n->death_time?n->death_time-t:0,
242                n->nb_flags));
243     }
244
245   fclose(f);
246   unlink(fname);
247   chmod(fnamenew,0644);
248   rename(fnamenew,fname);   
249
250   DEBUG(3,("Wrote wins database %s\n",fname));
251 }
252
253 /****************************************************************************
254 load a netbios name database file
255 ****************************************************************************/
256 void load_netbios_names(void)
257 {
258   struct subnet_record *d = find_subnet(ipgrp);
259   fstring fname;
260
261   FILE *f;
262   pstring line;
263
264   if (!d) return;
265
266   strcpy(fname,lp_lockdir());
267   trim_string(fname,NULL,"/");
268   strcat(fname,"/");
269   strcat(fname,WINS_LIST);
270
271   f = fopen(fname,"r");
272
273   if (!f) {
274     DEBUG(2,("Can't open wins database file %s\n",fname));
275     return;
276   }
277
278   while (!feof(f))
279     {
280       pstring name_str, ip_str, ttd_str, nb_flags_str;
281
282       pstring name;
283       int type = 0;
284       int nb_flags;
285       time_t ttd;
286           struct in_addr ipaddr;
287
288           enum name_source source;
289
290       char *ptr;
291           int count = 0;
292
293       char *p;
294
295       if (!fgets_slash(line,sizeof(pstring),f)) continue;
296
297       if (*line == '#') continue;
298
299         ptr = line;
300
301         if (next_token(&ptr,name_str    ,NULL)) ++count;
302         if (next_token(&ptr,ip_str      ,NULL)) ++count;
303         if (next_token(&ptr,ttd_str     ,NULL)) ++count;
304         if (next_token(&ptr,nb_flags_str,NULL)) ++count;
305
306         if (count <= 0) continue;
307
308         if (count != 4) {
309           DEBUG(0,("Ill formed wins line"));
310           DEBUG(0,("[%s]: name#type ip nb_flags abs_time\n",line));
311           continue;
312         }
313
314       /* netbios name. # divides the name from the type (hex): netbios#xx */
315       strcpy(name,name_str);
316
317       p = strchr(name,'#');
318
319       if (p) {
320             *p = 0;
321             sscanf(p+1,"%x",&type);
322       }
323
324       /* decode the netbios flags (hex) and the time-to-die (seconds) */
325           sscanf(nb_flags_str,"%x",&nb_flags);
326           sscanf(ttd_str,"%ld",&ttd);
327
328           ipaddr = *interpret_addr2(ip_str);
329
330       if (ip_equal(ipaddr,ipzero)) {
331          source = SELF;
332       }
333       else
334       {
335          source = REGISTER;
336       }
337
338       DEBUG(4, ("add WINS line: %s#%02x %s %ld %2x\n",
339                name,type, inet_ntoa(ipaddr), ttd, nb_flags));
340
341       /* add all entries that have 60 seconds or more to live */
342       if (ttd - 10 < time(NULL) || ttd == 0)
343       {
344         time_t t = (ttd?ttd-time(NULL):0) / 3;
345
346         /* add netbios entry read from the wins.dat file. IF it's ok */
347         add_netbios_entry(d,name,type,nb_flags,t,source,ipaddr,True,True);
348       }
349     }
350
351   fclose(f);
352 }
353
354
355 /****************************************************************************
356   remove an entry from the name list
357   ****************************************************************************/
358 void remove_netbios_name(struct subnet_record *d,
359                         char *name,int type, enum name_source source,
360                          struct in_addr ip)
361 {
362   struct nmb_name nn;
363   struct name_record *n;
364   int search = FIND_LOCAL;
365
366   /* if it's not a special browser name, search the WINS database */
367   if (type != 0x01 && type != 0x1d && type != 0x1e)
368     search |= FIND_WINS;
369   
370   make_nmb_name(&nn, name, type, scope);
371   n = find_name_search(&d, &nn, search, ip);
372   
373   if (n && n->source == source) remove_name(d,n);
374 }
375
376
377 /****************************************************************************
378   add an entry to the name list.
379
380   this is a multi-purpose function.
381
382   it adds samba's own names in to its records on each interface, keeping a
383   record of whether it is a master browser, domain master, or WINS server.
384
385   it also keeps a record of WINS entries (names of type 0x00, 0x20, 0x03 etc)
386
387   ****************************************************************************/
388 struct name_record *add_netbios_entry(struct subnet_record *d,
389                 char *name, int type, int nb_flags, 
390                 int ttl, enum name_source source, struct in_addr ip,
391                 BOOL new_only,BOOL wins)
392 {
393   struct name_record *n;
394   struct name_record *n2=NULL;
395   int search = 0;
396   BOOL self = source == SELF;
397
398   /* add the name to the WINS list if the name comes from a directed query */
399   search |= wins ? FIND_WINS : FIND_LOCAL;
400   /* search for SELF names only */
401   search |= self ? FIND_SELF : 0;
402
403   if (!self)
404   {
405     if (wins)
406     {
407           if (type == 0x01 || type == 0x1d || type == 0x1e)
408       {
409          /* XXXX WINS server supposed to ignore special browser names. hm.
410             but is a primary domain controller supposed to ignore special
411             browser names? luke doesn't think so, but can't test it! :-)
412           */
413          return NULL;
414       }
415     }
416     else /* !wins */
417     {
418        /* the only broadcast (non-WINS) names we are adding are ours (SELF) */
419        return NULL;
420     }
421   }
422
423   n = (struct name_record *)malloc(sizeof(*n));
424   if (!n) return(NULL);
425
426   bzero((char *)n,sizeof(*n));
427
428   make_nmb_name(&n->name,name,type,scope);
429
430   if ((n2 = find_name_search(&d, &n->name, search, new_only?ipzero:ip)))
431   {
432     free(n);
433     if (new_only || (n2->source==SELF && source!=SELF)) return n2;
434     n = n2;
435   }
436
437   if (ttl) n->death_time = time(NULL)+ttl*3;
438   n->ip = ip;
439   n->nb_flags = nb_flags;
440   n->source = source;
441   
442   if (!n2) add_name(d,n);
443
444   DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n",
445                 namestr(&n->name),inet_ntoa(ip),ttl,nb_flags));
446
447   return(n);
448 }
449
450
451 /****************************************************************************
452   remove an entry from the name list
453   ****************************************************************************/
454 void remove_name_entry(struct subnet_record *d, char *name,int type)
455 {
456   if (lp_wins_support())
457     {
458       /* we are a WINS server. */
459       /* XXXX assume that if we are a WINS server that we are therefore
460          not pointing to another WINS server as well. this may later NOT
461          actually be true */
462       remove_netbios_name(d,name,type,SELF,ipzero);
463     }
464   else
465     {
466       /* not a WINS server: cannot just remove our own names: we have to
467          ask permission from the WINS server, or if no reply is received,
468                  _then_ we can remove the name */
469       
470           struct name_record n;
471           struct name_record *n2=NULL;
472       
473       make_nmb_name(&n.name,name,type,scope);
474
475       if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
476       {
477         /* check name isn't already being de-registered */
478                 if (NAME_DEREG(n2->nb_flags))
479           return;
480
481                 /* mark the name as in the process of deletion. */
482          n2->nb_flags &= NB_DEREG;
483       }
484       queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
485                              name, type, 0, 0,
486                              False, True, ipzero);
487     }
488 }
489
490
491 /****************************************************************************
492   add an entry to the name list
493   ****************************************************************************/
494 void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
495 {
496   BOOL re_reg = False;
497   struct nmb_name n;
498
499   if (!d) return;
500
501   /* not that it particularly matters, but if the SELF name already exists,
502      it must be re-registered, rather than just registered */
503
504   make_nmb_name(&n, name, type, scope);
505   if (find_name(d->namelist, &n, SELF, ipzero))
506         re_reg = True;
507
508   /* always add our own entries */
509   add_netbios_entry(d,name,type,nb_flags,0,SELF,ipzero,False,lp_wins_support());
510
511   if (!lp_wins_support())
512     {
513       /* we aren't supporting WINS: register name using broadcast or
514          contact WINS server */
515       
516       queue_netbios_pkt_wins(d,ClientNMB,
517                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
518                              name, type, nb_flags, GET_TTL(0),
519                              False, True, ipzero);
520     }
521 }
522
523
524 /****************************************************************************
525   add the magic samba names, useful for finding samba servers
526   **************************************************************************/
527 void add_my_names(void)
528 {
529   BOOL wins = lp_wins_support();
530   struct subnet_record *d;
531
532   struct in_addr ip = ipzero;
533   
534   /* each subnet entry, including the WINS one, must have its own
535      netbios name. */
536   /* XXXX if there was a transport layer added to samba (ipx/spx, netbeui
537      etc) then there would be yet _another_ for-loop, this time on the
538      transport type */
539   for (d = subnetlist; d; d = d->next)
540   {
541         add_my_name_entry(d, myname,0x20,NB_ACTIVE);
542         add_my_name_entry(d, myname,0x03,NB_ACTIVE);
543         add_my_name_entry(d, myname,0x00,NB_ACTIVE);
544         add_my_name_entry(d, myname,0x1f,NB_ACTIVE);
545
546         add_netbios_entry(d,"*",0x0,NB_ACTIVE,0,SELF,ip,False,wins);
547         add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins);
548         add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
549
550     if (wins) {
551     /* the 0x1c name gets added by any WINS server it seems */
552           add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
553   }
554 }
555 }
556
557
558 /****************************************************************************
559   remove all the samba names... from a WINS server if necessary.
560   **************************************************************************/
561 void remove_my_names()
562 {
563   struct subnet_record *d;
564
565   for (d = subnetlist; d; d = d->next)
566   {
567   struct name_record *n;
568   
569           for (n = d->namelist; n; n = n->next)
570     {
571       if (n->source == SELF)
572         {
573           /* get all SELF names removed from the WINS server's database */
574                   remove_name_entry(d,n->name.name, n->name.name_type);
575                 }
576         }
577     }
578 }
579
580
581 /*******************************************************************
582   refresh my own names
583   ******************************************************************/
584 void refresh_my_names(time_t t)
585 {
586   static time_t lasttime = 0;
587
588   if (t - lasttime < REFRESH_TIME) 
589     return;
590   lasttime = t;
591
592   add_my_names();
593 }
594
595 /*******************************************************************
596   queries names occasionally. an over-cautious, non-trusting WINS server!
597   ******************************************************************/
598 void query_refresh_names(void)
599 {
600         struct name_record *n;
601         struct subnet_record *d = find_subnet(ipgrp);
602
603         static time_t lasttime = 0;
604         time_t t = time(NULL);
605
606         int count = 0;
607         int name_refresh_time = NAME_POLL_REFRESH_TIME;
608         int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
609         if (max_count > 10) max_count = 10;
610
611         name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
612
613         /* if (!lp_poll_wins()) return; polling of registered names allowed */
614
615         if (!d) return;
616
617         if (t - lasttime < NAME_POLL_INTERVAL) return;
618
619         for (n = d->namelist; n; n = n->next)
620         {
621                 /* only do unique, registered names */
622
623                 if (n->source != REGISTER) continue;
624                 if (!NAME_GROUP(n->nb_flags)) continue;
625
626                 if (n->refresh_time < t)
627                 {
628                   DEBUG(3,("Polling name %s\n", namestr(&n->name)));
629                   
630           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
631                                 n->name.name, n->name.name_type,
632                                 0,0,
633                                 False,False,n->ip);
634                   count++;
635                 }
636
637                 if (count >= max_count)
638                 {
639                         /* don't do too many of these at once, but do enough to
640                            cover everyone in the list */
641                         return;
642                 }
643
644                 /* this name will be checked on again, if it's not removed */
645                 n->refresh_time += name_refresh_time;
646         }
647 }
648
649
650 /*******************************************************************
651   expires old names in the namelist
652   ******************************************************************/
653 void expire_names(time_t t)
654 {
655   struct name_record *n;
656   struct name_record *next;
657         struct subnet_record *d;
658   
659   /* expire old names */
660         for (d = subnetlist; d; d = d->next)
661         {
662           for (n = d->namelist; n; n = next)
663     {
664       if (n->death_time && n->death_time < t)
665         {
666           DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
667           
668           next = n->next;
669           
670           if (n->prev) n->prev->next = n->next;
671           if (n->next) n->next->prev = n->prev;
672           
673                   if (d->namelist == n) d->namelist = n->next; 
674           
675           free(n);
676         }
677       else
678         {
679           next = n->next;
680         }
681     }
682 }
683 }
684
685
686 /****************************************************************************
687   response for a reg release received. samba has asked a WINS server if it
688   could release a name.
689   **************************************************************************/
690 void response_name_release(struct subnet_record *d, struct packet_struct *p)
691 {
692   struct nmb_packet *nmb = &p->packet.nmb;
693   char *name = nmb->question.question_name.name;
694   int   type = nmb->question.question_name.name_type;
695   
696   DEBUG(4,("response name release received\n"));
697   
698   if (nmb->header.rcode == 0 && nmb->answers->rdata)
699     {
700       /* IMPORTANT: see expire_netbios_response_entries() */
701
702       struct in_addr found_ip;
703       putip((char*)&found_ip,&nmb->answers->rdata[2]);
704       
705       if (ismyip(found_ip))
706         {
707             remove_netbios_name(d,name,type,SELF,found_ip);
708         }
709     }
710   else
711     {
712       DEBUG(2,("name release for %s rejected!\n",
713                namestr(&nmb->question.question_name)));
714
715                 /* XXXX do we honestly care if our name release was rejected? 
716            only if samba is issuing the release on behalf of some out-of-sync
717            server. if it's one of samba's SELF names, we don't care. */
718     }
719 }
720
721
722 /****************************************************************************
723   reply to a name release
724   ****************************************************************************/
725 void reply_name_release(struct packet_struct *p)
726 {
727   struct nmb_packet *nmb = &p->packet.nmb;
728   struct in_addr ip;
729   int rcode=0;
730   int opcode = nmb->header.opcode;  
731   int nb_flags = nmb->additional->rdata[0];
732   BOOL bcast = nmb->header.nm_flags.bcast;
733   struct name_record *n;
734   struct subnet_record *d = NULL;
735   char rdata[6];
736   int search = 0;
737   
738   putip((char *)&ip,&nmb->additional->rdata[2]);  
739   
740   DEBUG(3,("Name release on name %s rcode=%d\n",
741            namestr(&nmb->question.question_name),rcode));
742   
743   if (!(d = find_req_subnet(p->ip, bcast)))
744   {
745     DEBUG(3,("response packet: bcast %s not known\n",
746                         inet_ntoa(p->ip)));
747     return;
748   }
749
750   if (bcast)
751         search &= FIND_LOCAL;
752   else
753         search &= FIND_WINS;
754
755   n = find_name_search(&d, &nmb->question.question_name, 
756                                         search, ip);
757   
758   /* XXXX under what conditions should we reject the removal?? */
759   if (n && n->nb_flags == nb_flags)
760     {
761       /* success = True;
762          rcode = 6; */
763       
764       remove_name(d,n);
765       n = NULL;
766     }
767   
768   if (bcast) return;
769   
770   rdata[0] = nb_flags;
771   rdata[1] = 0;
772   putip(&rdata[2],(char *)&ip);
773   
774   /* Send a NAME RELEASE RESPONSE */
775   reply_netbios_packet(p,nmb->header.name_trn_id,
776                        rcode,opcode,True,
777                        &nmb->question.question_name,
778                        nmb->question.question_type,
779                        nmb->question.question_class,
780                        0,
781                        rdata, 6);
782 }
783
784
785 /****************************************************************************
786   response for a reg request received
787   **************************************************************************/
788 void response_name_reg(struct subnet_record *d, struct packet_struct *p)
789 {
790   struct nmb_packet *nmb = &p->packet.nmb;
791   char *name = nmb->question.question_name.name;
792   int   type = nmb->question.question_name.name_type;
793   BOOL bcast = nmb->header.nm_flags.bcast;
794   
795   DEBUG(4,("response name registration received!\n"));
796   
797   if (nmb->header.rcode == 0 && nmb->answers->rdata)
798     {
799       /* IMPORTANT: see expire_netbios_response_entries() */
800
801       int nb_flags = nmb->answers->rdata[0];
802       struct in_addr found_ip;
803       int ttl = nmb->answers->ttl;
804       enum name_source source = REGISTER;
805       
806       putip((char*)&found_ip,&nmb->answers->rdata[2]);
807       
808       if (ismyip(found_ip)) source = SELF;
809       
810       add_netbios_entry(d, name,type,nb_flags,ttl,source,found_ip,True,!bcast);
811     }
812   else
813     {
814                 struct work_record *work;
815
816       DEBUG(1,("name registration for %s rejected!\n",
817                namestr(&nmb->question.question_name)));
818
819           /* XXXX oh dear. we have problems. must deal with our name having
820          been rejected: e.g if it was our GROUP(1d) name, we must unbecome
821          a master browser. */
822         
823                 if (!(work = find_workgroupstruct(d, name, False))) return;
824
825         /* remove_netbios_name(d,name,type,SELF,ipzero); */
826
827                 if (AM_MASTER(work) && (type == 0x1d || type == 0x1b))
828                 {
829                         int remove_type = 0;
830                         if (type == 0x1d) remove_type = SV_TYPE_MASTER_BROWSER;
831                         if (type == 0x1b) remove_type = SV_TYPE_DOMAIN_MASTER;
832                         
833                         become_nonmaster(d, work, remove_type);
834                 }
835     }
836 }
837
838
839 /****************************************************************************
840   reply to a reg request
841   **************************************************************************/
842 void reply_name_reg(struct packet_struct *p)
843 {
844   struct nmb_packet *nmb = &p->packet.nmb;
845   struct nmb_name *question = &nmb->question.question_name;
846   
847   struct nmb_name *reply_name = question;
848   char *qname = question->name;
849   int name_type  = question->name_type;
850   int name_class = nmb->question.question_class;
851   
852   BOOL bcast = nmb->header.nm_flags.bcast;
853   
854   int ttl = GET_TTL(nmb->additional->ttl);
855   int nb_flags = nmb->additional->rdata[0];
856   BOOL group = NAME_GROUP(nb_flags);
857   int rcode = 0;  
858   int opcode = nmb->header.opcode;  
859   
860   struct subnet_record *d = NULL;
861   struct name_record *n = NULL;
862   BOOL success = True;
863   BOOL recurse = True; /* true if samba replies yes/no: false if caller */
864   /* must challenge the current owner of the unique name */
865   char rdata[6];
866   struct in_addr ip, from_ip;
867   int search = 0;
868   
869   putip((char *)&from_ip,&nmb->additional->rdata[2]);
870   ip = from_ip;
871   
872   DEBUG(3,("Name registration for name %s at %s rcode=%d\n",
873            namestr(question),inet_ntoa(ip),rcode));
874   
875   if (group)
876     {
877       /* apparently we should return 255.255.255.255 for group queries
878          (email from MS) */
879       ip = ipgrp;
880     }
881   
882   if (!(d = find_req_subnet(p->ip, bcast)))
883   {
884     DEBUG(3,("response packet: bcast %s not known\n",
885                                 inet_ntoa(p->ip)));
886     return;
887   }
888
889   if (bcast)
890         search &= FIND_LOCAL;
891   else
892         search &= FIND_WINS;
893
894   /* see if the name already exists */
895   n = find_name_search(&d, question, search, from_ip);
896   
897   if (n)
898     {
899       if (!group) /* unique names */
900         {
901           if (n->source == SELF || NAME_GROUP(n->nb_flags))
902             {
903               /* no-one can register one of samba's names, nor can they
904                  register a name that's a group name as a unique name */
905               
906               rcode = 6;
907               success = False;
908             }
909           else if(!ip_equal(ip, n->ip))
910             {
911               /* hm. this unique name doesn't belong to them. */
912               
913               /* XXXX rfc1001.txt says:
914                * if we are doing secured WINS, we must send a Wait-Acknowledge
915                * packet (WACK) to the person who wants the name, then do a
916                * name query on the person who currently owns the unique name.
917                * if the current owner still says they own it, the person who wants
918                    * the name can't have it. if they do not, or are not alive, they can.
919                *
920                * if we are doing non-secured WINS (which is much simpler) then
921                * we send a message to the person wanting the name saying 'he
922                * owns this name: i don't want to hear from you ever again
923                * until you've checked with him if you can have it!'. we then
924                * abandon the registration. once the person wanting the name
925                * has checked with the current owner, they will repeat the
926                * registration packet if the current owner is dead or doesn't
927                * want the name.
928                */
929               
930               /* non-secured WINS implementation: caller is responsible
931                  for checking with current owner of name, then getting back
932                  to us... IF current owner no longer owns the unique name */
933               
934               rcode = 0;
935               success = False;
936               recurse = False;
937               
938               /* we inform on the current owner to the caller (which is
939                  why it's non-secure */
940               
941               reply_name = &n->name;
942               
943               /* name_type  = ?;
944                  name_class = ?;
945                  XXXX sorry, guys: i really can't see what name_type
946                  and name_class should be set to according to rfc1001 */
947             }
948           else
949             {
950               n->ip = ip;
951               n->death_time = ttl?p->timestamp+ttl*3:0;
952               DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip)));
953             }
954         }
955       else
956         {
957           /* refresh the name */
958           if (n->source != SELF)
959             {
960               n->death_time = ttl?p->timestamp + ttl*3:0;
961             }
962         }
963
964     /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
965     /* names that people have checked for and not found get DNSFAILed. 
966        we need to update the name record if someone then registers */
967
968     if (n->source == DNSFAIL)
969       n->source = REGISTER;
970
971     }
972   else
973     {
974       /* add the name to our name/subnet, or WINS, database */
975       n = add_netbios_entry(d,qname,name_type,nb_flags,ttl,REGISTER,ip,
976                                 True,!bcast);
977     }
978   
979   if (bcast) return;
980   
981   rdata[0] = nb_flags;
982   rdata[1] = 0;
983   putip(&rdata[2],(char *)&ip);
984   
985   /* Send a NAME REGISTRATION RESPONSE (pos/neg)
986      or an END-NODE CHALLENGE REGISTRATION RESPONSE */
987   reply_netbios_packet(p,nmb->header.name_trn_id,
988                        rcode,opcode,recurse,
989                        reply_name, name_type, name_class,
990                        ttl,
991                        rdata, 6);
992 }
993
994
995 /****************************************************************************
996   reply to a name status query
997   ****************************************************************************/
998 void reply_name_status(struct packet_struct *p)
999 {
1000   struct nmb_packet *nmb = &p->packet.nmb;
1001   char *qname   = nmb->question.question_name.name;
1002   int ques_type = nmb->question.question_name.name_type;
1003   char rdata[MAX_DGRAM_SIZE];
1004   char *countptr, *buf, *bufend;
1005   int names_added;
1006   struct name_record *n;
1007   struct subnet_record *d = NULL;
1008
1009   BOOL bcast = nmb->header.nm_flags.bcast;
1010   
1011   if (!(d = find_req_subnet(p->ip, bcast)))
1012   {
1013     DEBUG(3,("Name status req: bcast %s not known\n",
1014                         inet_ntoa(p->ip)));
1015     return;
1016   }
1017   
1018   DEBUG(3,("Name status for name %s %s\n",
1019            namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
1020   
1021   n = find_name_search(&d, &nmb->question.question_name,
1022                                 FIND_SELF|FIND_LOCAL,
1023                                 p->ip);
1024   
1025   if (!n) return;
1026     
1027   /* XXXX hack, we should calculate exactly how many will fit */
1028   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
1029   countptr = buf = rdata;
1030   buf += 1;
1031   
1032   names_added = 0;
1033   
1034   for (n = d->namelist ; n && buf < bufend; n = n->next) 
1035     {
1036       int name_type = n->name.name_type;
1037       
1038       if (n->source != SELF) continue;
1039       
1040       /* start with first bit of putting info in buffer: the name */
1041       
1042       bzero(buf,18);
1043       sprintf(buf,"%-15.15s",n->name.name);
1044       strupper(buf);
1045       
1046       /* now check if we want to exclude other workgroup names
1047          from the response. if we don't exclude them, windows clients
1048          get confused and will respond with an error for NET VIEW */
1049       
1050       if (name_type >= 0x1b && name_type <= 0x20 && 
1051           ques_type >= 0x1b && ques_type <= 0x20)
1052         {
1053           if (!strequal(qname, n->name.name)) continue;
1054         }
1055       
1056       /* carry on putting name info in buffer */
1057       
1058       buf[15] = name_type;
1059       buf[16]  = n->nb_flags;
1060       
1061       buf += 18;
1062       
1063       names_added++;
1064     }
1065     
1066   SCVAL(countptr,0,names_added);
1067   
1068   /* XXXXXXX we should fill in more fields of the statistics structure */
1069   bzero(buf,64);
1070   {
1071     extern int num_good_sends,num_good_receives;
1072     SIVAL(buf,20,num_good_sends);
1073     SIVAL(buf,24,num_good_receives);
1074   }
1075   
1076   SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */
1077   
1078   buf += 64;
1079   
1080   /* Send a POSITIVE NAME STATUS RESPONSE */
1081   reply_netbios_packet(p,nmb->header.name_trn_id,
1082                        0,0,True,
1083                        &nmb->question.question_name,
1084                        nmb->question.question_type,
1085                        nmb->question.question_class,
1086                        0,
1087                        rdata,PTR_DIFF(buf,rdata));
1088 }
1089
1090
1091 /***************************************************************************
1092   reply to a name query
1093   ****************************************************************************/
1094 struct name_record *search_for_name(struct subnet_record **d,
1095                                         struct nmb_name *question,
1096                                     struct in_addr ip, int Time, int search)
1097 {
1098   int name_type = question->name_type;
1099   char *qname = question->name;
1100   BOOL dns_type = name_type == 0x20 || name_type == 0;
1101   
1102   struct name_record *n;
1103   
1104   DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip)));
1105   
1106   /* first look up name in cache */
1107   n = find_name_search(d,question,search,ip);
1108   
1109   if (*d == NULL) return NULL;
1110   
1111   /* now try DNS lookup. */
1112   if (!n)
1113     {
1114       struct in_addr dns_ip;
1115       unsigned long a;
1116       
1117       /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
1118       if (!dns_type)
1119         {
1120           DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n"));
1121           return NULL;
1122         }
1123       
1124       /* look it up with DNS */      
1125       a = interpret_addr(qname);
1126       
1127       putip((char *)&dns_ip,(char *)&a);
1128       
1129       if (!a)
1130         {
1131           /* no luck with DNS. We could possibly recurse here XXXX */
1132           DEBUG(3,("no recursion.\n"));
1133       /* add the fail to our WINS cache of names. give it 1 hour in the cache */
1134           add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,
1135                                                 True, True);
1136           return NULL;
1137         }
1138       
1139       /* add it to our WINS cache of names. give it 2 hours in the cache */
1140       n = add_netbios_entry(*d,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
1141                                                 True,True);
1142       
1143       /* failed to add it? yikes! */
1144       if (!n) return NULL;
1145     }
1146   
1147   /* is our entry already dead? */
1148   if (n->death_time)
1149     {
1150       if (n->death_time < Time) return False;
1151     }
1152   
1153   /* it may have been an earlier failure */
1154   if (n->source == DNSFAIL)
1155     {
1156       DEBUG(3,("DNSFAIL\n"));
1157       return NULL;
1158     }
1159   
1160   DEBUG(3,("OK %s\n",inet_ntoa(n->ip)));      
1161   
1162   return n;
1163 }
1164
1165
1166 /***************************************************************************
1167 reply to a name query.
1168
1169 with broadcast name queries:
1170
1171         - only reply if the query is for one of YOUR names. all other machines on
1172           the network will be doing the same thing (that is, only replying to a
1173           broadcast query if they own it)
1174           NOTE: broadcast name queries should only be sent out by a machine
1175           if they HAVEN'T been configured to use WINS. this is generally bad news
1176           in a wide area tcp/ip network and should be rectified by the systems
1177           administrator. USE WINS! :-)
1178         - the exception to this is if the query is for a Primary Domain Controller
1179           type name (0x1b), in which case, a reply is sent.
1180
1181         - NEVER send a negative response to a broadcast query. no-one else will!
1182
1183 with directed name queries:
1184
1185         - if you are the WINS server, you are expected to respond with either
1186       a negative response, a positive response, or a wait-for-acknowledgement
1187       packet, and then later on a pos/neg response.
1188
1189   ****************************************************************************/
1190 void reply_name_query(struct packet_struct *p)
1191 {
1192   struct nmb_packet *nmb = &p->packet.nmb;
1193   struct nmb_name *question = &nmb->question.question_name;
1194   int name_type = question->name_type;
1195   BOOL bcast = nmb->header.nm_flags.bcast;
1196   int ttl=0;
1197   int rcode = 0;
1198   int nb_flags = 0;
1199   struct in_addr retip;
1200   char rdata[6];
1201   struct subnet_record *d = NULL;
1202
1203   BOOL success = True;
1204   
1205   struct name_record *n;
1206   int search = 0;
1207
1208   if (name_type == 0x20 || name_type == 0x00 || name_type == 0x1b ||
1209       name_type == 0x1f || name_type == 0x03 || name_type == 0x01 ||
1210       name_type == 0x1c)
1211   {
1212     /* search for any of the non-'special browser' names, or for a PDC type
1213        (0x1b) name in the WINS database.
1214        XXXX should we include name type 0x1c: WINS server type?
1215      */
1216         search |= FIND_WINS;
1217   }
1218   else
1219   {
1220         /* special browser name types e.g 
1221        ^1^2__MSBROWSE__^2^1, GROUP(1d) and GROUP(1e)
1222
1223        name_type == 0x01 || name_type == 0x1d || name_type == 0x1e.
1224
1225        XXXX luke reckons we should be able to search for any SELF name
1226        in the WINS database, if we are a primary domain controller.
1227      */
1228
1229     if (!(d = find_req_subnet(p->ip, bcast)))
1230     {
1231       DEBUG(3,("name query: bcast %s not known\n",
1232                                   inet_ntoa(p->ip)));
1233       success = False;
1234     }
1235
1236     /* XXXX delete if shouldn't search for SELF names in WINS database */
1237     search |= FIND_WINS;
1238   }
1239
1240   if (bcast)
1241   {
1242     /* a name query has been made by a non-WINS configured host. search the
1243        local interface database as well */
1244     search |= FIND_LOCAL;
1245   }
1246
1247   DEBUG(3,("Name query "));
1248   
1249   if (search == 0)
1250   {
1251     /* eh? no criterion for searching database. help! */
1252     success = False;
1253   }
1254
1255   if (success && (n = search_for_name(&d,question,p->ip,p->timestamp, search)))
1256     {
1257       /* don't respond to broadcast queries unless the query is for
1258          a name we own or it is for a Primary Domain Controller name */
1259
1260       if (bcast && n->source != SELF && name_type != 0x1b) {
1261           if (!lp_wins_proxy() || same_net(p->ip,n->ip,*iface_nmask(p->ip))) {
1262             /* never reply with a negative response to broadcast queries */
1263             return;
1264           }
1265         }
1266
1267       /* name is directed query, or it's self, or it's a PDC type name, or
1268              we're replying on behalf of a caller because they are on a different
1269          subnet and cannot hear the broadcast. XXXX lp_wins_proxy should be
1270                  switched off in environments where broadcasts are forwarded */
1271
1272       ttl = n->death_time - p->timestamp;
1273       retip = n->ip;
1274       nb_flags = n->nb_flags;
1275     }
1276   else
1277     {
1278       if (bcast) return; /* never reply negative response to bcasts */
1279       success = False;
1280     }
1281
1282   /* if the IP is 0 then substitute my IP */
1283   if (zero_ip(retip)) retip = *iface_ip(p->ip);
1284   
1285   if (success)
1286     {
1287       rcode = 0;
1288       DEBUG(3,("OK %s\n",inet_ntoa(retip)));      
1289     }
1290   else
1291     {
1292       rcode = 3;
1293       DEBUG(3,("UNKNOWN\n"));      
1294     }
1295   
1296   if (success)
1297     {
1298       rdata[0] = nb_flags;
1299       rdata[1] = 0;
1300       putip(&rdata[2],(char *)&retip);
1301     }
1302   
1303   reply_netbios_packet(p,nmb->header.name_trn_id,
1304                        rcode,0,True,
1305                        &nmb->question.question_name,
1306                        nmb->question.question_type,
1307                        nmb->question.question_class,
1308                        ttl,
1309                        rdata, success ? 6 : 0);
1310 }
1311
1312
1313 /****************************************************************************
1314   response from a name query server check. commands of type NAME_QUERY_MST_SRV_CHK,
1315   NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
1316   ****************************************************************************/
1317 static void response_server_check(struct nmb_name *ans_name, 
1318                 struct response_record *n, struct subnet_record *d)
1319 {
1320     /* issue another command: this time to do a name status check */
1321
1322     enum cmd_type cmd = (n->cmd_type == NAME_QUERY_MST_SRV_CHK) ?
1323               NAME_STATUS_MASTER_CHECK : NAME_STATUS_CHECK;
1324
1325     /* initiate a name status check on the server that replied */
1326     queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
1327                                 ans_name->name, ans_name->name_type,
1328                                 0,0,
1329                                 False,False,n->to_ip);
1330 }
1331
1332 /****************************************************************************
1333   response from a name status check. commands of type NAME_STATUS_MASTER_CHECK
1334   and NAME_STATUS_CHECK dealt with here.
1335 ****************************************************************************/
1336 static void response_name_status_check(struct in_addr ip,
1337                 struct nmb_packet *nmb, BOOL bcast,
1338                 struct response_record *n, struct subnet_record *d)
1339 {
1340         /* NMB_STATUS arrives: contains workgroup name and server name required.
1341        amongst other things. */
1342
1343         struct nmb_name name;
1344         fstring serv_name;
1345
1346         if (interpret_node_status(d,nmb->answers->rdata,
1347                                   &name,0x1d,serv_name,ip,bcast))
1348     {
1349                 if (*serv_name)
1350                 {
1351                         sync_server(n->cmd_type,serv_name,
1352                                     name.name,name.name_type, n->to_ip);
1353     }
1354   }
1355         else
1356         {
1357                 DEBUG(1,("No 0x1d name type in interpret_node_status()\n"));
1358   }
1359   }
1360
1361
1362 /****************************************************************************
1363   response from a name query to sync browse lists or to update our netbios
1364   entry. commands of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM 
1365   ****************************************************************************/
1366 static void response_name_query_sync(struct nmb_packet *nmb, 
1367                 struct nmb_name *ans_name, BOOL bcast,
1368                 struct response_record *n, struct subnet_record *d)
1369 {
1370         DEBUG(4, ("Name query at %s ip %s - ",
1371                   namestr(&n->name), inet_ntoa(n->to_ip)));
1372   
1373         if (nmb->header.rcode == 0 && nmb->answers->rdata)
1374     {
1375                 int nb_flags = nmb->answers->rdata[0];
1376                 struct in_addr found_ip;
1377
1378                 putip((char*)&found_ip,&nmb->answers->rdata[2]);
1379
1380                 DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
1381
1382                 if (n->cmd_type == NAME_QUERY_SYNC)
1383                 {
1384                         struct work_record *work = NULL;
1385                         if ((work = find_workgroupstruct(d, ans_name->name, False)))
1386                         {
1387                                 /* the server is there: sync quick before it (possibly) dies! */
1388                                 sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
1389                                                         found_ip);
1390                         }
1391   }
1392                 else
1393                 {
1394                         /* update our netbios name list */
1395                         add_netbios_entry(d, ans_name->name, ans_name->name_type,
1396                                                                 nb_flags,GET_TTL(0),STATUS_QUERY,
1397                                                                 found_ip,False,!bcast);
1398                 }
1399         }
1400         else
1401         {
1402                 DEBUG(4, (" NEGATIVE RESPONSE!\n"));
1403
1404                 if (n->cmd_type == NAME_QUERY_CONFIRM)
1405                 {
1406                         /* XXXX remove_netbios_entry()? */
1407                         /* lots of things we ought to do, here. if we get here,
1408                            then we're in a mess: our name database doesn't match
1409                            reality. sort it out
1410              */
1411                 }
1412         }
1413 }
1414
1415 /****************************************************************************
1416   report the response record type
1417   ****************************************************************************/
1418 static void debug_rr_type(int rr_type)
1419     {
1420   switch (rr_type)
1421   {
1422       case NMB_STATUS: DEBUG(3,("Name status ")); break;
1423           case NMB_QUERY : DEBUG(3,("Name query ")); break;
1424           case NMB_REG   : DEBUG(3,("Name registration ")); break;
1425           case NMB_REL   : DEBUG(3,("Name release ")); break;
1426       default        : DEBUG(1,("wrong response packet type received")); break;
1427   }
1428 }
1429
1430 /****************************************************************************
1431   report the response record nmbd command type
1432   ****************************************************************************/
1433 static void debug_cmd_type(int cmd_type)
1434 {
1435   /* report the command type to help debugging */
1436   switch (cmd_type)
1437   {
1438     case NAME_QUERY_MST_SRV_CHK  : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
1439     case NAME_QUERY_SRV_CHK      : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
1440     case NAME_QUERY_FIND_MST     : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
1441     case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break;
1442     case NAME_STATUS_CHECK       : DEBUG(4,("NAME_STATUS_CHECK\n")); break;
1443     case NAME_QUERY_MST_CHK      : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
1444     case NAME_REGISTER           : DEBUG(4,("NAME_REGISTER\n")); break;
1445     case NAME_RELEASE            : DEBUG(4,("NAME_RELEASE\n")); break;
1446     case NAME_QUERY_CONFIRM      : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
1447     case NAME_QUERY_SYNC         : DEBUG(4,("NAME_QUERY_SYNC\n")); break;
1448     default: break;
1449     }
1450 }
1451
1452 /****************************************************************************
1453   report any problems with the fact that a response has been received.
1454
1455   (responses for certain types of operations are only expected from one host)
1456   ****************************************************************************/
1457 static BOOL response_problem_check(struct response_record *n,
1458                         struct nmb_packet *nmb, char *qname)
1459     {
1460   switch (nmb->answers->rr_type)
1461               {
1462     case NMB_REL:
1463     {
1464         if (n->num_msgs > 1)
1465         {
1466             DEBUG(1,("more than one release name response received!\n"));
1467             return True;
1468               }
1469         break;
1470           }
1471
1472     case NMB_REG:
1473           {
1474         if (n->num_msgs > 1)
1475         {
1476             DEBUG(1,("more than one register name response received!\n"));
1477             return True;
1478           }
1479         break;
1480       }
1481       
1482     case NMB_QUERY:
1483       {
1484       if (n->num_msgs > 1)
1485           {
1486                   if (nmb->header.rcode == 0 && nmb->answers->rdata)
1487                   {
1488                         int nb_flags = nmb->answers->rdata[0];
1489             
1490                         if ((!NAME_GROUP(nb_flags)))
1491               {
1492                            /* oh dear. more than one person responded to a unique name.
1493                                   there is either a network problem, a configuration problem
1494                                   or a server is mis-behaving */
1495
1496                            /* XXXX mark the name as in conflict, and then let the
1497                                   person who just responded know that they must also mark it
1498                                   as in conflict, and therefore must NOT use it.
1499                   see rfc1001.txt 15.1.3.5 */
1500                                         
1501                /* this may cause problems for some early versions of nmbd */
1502
1503                switch (n->cmd_type)
1504                   {
1505                         case NAME_QUERY_MST_SRV_CHK:
1506                 case NAME_QUERY_SRV_CHK:
1507                 case NAME_QUERY_MST_CHK:
1508                 /* don't do case NAME_QUERY_FIND_MST: MSBROWSE isn't a unique name. */
1509                 {
1510                       if (!strequal(qname,n->name.name))
1511                       {
1512                              /* one subnet, one master browser per workgroup */
1513                              /* XXXX force an election? */
1514
1515                              DEBUG(3,("more than one master browser replied!\n"));
1516                                  return True;
1517                           }
1518                    break;
1519                 }
1520                 default: break;
1521                }
1522                DEBUG(3,("Unique Name conflict detected!\n"));
1523                            return True;
1524                   }
1525               }
1526             else
1527               {
1528              /* we have received a negative reply, having already received
1529                 at least one response (pos/neg). something's really wrong! */
1530
1531                  DEBUG(3,("wierd name query problem detected!\n"));
1532                      return True;
1533               }
1534           }
1535     }
1536   }
1537   return False;
1538 }
1539
1540 /****************************************************************************
1541   check that the response received is compatible with the response record
1542   ****************************************************************************/
1543 static BOOL response_compatible(struct response_record *n,
1544                         struct nmb_packet *nmb)
1545           {
1546   switch (n->cmd_type)
1547   {
1548     case NAME_RELEASE:
1549     {
1550                 if (nmb->answers->rr_type != NMB_REL)
1551                 {
1552                         DEBUG(1,("Name release reply has wrong answer rr_type\n"));
1553                         return False;
1554           }
1555         break;
1556       }
1557       
1558     case NAME_REGISTER:
1559       {
1560                 if (nmb->answers->rr_type != NMB_REG)
1561           {
1562                         DEBUG(1,("Name register reply has wrong answer rr_type\n"));
1563                         return False;
1564                 }
1565         break;
1566           }
1567
1568     case NAME_QUERY_CONFIRM:
1569     case NAME_QUERY_SYNC:
1570     case NAME_QUERY_MST_SRV_CHK:
1571     case NAME_QUERY_SRV_CHK:
1572     case NAME_QUERY_FIND_MST:
1573     case NAME_QUERY_MST_CHK:
1574     {
1575         if (nmb->answers->rr_type != NMB_QUERY)
1576           {
1577             DEBUG(1,("Name query reply has wrong answer rr_type\n"));
1578                         return False;
1579           }
1580         break;
1581       }
1582       
1583     case NAME_STATUS_MASTER_CHECK:
1584     case NAME_STATUS_CHECK:
1585       {
1586                 if (nmb->answers->rr_type != NMB_STATUS)
1587           {
1588                         DEBUG(1,("Name status reply has wrong answer rr_type\n"));
1589                         return False;
1590                 }
1591                 break;
1592     }
1593             
1594     default:
1595     {
1596                 DEBUG(0,("unknown command received in response_netbios_packet\n"));
1597                 break;
1598           }
1599   }
1600   return True;
1601 }
1602
1603
1604 /****************************************************************************
1605   process the response packet received
1606   ****************************************************************************/
1607 static void response_process(struct subnet_record *d, struct packet_struct *p,
1608                                 struct response_record *n, struct nmb_packet *nmb,
1609                                 BOOL bcast, struct nmb_name *ans_name)
1610 {
1611   switch (n->cmd_type)
1612           {
1613     case NAME_RELEASE:
1614     {
1615         response_name_release(d, p);
1616         break;
1617     }
1618
1619     case NAME_REGISTER:
1620     {
1621         response_name_reg(d, p);
1622         break;
1623           }
1624         
1625     case NAME_QUERY_MST_SRV_CHK:
1626     case NAME_QUERY_SRV_CHK:
1627     case NAME_QUERY_FIND_MST:
1628     {
1629                 response_server_check(ans_name, n, d);
1630         break;
1631       }
1632       
1633     case NAME_STATUS_MASTER_CHECK:
1634     case NAME_STATUS_CHECK:
1635     {
1636                 response_name_status_check(p->ip, nmb, bcast, n, d);
1637                 break;
1638     }
1639       
1640     case NAME_QUERY_CONFIRM:
1641     case NAME_QUERY_SYNC:
1642     {
1643                 response_name_query_sync(nmb, ans_name, bcast, n, d);
1644                 break;
1645     }
1646     case NAME_QUERY_MST_CHK:
1647     {
1648                 /* no action required here. it's when NO responses are received
1649                    that we need to do something. see expire_name_query_entries() */
1650         
1651                 DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n",
1652                                         namestr(&n->name), inet_ntoa(n->to_ip)));
1653                 break;
1654     }
1655
1656     default:
1657       {
1658         DEBUG(0,("unknown command received in response_netbios_packet\n"));
1659         break;
1660       }
1661     }
1662 }
1663
1664
1665 /****************************************************************************
1666   response from a netbios packet.
1667   ****************************************************************************/
1668 static void response_netbios_packet(struct packet_struct *p)
1669 {
1670   struct nmb_packet *nmb = &p->packet.nmb;
1671   struct nmb_name *question = &nmb->question.question_name;
1672   struct nmb_name *ans_name = NULL;
1673   char *qname = question->name;
1674   BOOL bcast = nmb->header.nm_flags.bcast;
1675   struct response_record *n;
1676   struct subnet_record *d = NULL;
1677
1678   if (!(d = find_req_subnet(p->ip, bcast)))
1679   {
1680     DEBUG(3,("response packet: bcast %s not known\n", inet_ntoa(p->ip)));
1681     return;
1682   }
1683
1684   if (nmb->answers == NULL)
1685   {
1686       /* hm. the packet received was a response, but with no answer. wierd! */
1687       DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
1688                inet_ntoa(p->ip), BOOLSTR(bcast)));
1689       return;
1690   }
1691
1692   ans_name = &nmb->answers->rr_name;
1693   DEBUG(3,("response for %s from %s (bcast=%s)\n",
1694            namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast)));
1695   
1696   if (!(n = find_response_record(d,nmb->header.name_trn_id))) {
1697     DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
1698     return;
1699   }
1700
1701   debug_rr_type(nmb->answers->rr_type);
1702
1703   n->num_msgs++; /* count number of responses received */
1704   n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */
1705
1706   debug_cmd_type(n->cmd_type);
1707
1708   /* problem checking: multiple responses etc */
1709   if (response_problem_check(n, nmb, qname))
1710     return;
1711
1712   /* now check whether the command has received the correct type of response*/
1713   if (!response_compatible(n, nmb))
1714     return;
1715
1716   /* now deal with the command */
1717   response_process(d, p, n, nmb, bcast, ans_name);
1718 }
1719
1720
1721 /****************************************************************************
1722   process a nmb packet
1723   ****************************************************************************/
1724 void process_nmb(struct packet_struct *p)
1725 {
1726   struct nmb_packet *nmb = &p->packet.nmb;
1727
1728   debug_nmb_packet(p);
1729
1730   switch (nmb->header.opcode) 
1731     {
1732     case 8: /* what is this?? */
1733     case NMB_REG:
1734     case NMB_REG_REFRESH:
1735       {
1736         if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
1737         if (nmb->header.response)
1738           response_netbios_packet(p); /* response to registration dealt with here */
1739         else
1740           reply_name_reg(p);
1741         break;
1742       }
1743       
1744     case 0:
1745       {
1746         if (nmb->header.response)
1747           {
1748             switch (nmb->question.question_type)
1749               {
1750               case 0x0:
1751                 {
1752                   response_netbios_packet(p);
1753                   break;
1754                 }
1755               }
1756             return;
1757           }
1758         else if (nmb->header.qdcount>0) 
1759           {
1760             switch (nmb->question.question_type)
1761               {
1762               case NMB_QUERY:
1763                 {
1764                   reply_name_query(p);
1765                   break;
1766                 }
1767               case NMB_STATUS:
1768                 {
1769                   reply_name_status(p);
1770                   break;
1771                 }
1772               }
1773             return;
1774           }
1775         break;
1776       }
1777       
1778     case NMB_REL:
1779       {
1780         if (nmb->header.qdcount==0 || nmb->header.arcount==0)
1781           {
1782             DEBUG(2,("netbios release packet rejected\n"));
1783             break;
1784           }
1785         
1786         if (nmb->header.response)
1787           response_netbios_packet(p); /* response to reply dealt with in here */
1788         else
1789           reply_name_release(p);
1790         break;
1791       }
1792     }
1793 }
1794