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