more changes from Luke
[samba.git] / source3 / 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 #include "loadparm.h"
30
31 extern int ClientNMB;
32 extern int ClientDGRAM;
33
34 extern int DEBUGLEVEL;
35
36 extern pstring scope;
37 extern BOOL CanRecurse;
38 extern pstring myname;
39 extern struct in_addr ipzero;
40 extern struct in_addr ipgrp;
41
42 /* netbios names database */
43 struct name_record *namelist;
44
45 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
46
47
48 /****************************************************************************
49   true if two netbios names are equal
50 ****************************************************************************/
51 static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
52 {
53   if (n1->name_type != n2->name_type) return(False);
54
55   return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
56 }
57
58 /****************************************************************************
59   add a netbios name into the namelist
60   **************************************************************************/
61 static void add_name(struct name_record *n)
62 {
63   struct name_record *n2;
64
65   if (!namelist)
66   {
67     namelist = n;
68     n->prev = NULL;
69     n->next = NULL;
70     return;
71   }
72
73   for (n2 = namelist; n2->next; n2 = n2->next) ;
74
75   n2->next = n;
76   n->next = NULL;
77   n->prev = n2;
78 }
79
80 /****************************************************************************
81   remove a name from the namelist. The pointer must be an element just 
82   retrieved
83   **************************************************************************/
84 void remove_name(struct name_record *n)
85 {
86   struct name_record *nlist = namelist;
87
88   while (nlist && nlist != n) nlist = nlist->next;
89
90   if (nlist)
91   {
92     if (nlist->next) nlist->next->prev = nlist->prev;
93     if (nlist->prev) nlist->prev->next = nlist->next;
94     free(nlist);
95   }
96 }
97
98
99 /****************************************************************************
100   find a name in the domain database namelist 
101   search can be:
102   FIND_SELF   - look for names the samba server has added for itself
103   FIND_GLOBAL - the name can be anyone. first look on the client's
104                 subnet, then the server's subnet, then all subnets.
105   **************************************************************************/
106 static struct name_record *find_name_search(struct nmb_name *name,
107                                             enum name_search search,
108                                             struct in_addr ip)
109 {
110   struct name_record *ret;
111   
112   for (ret = namelist; ret; ret = ret->next)
113     {
114       if (!name_equal(&ret->name,name)) continue;
115
116       if (search == FIND_SELF && ret->source != SELF) continue;
117       
118       return ret;
119     }
120   
121   return NULL;
122 }
123
124
125 /****************************************************************************
126   dump a copy of the name table
127   **************************************************************************/
128 void dump_names(void)
129 {
130   struct name_record *n;
131   time_t t = time(NULL);
132   
133   DEBUG(3,("Dump of local name table:\n"));
134   
135   for (n = namelist; n; n = n->next)
136     {
137       DEBUG(3,("%s %s TTL=%d NBFLAGS=%2x\n",
138                namestr(&n->name),
139                inet_ntoa(n->ip),
140                n->death_time?n->death_time-t:0,
141                n->nb_flags));
142     }
143 }
144
145
146 /****************************************************************************
147   remove an entry from the name list
148   ****************************************************************************/
149 void remove_netbios_name(char *name,int type, enum name_source source,
150                          struct in_addr ip)
151 {
152   struct nmb_name nn;
153   struct name_record *n;
154   
155   make_nmb_name(&nn, name, type, scope);
156   n = find_name_search(&nn, FIND_GLOBAL, ip);
157   
158   if (n && n->source == source) remove_name(n);
159 }
160
161
162 /****************************************************************************
163   add an entry to the name list
164   ****************************************************************************/
165 struct name_record *add_netbios_entry(char *name, int type, int nb_flags, 
166                                       int ttl,
167                                       enum name_source source, 
168                                       struct in_addr ip,
169                                       BOOL new_only)
170 {
171   struct name_record *n;
172   struct name_record *n2=NULL;
173
174   n = (struct name_record *)malloc(sizeof(*n));
175   if (!n) return(NULL);
176
177   bzero((char *)n,sizeof(*n));
178
179   make_nmb_name(&n->name,name,type,scope);
180
181   if ((n2 = find_name_search(&n->name, FIND_GLOBAL, new_only?ipzero:ip)))
182   {
183     free(n);
184     if (new_only || (n2->source==SELF && source!=SELF)) return n2;
185     n = n2;
186   }
187
188   if (ttl) n->death_time = time(NULL)+ttl*3;
189   n->ip = ip;
190   n->nb_flags = nb_flags;
191   n->source = source;
192   
193   if (!n2) add_name(n);
194
195   DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n",
196                 namestr(&n->name),inet_ntoa(ip),ttl,nb_flags));
197
198   return(n);
199 }
200
201
202 /****************************************************************************
203   remove an entry from the name list
204   ****************************************************************************/
205 void remove_name_entry(char *name,int type)
206 {
207   if (lp_wins_support())
208     {
209       /* we are a WINS server. */
210       remove_netbios_name(name,type,SELF,ipzero);
211     }
212   else
213     {
214       struct in_addr ip;
215       ip = ipzero;
216       
217       queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE,
218                              name, type, 0,
219                              False, True, ip);
220     }
221 }
222
223
224 /****************************************************************************
225   add an entry to the name list
226   ****************************************************************************/
227 void add_name_entry(char *name,int type,int nb_flags)
228 {
229   /* always add our own entries */
230   add_netbios_entry(name,type,nb_flags,0,SELF,ipzero,False);
231
232   if (!lp_wins_support())
233     {
234       struct in_addr ip;
235       ip = ipzero;
236       
237       queue_netbios_pkt_wins(ClientNMB,NMB_REG,NAME_REGISTER,
238                              name, type, nb_flags,
239                              False, True, ip);
240     }
241 }
242
243
244 /****************************************************************************
245   add the magic samba names, useful for finding samba servers
246   **************************************************************************/
247 void add_my_names(void)
248 {
249   struct in_addr ip;
250
251   ip = ipzero;
252   
253   add_name_entry(myname,0x20,NB_ACTIVE);
254   add_name_entry(myname,0x03,NB_ACTIVE);
255   add_name_entry(myname,0x00,NB_ACTIVE);
256   add_name_entry(myname,0x1f,NB_ACTIVE);
257   
258   add_netbios_entry("*",0x0,NB_ACTIVE,0,SELF,ip,False);
259   add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False);
260   add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False);
261
262   if (lp_wins_support()) {
263     /* the 0x1c name gets added by any WINS server it seems */
264     add_name_entry(my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);      
265   }
266 }
267
268 /****************************************************************************
269   remove all the samba names... from a WINS server if necessary.
270   **************************************************************************/
271 void remove_my_names()
272 {
273   struct name_record *n;
274   
275   for (n = namelist; n; n = n->next)
276     {
277       if (n->source == SELF)
278         {
279           /* get all SELF names removed from the WINS server's database */
280           remove_name_entry(n->name.name, n->name.name_type);
281         }
282     }
283 }
284
285
286 /*******************************************************************
287   refresh my own names
288   ******************************************************************/
289 void refresh_my_names(time_t t)
290 {
291   static time_t lasttime = 0;
292
293   if (t - lasttime < REFRESH_TIME) 
294     return;
295   lasttime = t;
296
297   add_my_names();
298 }
299
300 /*******************************************************************
301   expires old names in the namelist
302   ******************************************************************/
303 void expire_names(time_t t)
304 {
305   struct name_record *n;
306   struct name_record *next;
307   
308   /* expire old names */
309   for (n = namelist; n; n = next)
310     {
311       if (n->death_time && n->death_time < t)
312         {
313           DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
314           
315           next = n->next;
316           
317           if (n->prev) n->prev->next = n->next;
318           if (n->next) n->next->prev = n->prev;
319           
320           if (namelist == n) namelist = n->next; 
321           
322           free(n);
323         }
324       else
325         {
326           next = n->next;
327         }
328     }
329 }
330
331
332 /****************************************************************************
333   response for a reg release received
334   **************************************************************************/
335 void response_name_release(struct packet_struct *p)
336 {
337   struct nmb_packet *nmb = &p->packet.nmb;
338   char *name = nmb->question.question_name.name;
339   int   type = nmb->question.question_name.name_type;
340   
341   DEBUG(4,("response name release received\n"));
342   
343   if (nmb->header.rcode == 0 && nmb->answers->rdata)
344     {
345       struct in_addr found_ip;
346       putip((char*)&found_ip,&nmb->answers->rdata[2]);
347       
348       if (ismyip(found_ip))
349         {
350           remove_netbios_name(name,type,SELF,found_ip);
351         }
352     }
353   else
354     {
355       DEBUG(1,("name registration for %s rejected!\n",
356                namestr(&nmb->question.question_name)));
357     }
358 }
359
360
361 /****************************************************************************
362   reply to a name release
363   ****************************************************************************/
364 void reply_name_release(struct packet_struct *p)
365 {
366   struct nmb_packet *nmb = &p->packet.nmb;
367   struct in_addr ip;
368   int rcode=0;
369   int opcode = nmb->header.opcode;  
370   int nb_flags = nmb->additional->rdata[0];
371   BOOL bcast = nmb->header.nm_flags.bcast;
372   struct name_record *n;
373   char rdata[6];
374   
375   putip((char *)&ip,&nmb->additional->rdata[2]);  
376   
377   DEBUG(3,("Name release on name %s rcode=%d\n",
378            namestr(&nmb->question.question_name),rcode));
379   
380   n = find_name_search(&nmb->question.question_name, FIND_GLOBAL, ip);
381   
382   /* XXXX under what conditions should we reject the removal?? */
383   if (n && n->nb_flags == nb_flags)
384     {
385       /* success = True;
386          rcode = 6; */
387       
388       remove_name(n);
389       n = NULL;
390     }
391   
392   if (bcast) return;
393   
394   rdata[0] = nb_flags;
395   rdata[1] = 0;
396   putip(&rdata[2],(char *)&ip);
397   
398   /* Send a NAME RELEASE RESPONSE */
399   reply_netbios_packet(p,nmb->header.name_trn_id,
400                        rcode,opcode,True,
401                        &nmb->question.question_name,
402                        nmb->question.question_type,
403                        nmb->question.question_class,
404                        0,
405                        rdata, 6);
406 }
407
408
409 /****************************************************************************
410   response for a reg request received
411   **************************************************************************/
412 void response_name_reg(struct packet_struct *p)
413 {
414   struct nmb_packet *nmb = &p->packet.nmb;
415   char *name = nmb->question.question_name.name;
416   int   type = nmb->question.question_name.name_type;
417   
418   DEBUG(4,("response name registration received!\n"));
419   
420   if (nmb->header.rcode == 0 && nmb->answers->rdata)
421     {
422       int nb_flags = nmb->answers->rdata[0];
423       struct in_addr found_ip;
424       int ttl = nmb->answers->ttl;
425       enum name_source source = REGISTER;
426       
427       putip((char*)&found_ip,&nmb->answers->rdata[2]);
428       
429       if (ismyip(found_ip)) source = SELF;
430       
431       add_netbios_entry(name,type,nb_flags,ttl,source,found_ip,True);
432     }
433   else
434     {
435       DEBUG(1,("name registration for %s rejected!\n",
436                namestr(&nmb->question.question_name)));
437     }
438 }
439
440
441 /****************************************************************************
442   reply to a reg request
443   **************************************************************************/
444 void reply_name_reg(struct packet_struct *p)
445 {
446   struct nmb_packet *nmb = &p->packet.nmb;
447   struct nmb_name *question = &nmb->question.question_name;
448   
449   struct nmb_name *reply_name = question;
450   char *qname = question->name;
451   int name_type  = question->name_type;
452   int name_class = nmb->question.question_class;
453   
454   BOOL bcast = nmb->header.nm_flags.bcast;
455   
456   int ttl = GET_TTL(nmb->additional->ttl);
457   int nb_flags = nmb->additional->rdata[0];
458   BOOL group = NAME_GROUP(nb_flags);
459   int rcode = 0;  
460   int opcode = nmb->header.opcode;  
461   
462   struct name_record *n = NULL;
463   BOOL success = True;
464   BOOL recurse = True; /* true if samba replies yes/no: false if caller */
465   /* must challenge the current owner */
466   char rdata[6];
467   
468   struct in_addr ip, from_ip;
469   
470   DEBUG(3,("Name registration for name %s at %s rcode=%d\n",
471            namestr(question),inet_ntoa(ip),rcode));
472   
473   putip((char *)&from_ip,&nmb->additional->rdata[2]);
474   ip = from_ip;
475   
476   if (group)
477     {
478       /* apparently we should return 255.255.255.255 for group queries
479          (email from MS) */
480       ip = ipgrp;
481     }
482   
483   /* see if the name already exists */
484   n = find_name_search(question, FIND_GLOBAL, from_ip);
485   
486   if (n)
487     {
488       if (!group) /* unique names */
489         {
490           if (n->source == SELF || NAME_GROUP(n->nb_flags))
491             {
492               /* no-one can register one of samba's names, nor can they
493                  register a name that's a group name as a unique name */
494               
495               rcode = 6;
496               success = False;
497             }
498           else if(!ip_equal(ip, n->ip))
499             {
500               /* hm. this unique name doesn't belong to them. */
501               
502               /* XXXX rfc1001.txt says:
503                * if we are doing secured WINS, we must send a Wait-Acknowledge
504                * packet (WACK) to the person who wants the name, then do a
505                * name query on the person who currently owns the unique name.
506                * if the current owner is alive, the person who wants the name
507                * can't have it. if they are not alive, they can.
508                *
509                * if we are doing non-secure WINS (which is much simpler) then
510                * we send a message to the person wanting the name saying 'he
511                * owns this name: i don't want to hear from you ever again
512                * until you've checked with him if you can have it!'. we then
513                * abandon the registration. once the person wanting the name
514                * has checked with the current owner, they will repeat the
515                * registration packet if the current owner is dead or doesn't
516                * want the name.
517                */
518               
519               /* non-secured WINS implementation: caller is responsible
520                  for checking with current owner of name, then getting back
521                  to us... IF current owner no longer owns the unique name */
522               
523               rcode = 0;
524               success = False;
525               recurse = False;
526               
527               /* we inform on the current owner to the caller (which is
528                  why it's non-secure */
529               
530               reply_name = &n->name;
531               
532               /* name_type  = ?;
533                  name_class = ?;
534                  XXXX sorry, guys: i really can't see what name_type
535                  and name_class should be set to according to rfc1001 */
536             }
537           else
538             {
539               /* XXXX removed code that checked with the owner of a name */
540               
541               n->ip = ip;
542               n->death_time = ttl?p->timestamp+ttl*3:0;
543               DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip)));
544             }
545         }
546       else
547         {
548           /* refresh the name */
549           if (n->source != SELF)
550             {
551               n->death_time = ttl?p->timestamp + ttl*3:0;
552             }
553         }
554     }
555   else
556     {
557       /* add the name to our subnet/name database */
558       n = add_netbios_entry(qname,name_type,nb_flags,ttl,REGISTER,ip,True);
559     }
560   
561   if (bcast) return;
562   
563   if (success)
564     {
565       update_from_reg(nmb->question.question_name.name,
566                       nmb->question.question_name.name_type, from_ip);
567     }
568   
569   rdata[0] = nb_flags;
570   rdata[1] = 0;
571   putip(&rdata[2],(char *)&ip);
572   
573   /* Send a NAME REGISTRATION RESPONSE (pos/neg)
574      or and END-NODE CHALLENGE REGISTRATION RESPONSE */
575   reply_netbios_packet(p,nmb->header.name_trn_id,
576                        rcode,opcode,recurse,
577                        reply_name, name_type, name_class,
578                        ttl,
579                        rdata, 6);
580 }
581
582
583 /****************************************************************************
584   reply to a name status query
585   ****************************************************************************/
586 void reply_name_status(struct packet_struct *p)
587 {
588   struct nmb_packet *nmb = &p->packet.nmb;
589   char *qname   = nmb->question.question_name.name;
590   int ques_type = nmb->question.question_name.name_type;
591   char rdata[MAX_DGRAM_SIZE];
592   char *countptr, *buf, *bufend;
593   int names_added;
594   struct name_record *n;
595   
596   DEBUG(3,("Name status for name %s %s\n",
597            namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
598   
599   n = find_name_search(&nmb->question.question_name,FIND_GLOBAL, p->ip);
600   
601   if (!n) return;
602     
603   /* XXXX hack, we should calculate exactly how many will fit */
604   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
605   countptr = buf = rdata;
606   buf += 1;
607   
608   names_added = 0;
609   
610   for (n = namelist ; n && buf < bufend; n = n->next) 
611     {
612       int name_type = n->name.name_type;
613       
614       if (n->source != SELF) continue;
615       
616       /* start with first bit of putting info in buffer: the name */
617       
618       bzero(buf,18);
619       sprintf(buf,"%-15.15s",n->name.name);
620       strupper(buf);
621       
622       /* now check if we want to exclude other workgroup names
623          from the response. if we don't exclude them, windows clients
624          get confused and will respond with an error for NET VIEW */
625       
626       if (name_type >= 0x1b && name_type <= 0x20 && 
627           ques_type >= 0x1b && ques_type <= 0x20)
628         {
629           if (!strequal(qname, n->name.name)) continue;
630         }
631       
632       /* carry on putting name info in buffer */
633       
634       buf[15] = name_type;
635       buf[16]  = n->nb_flags;
636       
637       buf += 18;
638       
639       names_added++;
640     }
641     
642   SCVAL(countptr,0,names_added);
643   
644   /* XXXXXXX we should fill in more fields of the statistics structure */
645   bzero(buf,64);
646   {
647     extern int num_good_sends,num_good_receives;
648     SIVAL(buf,20,num_good_sends);
649     SIVAL(buf,24,num_good_receives);
650   }
651   
652   SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */
653   
654   buf += 64;
655   
656   /* Send a POSITIVE NAME STATUS RESPONSE */
657   reply_netbios_packet(p,nmb->header.name_trn_id,
658                        0,0,True,
659                        &nmb->question.question_name,
660                        nmb->question.question_type,
661                        nmb->question.question_class,
662                        0,
663                        rdata,PTR_DIFF(buf,rdata));
664 }
665
666
667 /***************************************************************************
668   reply to a name query
669   ****************************************************************************/
670 static struct name_record *search_for_name(struct nmb_name *question,
671                                            struct in_addr ip, int Time, 
672                                            enum name_search search)
673 {
674   int name_type = question->name_type;
675   char *qname = question->name;
676   BOOL dns_type = name_type == 0x20 || name_type == 0;
677   
678   struct name_record *n;
679   
680   DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip)));
681   
682   /* first look up name in cache. use ip as well as name to locate it */
683   n = find_name_search(question,search,ip);
684   
685   /* now try DNS lookup. */
686   if (!n)
687     {
688       struct in_addr dns_ip;
689       unsigned long a;
690       
691       /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
692       if (!dns_type)
693         {
694           DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n"));
695           return NULL;
696         }
697       
698       /* look it up with DNS */      
699       a = interpret_addr(qname);
700       
701       putip((char *)&dns_ip,(char *)&a);
702       
703       if (!a)
704         {
705           /* no luck with DNS. We could possibly recurse here XXXX */
706           /* if this isn't a bcast then we should send a negative reply XXXX */
707           DEBUG(3,("no recursion\n"));
708           add_netbios_entry(qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,True);
709           return NULL;
710         }
711       
712       /* add it to our cache of names. give it 2 hours in the cache */
713       n = add_netbios_entry(qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,True);
714       
715       /* failed to add it? yikes! */
716       if (!n) return NULL;
717     }
718   
719   /* is our entry already dead? */
720   if (n->death_time)
721     {
722       if (n->death_time < Time) return False;
723     }
724   
725   /* it may have been an earlier failure */
726   if (n->source == DNSFAIL)
727     {
728       DEBUG(3,("DNSFAIL\n"));
729       return NULL;
730     }
731   
732   DEBUG(3,("OK %s\n",inet_ntoa(n->ip)));      
733   
734   return n;
735 }
736
737
738
739 /***************************************************************************
740   reply to a name query
741   ****************************************************************************/
742 void reply_name_query(struct packet_struct *p)
743 {
744   struct nmb_packet *nmb = &p->packet.nmb;
745   struct nmb_name *question = &nmb->question.question_name;
746   int name_type = question->name_type;
747   BOOL dns_type = name_type == 0x20 || name_type == 0; 
748   BOOL bcast = nmb->header.nm_flags.bcast;
749   int ttl=0;
750   int rcode = 0;
751   int nb_flags = 0;
752   struct in_addr retip;
753   char rdata[6];
754   BOOL success = True;
755   struct name_record *n;
756   enum name_search search = (dns_type || name_type == 0x1b) ?
757     FIND_GLOBAL : FIND_SELF;
758
759   DEBUG(3,("Name query "));
760   
761   if ((n = search_for_name(question,p->ip,p->timestamp, search)))
762     {
763       /* don't respond to broadcast queries unless the query is for
764          a name we own or it is for a Primary Domain Controller name */
765       if (bcast && n->source != SELF && name_type != 0x1b)
766         {
767           if (!lp_wins_proxy() || same_net(p->ip,n->ip,*iface_nmask(p->ip))) {
768             /* never reply with a negative response to broadcast queries */
769             return;
770           }
771         }
772
773       /* name is directed query, or it's self, or it's a PDC type name */
774       ttl = n->death_time - p->timestamp;
775       retip = n->ip;
776       nb_flags = n->nb_flags;
777     }
778   else
779     {
780       if (bcast) return; /* never reply negative response to bcasts */
781       success = False;
782     }
783
784   /* if the IP is 0 then substitute my IP */
785   if (zero_ip(retip)) retip = *iface_ip(p->ip);
786   
787   if (success)
788     {
789       rcode = 0;
790       DEBUG(3,("OK %s\n",inet_ntoa(retip)));      
791     }
792   else
793     {
794       rcode = 3;
795       DEBUG(3,("UNKNOWN\n"));      
796     }
797   
798   if (success)
799     {
800       rdata[0] = nb_flags;
801       rdata[1] = 0;
802       putip(&rdata[2],(char *)&retip);
803     }
804   
805   reply_netbios_packet(p,nmb->header.name_trn_id,
806                        rcode,0,True,
807                        &nmb->question.question_name,
808                        nmb->question.question_type,
809                        nmb->question.question_class,
810                        ttl,
811                        rdata, success ? 6 : 0);
812 }
813
814
815
816 /****************************************************************************
817 response from a name query
818 ****************************************************************************/
819 static void response_netbios_packet(struct packet_struct *p)
820 {
821   struct nmb_packet *nmb = &p->packet.nmb;
822   struct nmb_name *question = &nmb->question.question_name;
823   char *qname = question->name;
824   BOOL bcast = nmb->header.nm_flags.bcast;
825   struct name_response_record *n;
826
827   if (nmb->answers == NULL)
828     {
829       DEBUG(3,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
830                inet_ntoa(p->ip),
831                BOOLSTR(bcast)));
832       return;
833     }
834   
835   if (nmb->answers->rr_type == NMB_STATUS) {
836     DEBUG(3,("Name status "));
837   }
838
839   if (nmb->answers->rr_type == NMB_QUERY)       {
840     DEBUG(3,("Name query "));
841   }
842
843   if (nmb->answers->rr_type == NMB_REG) {
844     DEBUG(3,("Name registration "));
845   }
846
847   if (nmb->answers->rr_type == NMB_REL) {
848     DEBUG(3,("Name release "));
849   }
850
851   DEBUG(3,("response for %s from %s (bcast=%s)\n",
852            namestr(&nmb->answers->rr_name),
853            inet_ntoa(p->ip),
854            BOOLSTR(bcast)));
855   
856   if (!(n = find_name_query(nmb->header.name_trn_id))) {
857     DEBUG(3,("unknown response (received too late or from nmblookup?)\n"));
858     return;
859   }
860
861   n->num_msgs++; /* count number of responses received */
862
863   switch (n->cmd_type)
864     {
865     case MASTER_SERVER_CHECK     : DEBUG(4,("MASTER_SVR_CHECK\n")); break;
866     case SERVER_CHECK            : DEBUG(4,("SERVER_CHECK\n")); break;
867     case FIND_MASTER             : DEBUG(4,("FIND_MASTER\n")); break;
868     case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break;
869     case NAME_STATUS_CHECK       : DEBUG(4,("NAME_STATUS_CHECK\n")); break;
870     case CHECK_MASTER            : DEBUG(4,("CHECK_MASTER\n")); break;
871     case NAME_CONFIRM_QUERY      : DEBUG(4,("NAME_CONFIRM_QUERY\n")); break;
872     default: break;
873     }
874   switch (n->cmd_type)
875     {
876     case MASTER_SERVER_CHECK:
877     case SERVER_CHECK:
878     case FIND_MASTER:
879       {
880         if (nmb->answers->rr_type == NMB_QUERY)
881           {
882             enum cmd_type cmd = (n->cmd_type == MASTER_SERVER_CHECK) ?
883               NAME_STATUS_MASTER_CHECK :
884               NAME_STATUS_CHECK;
885             if (n->num_msgs > 1 && !strequal(qname,n->name.name))
886               {
887                 /* one subnet, one master browser per workgroup */
888                 /* XXXX force an election? */
889                 DEBUG(1,("more than one master browser replied!\n"));
890               }
891             
892             /* initiate a name status check on the server that replied */
893             queue_netbios_packet(ClientNMB,NMB_STATUS, cmd,
894                                  nmb->answers->rr_name.name,
895                                  nmb->answers->rr_name.name_type,0,
896                                  False,False,n->to_ip);
897           }
898         else
899           {
900             DEBUG(1,("Name query reply has wrong answer rr_type\n"));
901           }
902         break;
903       }
904       
905     case NAME_STATUS_MASTER_CHECK:
906     case NAME_STATUS_CHECK:
907       {
908         if (nmb->answers->rr_type == NMB_STATUS)
909           {
910             /* NMB_STATUS arrives: contains the workgroup name 
911                and server name we require */
912             struct nmb_name name;
913             fstring serv_name;
914             
915             if (interpret_node_status(nmb->answers->rdata,
916                                       &name,0x1d,serv_name,p->ip))
917               {
918                 if (*serv_name)
919                   {
920                     sync_server(n->cmd_type,serv_name,
921                                 name.name,name.name_type,
922                                 n->to_ip);
923                   }
924               }
925             else
926               {
927                 DEBUG(1,("No 0x1d name type in interpret_node_status()\n"));
928               }
929           }
930         else
931           {
932             DEBUG(1,("Name status reply has wrong answer rr_type\n"));
933           }
934         break;
935       }
936       
937     case CHECK_MASTER:
938       {
939         /* no action required here. it's when NO responses are received
940            that we need to do something (see expire_name_query_entries) */
941         
942         DEBUG(4, ("Master browser exists for %s at %s\n",
943                   namestr(&n->name),
944                   inet_ntoa(n->to_ip)));
945         if (n->num_msgs > 1)
946           {
947             DEBUG(1,("more than one master browser!\n"));
948           }
949         if (nmb->answers->rr_type != NMB_QUERY)
950           {
951             DEBUG(1,("Name query reply has wrong answer rr_type\n"));
952           }
953         break;
954       }
955     case NAME_CONFIRM_QUERY:
956       {
957         DEBUG(4, ("Name query at WINS server: %s at %s - ",
958                   namestr(&n->name),
959                   inet_ntoa(n->to_ip)));
960         if (nmb->header.rcode == 0 && nmb->answers->rdata)
961           {
962             int nb_flags = nmb->answers->rdata[0];
963             struct in_addr found_ip;
964             putip((char*)&found_ip,&nmb->answers->rdata[2]);
965             
966             DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
967             add_netbios_entry(nmb->answers->rr_name.name,
968                               nmb->answers->rr_name.name_type,
969                               nb_flags,GET_TTL(0),STATUS_QUERY,found_ip,False);
970           }
971         else
972           {
973             DEBUG(4, (" NEGATIVE RESPONSE\n"));
974           }
975         
976         break;
977       }
978     default:
979       {
980         DEBUG(0,("unknown command received in response_netbios_packet\n"));
981         break;
982       }
983     }
984 }
985
986
987 /****************************************************************************
988   process a nmb packet
989   ****************************************************************************/
990 void process_nmb(struct packet_struct *p)
991 {
992   struct nmb_packet *nmb = &p->packet.nmb;
993
994   debug_nmb_packet(p);
995
996   switch (nmb->header.opcode) 
997     {
998     case 5:
999     case 8:
1000     case 9:
1001       {
1002         if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
1003         if (nmb->header.response)
1004           response_name_reg(p);
1005         else
1006           reply_name_reg(p);
1007         break;
1008       }
1009       
1010     case 0:
1011       {
1012         if (nmb->header.response)
1013           {
1014             switch (nmb->question.question_type)
1015               {
1016               case 0x0:
1017                 {
1018                   response_netbios_packet(p);
1019                   break;
1020                 }
1021               }
1022             return;
1023           }
1024         else if (nmb->header.qdcount>0) 
1025           {
1026             switch (nmb->question.question_type)
1027               {
1028               case NMB_QUERY:
1029                 {
1030                   reply_name_query(p);
1031                   break;
1032                 }
1033               case NMB_STATUS:
1034                 {
1035                   reply_name_status(p);
1036                   break;
1037                 }
1038               }
1039             return;
1040           }
1041         break;
1042       }
1043       
1044     case 6:
1045       {
1046         if (nmb->header.qdcount==0 || nmb->header.arcount==0)
1047           {
1048             DEBUG(2,("netbios release packet rejected\n"));
1049             break;
1050           }
1051         
1052         if (nmb->header.response)
1053           response_name_release(p);
1054         else
1055           reply_name_release(p);
1056         break;
1057       }
1058     }
1059 }
1060