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