'The mother of all checkins' :-). Jeremy Allison (jallison@whistle.com)
[kai/samba.git] / source3 / nameservresp.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1997
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Revision History:
22
23    Module name: nameservresp.c
24
25    14 jan 96: lkcl@pires.co.uk
26    added multiple workgroup domain master support
27
28    05 jul 96: lkcl@pires.co.uk
29    created module nameservresp containing NetBIOS response functions
30
31 */
32
33 #include "includes.h"
34
35 extern int ClientNMB;
36
37 extern int DEBUGLEVEL;
38
39 extern pstring scope;
40 extern struct in_addr ipzero;
41
42 #define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
43
44
45 /****************************************************************************
46   response for a reg release received. samba has asked a WINS server if it
47   could release a name.
48   **************************************************************************/
49 static void response_name_release(struct nmb_name *ans_name,
50                         struct subnet_record *d, struct packet_struct *p)
51 {
52   struct nmb_packet *nmb = &p->packet.nmb;
53   char *name = ans_name->name;
54   int   type = ans_name->name_type;
55   
56   DEBUG(4,("response name release received\n"));
57   
58   if (nmb->header.rcode == 0 && nmb->answers->rdata)
59   {
60     /* IMPORTANT: see expire_netbios_response_entries() */
61
62     struct in_addr found_ip;
63     putip((char*)&found_ip,&nmb->answers->rdata[2]);
64       
65     /* NOTE: we only release our own names at present */
66     if (ismyip(found_ip))
67     {
68       name_unregister_work(d,name,type);
69     }
70     else
71     {
72       DEBUG(2,("name release for different ip! %s %s\n",
73                   inet_ntoa(found_ip), namestr(ans_name)));
74     }
75   }
76   else
77   {
78     DEBUG(2,("name release for %s rejected!\n", namestr(ans_name)));
79
80     /* XXXX PANIC! what to do if it's one of samba's own names? */
81
82     /* XXXX do we honestly care if our name release was rejected? 
83        only if samba is issuing the release on behalf of some out-of-sync
84        server. if it's one of samba's SELF names, we don't care. */
85   }
86 }
87
88
89 /****************************************************************************
90 response for a reg request received
91 **************************************************************************/
92 static void response_name_reg(struct nmb_name *ans_name,
93                         struct subnet_record *d, struct packet_struct *p)
94 {
95   struct nmb_packet *nmb = &p->packet.nmb;
96   BOOL bcast = nmb->header.nm_flags.bcast;
97   char *name = ans_name->name;
98   int   type = ans_name->name_type;
99   
100   DEBUG(4,("response name registration received!\n"));
101   
102   if (nmb->header.rcode == 0 && nmb->answers->rdata)
103   {
104     /* IMPORTANT: see expire_netbios_response_entries() */
105
106     int nb_flags = nmb->answers->rdata[0];
107     int ttl = nmb->answers->ttl;
108     struct in_addr found_ip;
109
110     putip((char*)&found_ip,&nmb->answers->rdata[2]);
111       
112     name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
113   }
114   else
115   {
116     DEBUG(2,("name registration for %s rejected!\n", namestr(ans_name)));
117
118         /* oh dear. we have problems. possibly unbecome a master browser. */
119     name_unregister_work(d,name,type);
120   }
121 }
122
123
124 /****************************************************************************
125   response from a name query announce host
126   NAME_QUERY_ANNOUNCE_HOST is dealt with here
127   ****************************************************************************/
128 static void response_announce_host(struct nmb_name *ans_name, 
129                 struct nmb_packet *nmb, 
130                 struct response_record *n, struct subnet_record *d)
131 {
132         DEBUG(4, ("Name query at %s ip %s - ",
133                   namestr(&n->name), inet_ntoa(n->send_ip)));
134
135         if (!name_equal(&n->name, ans_name))
136         {
137                 /* someone gave us the wrong name as a reply. oops. */
138                 /* XXXX should say to them 'oi! release that name!' */
139
140                 DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
141                 return;
142         }
143
144         if (nmb->header.rcode == 0 && nmb->answers->rdata)
145     {
146                 /* we had sent out a name query to the current owner
147                    of a name because someone else wanted it. now they
148                    have responded saying that they still want the name,
149                    so the other host can't have it.
150                  */
151
152                 /* first check all the details are correct */
153
154                 int nb_flags = nmb->answers->rdata[0];
155                 struct in_addr found_ip;
156
157                 putip((char*)&found_ip,&nmb->answers->rdata[2]);
158
159                 if (nb_flags != n->nb_flags)
160                 {
161                         /* someone gave us the wrong nb_flags as a reply. oops. */
162                         /* XXXX should say to them 'oi! release that name!' */
163
164                         DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
165                         DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
166                         return;
167                 }
168
169         /* do an announce host */
170         do_announce_host(ANN_HostAnnouncement,
171                                 n->my_name  , 0x00, d->myip,
172                                 n->name.name, 0x1d, found_ip,
173                                 n->ttl,
174                                 n->my_name, n->server_type, n->my_comment);
175         }
176         else
177         {
178                 /* XXXX negative name query response. no master exists. oops */
179         }
180 }
181
182
183 /****************************************************************************
184   response from a name query server check. states of type NAME_QUERY_DOM_SRV_CHK,
185   NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
186   ****************************************************************************/
187 static void response_server_check(struct nmb_name *ans_name, 
188                 struct response_record *n, struct subnet_record *d)
189 {
190     /* issue another state: this time to do a name status check */
191
192     enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
193               NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK;
194
195     /* initiate a name status check on the server that replied 
196        in addition, the workgroup being checked has been stored
197        in the response_record->my_name (see announce_master) we
198        also propagate this into the same field. */
199     queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
200                                 ans_name->name, ans_name->name_type,
201                                 0,0,0,n->my_name,NULL,
202                                 False,False,n->send_ip,n->reply_to_ip);
203 }
204
205
206 /****************************************************************************
207   interpret a node status response. this is pretty hacked: we need two bits of
208   info. a) the name of the workgroup b) the name of the server. it will also
209   add all the names it finds into the namelist.
210 ****************************************************************************/
211 static BOOL interpret_node_status(struct subnet_record *d,
212                                 char *p, struct nmb_name *name,int t,
213                            char *serv_name, struct in_addr ip, BOOL bcast)
214 {
215   int numnames = CVAL(p,0);
216   BOOL found = False;
217
218   DEBUG(4,("received %d names\n",numnames));
219
220   p += 1;
221
222   if (serv_name) *serv_name = 0;
223
224   while (numnames--)
225     {
226       char qname[17];
227       int type;
228       fstring flags;
229       int nb_flags;
230       
231       BOOL group = False;
232       BOOL add   = False;
233       
234       *flags = 0;
235       
236       StrnCpy(qname,p,15);
237       type = CVAL(p,15);
238       nb_flags = p[16];
239       trim_string(qname,NULL," ");
240       
241       p += 18;
242       
243       if (NAME_GROUP    (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
244       if (NAME_BFLAG    (nb_flags)) { strcat(flags,"B "); }
245       if (NAME_PFLAG    (nb_flags)) { strcat(flags,"P "); }
246       if (NAME_MFLAG    (nb_flags)) { strcat(flags,"M "); }
247       if (NAME_HFLAG    (nb_flags)) { strcat(flags,"H "); }
248       if (NAME_DEREG    (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
249       if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); }
250       if (NAME_ACTIVE   (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
251       if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
252
253 /* I don't think we should be messing with our namelist here... JRA */      
254 #if 0
255       /* might as well update our namelist while we're at it */
256       if (add)
257         {
258           struct in_addr nameip;
259           enum name_source src;
260           
261           if (ismyip(ip)) {
262             nameip = ipzero;
263             src = SELF;
264           } else {
265             nameip = ip;
266             src = STATUS_QUERY;
267           }
268           add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
269         } 
270 #endif /* JRA */
271
272       /* we want the server name */
273       if (serv_name && !*serv_name && !group && type == 0x20)
274         {
275           StrnCpy(serv_name,qname,15);
276           serv_name[15] = 0;
277         }
278       
279       /* looking for a name and type? */
280       if (name && !found && (t == type))
281         {
282           /* take a guess at some of the name types we're going to ask for.
283              evaluate whether they are group names or no... */
284           if (((t == 0x1b || t == 0x1d || t == 0x20 ) && !group) ||
285               ((t == 0x1c || t == 0x1e              ) &&  group))
286             {
287               found = True;
288               make_nmb_name(name,qname,type,scope);
289             }
290         }
291       
292       DEBUG(4,("\t%s(0x%x)\t%s\n",qname,type,flags));
293     }
294   DEBUG(4,("num_good_sends=%d num_good_receives=%d\n",
295                IVAL(p,20),IVAL(p,24)));
296   return found;
297 }
298
299
300 /****************************************************************************
301   response from a name status check. states of type NAME_STATUS_DOM_SRV_CHK
302   and NAME_STATUS_SRV_CHK dealt with here.
303   ****************************************************************************/
304 static void response_name_status_check(struct in_addr ip,
305                 struct nmb_packet *nmb, BOOL bcast,
306                 struct response_record *n, struct subnet_record *d)
307 {
308         /* NMB_STATUS arrives: contains workgroup name and server name required.
309        amongst other things. */
310
311         struct nmb_name name;
312         fstring serv_name;
313
314         if (interpret_node_status(d,nmb->answers->rdata,
315                                   &name,0x20,serv_name,ip,bcast))
316         {
317                 if (*serv_name)
318                 {
319                         /* response_record->my_name contains the
320                            workgroup name to sync with. See 
321                            response_server_check() */
322                         sync_server(n->state,serv_name,
323                                     n->my_name,name.name_type, d, n->send_ip);
324                 }
325         }
326         else
327         {
328                 DEBUG(1,("No 0x20 name type in interpret_node_status()\n"));
329         }
330 }
331
332
333 /****************************************************************************
334   response from a name query for secured WINS registration. a state of
335   NAME_REGISTER_CHALLENGE is dealt with here.
336   ****************************************************************************/
337 static void response_name_query_register(struct nmb_packet *nmb, 
338                 struct nmb_name *ans_name, 
339                 struct response_record *n, struct subnet_record *d)
340 {
341         struct in_addr register_ip;
342         BOOL new_owner;
343
344         DEBUG(4, ("Name query at %s ip %s - ",
345                   namestr(&n->name), inet_ntoa(n->send_ip)));
346
347         if (!name_equal(&n->name, ans_name))
348         {
349                 /* someone gave us the wrong name as a reply. oops. */
350                 /* XXXX should say to them 'oi! release that name!' */
351
352                 DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
353                 return;
354         }
355
356         if (nmb->header.rcode == 0 && nmb->answers->rdata)
357     {
358                 /* we had sent out a name query to the current owner
359                    of a name because someone else wanted it. now they
360                    have responded saying that they still want the name,
361                    so the other host can't have it.
362                  */
363
364                 /* first check all the details are correct */
365
366                 int nb_flags = nmb->answers->rdata[0];
367                 struct in_addr found_ip;
368
369                 putip((char*)&found_ip,&nmb->answers->rdata[2]);
370
371                 if (nb_flags != n->nb_flags)
372                 {
373                         /* someone gave us the wrong nb_flags as a reply. oops. */
374                         /* XXXX should say to them 'oi! release that name!' */
375
376                         DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
377                         DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
378                         return;
379                 }
380
381                 if (!ip_equal(n->send_ip, found_ip))
382                 {
383                         /* someone gave us the wrong ip as a reply. oops. */
384                         /* XXXX should say to them 'oi! release that name!' */
385
386                         DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
387                         DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
388                         return;
389                 }
390
391                 DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
392
393                 /* fine: now tell the other host they can't have the name */
394                 register_ip = n->send_ip;
395                 new_owner = False;
396         }
397         else
398         {
399                 DEBUG(4, (" NEGATIVE RESPONSE!\n"));
400
401                 /* the owner didn't want the name: the other host can have it */
402                 register_ip = n->reply_to_ip;
403                 new_owner = True;
404         }
405
406         /* register the old or the new owners' ip */
407         add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags,
408                                         GET_TTL(0), register_ip,
409                                         new_owner, n->reply_to_ip);
410 }
411
412
413 /****************************************************************************
414   response from a name query to sync browse lists or to update our netbios
415   entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM 
416   ****************************************************************************/
417 static void response_name_query_sync(struct nmb_packet *nmb, 
418                 struct nmb_name *ans_name, BOOL bcast,
419                 struct response_record *n, struct subnet_record *d)
420 {
421   DEBUG(4, ("Name query at %s ip %s - ",
422             namestr(&n->name), inet_ntoa(n->send_ip)));
423
424   if (!name_equal(&n->name, ans_name))
425     {
426       /* someone gave us the wrong name as a reply. oops. */
427       DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
428       return;
429     }
430
431   if (nmb->header.rcode == 0 && nmb->answers->rdata)
432     {
433       int nb_flags = nmb->answers->rdata[0];
434       struct in_addr found_ip;
435       
436       putip((char*)&found_ip,&nmb->answers->rdata[2]);
437       
438       if (!ip_equal(n->send_ip, found_ip))
439         {
440           /* someone gave us the wrong ip as a reply. oops. */
441           DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
442           DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
443           return;
444         }
445
446       DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
447       
448       if (n->state == NAME_QUERY_SYNC_LOCAL ||
449           n->state == NAME_QUERY_SYNC_REMOTE)
450         {
451           struct work_record *work = NULL;
452           /* We cheat here as we know that the workgroup name has
453              been placed in the my_comment field of the 
454              response_record struct by the code in 
455              start_sync_browse_entry().
456           */
457           if ((work = find_workgroupstruct(d, n->my_comment, False)))
458             {
459               BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
460               
461               /* the server is there: sync quick before it (possibly) dies! */
462               sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
463                                 found_ip, local_list_only);
464             }
465         }
466       else
467         {
468           /* update our netbios name list (re-register it if necessary) */
469           add_netbios_entry(d, ans_name->name, ans_name->name_type,
470                             nb_flags,GET_TTL(0),REGISTER,
471                             found_ip,False,!bcast);
472         }
473     }
474   else
475     {
476       DEBUG(4, (" NEGATIVE RESPONSE!\n"));
477       
478       if (n->state == NAME_QUERY_CONFIRM)
479         {
480           /* XXXX remove_netbios_entry()? */
481           /* lots of things we ought to do, here. if we get here,
482              then we're in a mess: our name database doesn't match
483              reality. sort it out
484              */
485           remove_netbios_name(d,n->name.name, n->name.name_type,
486                               REGISTER,n->send_ip);
487         }
488     }
489 }
490
491
492 /****************************************************************************
493   report the response record type
494   ****************************************************************************/
495 static void debug_rr_type(int rr_type)
496 {
497   switch (rr_type)
498     {
499     case NMB_STATUS: DEBUG(3,("Name status ")); break;
500     case NMB_QUERY : DEBUG(3,("Name query ")); break;
501     case NMB_REG   : DEBUG(3,("Name registration ")); break;
502     case NMB_REL   : DEBUG(3,("Name release ")); break;
503     default        : DEBUG(1,("wrong response packet type received")); break;
504     }
505 }
506
507 /****************************************************************************
508   report the response record nmbd state
509   ****************************************************************************/
510 void debug_state_type(int state)
511 {
512   /* report the state type to help debugging */
513   switch (state)
514     {
515     case NAME_QUERY_DOM_SRV_CHK  : DEBUG(4,("NAME_QUERY_DOM_SRV_CHK\n")); break;
516     case NAME_QUERY_SRV_CHK      : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
517     case NAME_QUERY_FIND_MST     : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
518     case NAME_QUERY_MST_CHK      : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
519     case NAME_QUERY_CONFIRM      : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
520     case NAME_QUERY_SYNC_LOCAL   : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break;
521     case NAME_QUERY_SYNC_REMOTE  : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break;
522     case NAME_QUERY_ANNOUNCE_HOST: DEBUG(4,("NAME_QUERY_ANNCE_HOST\n"));break;
523       
524     case NAME_REGISTER           : DEBUG(4,("NAME_REGISTER\n")); break;
525     case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break;
526       
527     case NAME_RELEASE            : DEBUG(4,("NAME_RELEASE\n")); break;
528       
529     case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STATUS_DOM_SRV_CHK\n")); break;
530     case NAME_STATUS_SRV_CHK     : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break;
531       
532     default: break;
533     }
534 }
535
536 /****************************************************************************
537   report any problems with the fact that a response has been received.
538
539   (responses for certain types of operations are only expected from one host)
540   ****************************************************************************/
541 static BOOL response_problem_check(struct response_record *n,
542                         struct nmb_packet *nmb, char *ans_name)
543 {
544   switch (nmb->answers->rr_type)
545     {
546     case NMB_REL:
547       {
548         if (n->num_msgs > 1)
549           {
550             DEBUG(1,("more than one release name response received!\n"));
551             return True;
552           }
553         break;
554       }
555
556     case NMB_REG:
557       {
558         if (n->num_msgs > 1)
559           {
560             DEBUG(1,("more than one register name response received!\n"));
561             return True;
562           }
563         break;
564       }
565     
566     case NMB_QUERY:
567       { 
568         if (n->num_msgs > 1)
569           {
570             if (nmb->header.rcode == 0 && nmb->answers->rdata)
571               {
572                 int nb_flags = nmb->answers->rdata[0];
573                 
574                 if ((!NAME_GROUP(nb_flags)))
575                   {
576                     /* oh dear. more than one person responded to a 
577                        unique name.
578                        there is either a network problem, a 
579                        configuration problem
580                        or a server is mis-behaving */
581                     
582                     /* XXXX mark the name as in conflict, and then let the
583                        person who just responded know that they 
584                        must also mark it
585                        as in conflict, and therefore must NOT use it.
586                        see rfc1001.txt 15.1.3.5 */
587                     
588                     /* this may cause problems for some 
589                        early versions of nmbd */
590                     
591                     switch (n->state)
592                       {
593                       case NAME_QUERY_FIND_MST:
594                         {
595                           /* query for ^1^2__MSBROWSE__^2^1 expect 
596                              lots of responses */
597                           return False;
598                         }
599                       case NAME_QUERY_ANNOUNCE_HOST:
600                       case NAME_QUERY_DOM_SRV_CHK:
601                       case NAME_QUERY_SRV_CHK:
602                       case NAME_QUERY_MST_CHK:
603                         {
604                           if (!strequal(ans_name,n->name.name))
605                             {
606                               /* one subnet, one master browser 
607                                  per workgroup */
608                               /* XXXX force an election? */
609                               
610                               DEBUG(3,("more than one master browser replied!\n"));
611                               return True;
612                             }
613                           break;
614                         }
615                       default: break;
616                       }
617                     DEBUG(3,("Unique Name conflict detected!\n"));
618                     return True;
619                   }
620               }
621             else
622               {
623                 /* we have received a negative reply, 
624                    having already received
625                    at least one response (pos/neg). 
626                    something's really wrong! */
627                 
628                 DEBUG(3,("wierd name query problem detected!\n"));
629                 return True;
630               }
631           }
632       }
633     }
634   return False;
635 }
636
637 #if 0
638 /****************************************************************************
639   check that the response received is compatible with the response record
640   ****************************************************************************/
641 static BOOL response_compatible(struct response_record *n,
642                         struct nmb_packet *nmb)
643 {
644   switch (n->state)
645   {
646     case NAME_RELEASE:
647     {
648                 if (nmb->answers->rr_type != 0x20)
649                 {
650                         DEBUG(1,("Name release reply has wrong answer rr_type\n"));
651                         return False;
652                 }
653         break;
654     }
655
656     case NAME_REGISTER:
657     {
658                 if (nmb->answers->rr_type != 0x20)
659                 {
660                         DEBUG(1,("Name register reply has wrong answer rr_type\n"));
661                         return False;
662                 }
663         break;
664     }
665
666     case NAME_REGISTER_CHALLENGE: /* this is a query: we then do a register */
667     case NAME_QUERY_CONFIRM:
668     case NAME_QUERY_ANNOUNCE_HOST:
669     case NAME_QUERY_SYNC_LOCAL:
670     case NAME_QUERY_SYNC_REMOTE:
671     case NAME_QUERY_DOM_SRV_CHK:
672     case NAME_QUERY_SRV_CHK:
673     case NAME_QUERY_FIND_MST:
674     case NAME_QUERY_MST_CHK:
675     {
676                 if (nmb->answers->rr_type != 0x20)
677                 {
678                         DEBUG(1,("Name query reply has wrong answer rr_type\n"));
679                         return False;
680                 }
681                 break;
682     }
683       
684     case NAME_STATUS_DOM_SRV_CHK:
685     case NAME_STATUS_SRV_CHK:
686     {
687                 if (nmb->answers->rr_type != 0x21)
688                 {
689                         DEBUG(1,("Name status reply has wrong answer rr_type\n"));
690                         return False;
691                 }
692                 break;
693     }
694       
695     default:
696     {
697                 DEBUG(1,("unknown state type received in response_netbios_packet\n"));
698                 return False;
699     }
700   }
701   return True;
702 }
703 #endif
704
705
706 /****************************************************************************
707   process the response packet received
708   ****************************************************************************/
709 static void response_process(struct subnet_record *d, struct packet_struct *p,
710                              struct response_record *n, struct nmb_packet *nmb,
711                              BOOL bcast, struct nmb_name *ans_name)
712 {
713   switch (n->state)
714     {
715     case NAME_RELEASE:
716       {
717         response_name_release(ans_name, d, p);
718         break;
719       }
720
721     case NAME_REGISTER:
722       {
723         response_name_reg(ans_name, d, p);
724         break;
725       }
726
727     case NAME_REGISTER_CHALLENGE:
728       {
729         response_name_query_register(nmb, ans_name, n, d);
730         break;
731       }
732
733     case NAME_QUERY_DOM_SRV_CHK:
734     case NAME_QUERY_SRV_CHK:
735     case NAME_QUERY_FIND_MST:
736       {
737         response_server_check(ans_name, n, d);
738         break;
739       }
740     
741     case NAME_STATUS_DOM_SRV_CHK:
742     case NAME_STATUS_SRV_CHK:
743       {
744         response_name_status_check(p->ip, nmb, bcast, n, d);
745         break;
746       }
747     
748     case NAME_QUERY_ANNOUNCE_HOST:
749       {
750         response_announce_host(ans_name, nmb, n, d);
751         break;
752       }
753       
754     case NAME_QUERY_CONFIRM:
755     case NAME_QUERY_SYNC_LOCAL:
756     case NAME_QUERY_SYNC_REMOTE:
757       {
758         response_name_query_sync(nmb, ans_name, bcast, n, d);
759         break;
760       }
761     case NAME_QUERY_MST_CHK:
762       {
763         /* no action required here. it's when NO responses are received
764            that we need to do something. see expire_name_query_entries() */
765         
766         DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n",
767                   namestr(&n->name), inet_ntoa(n->send_ip)));
768         break;
769       }
770     
771     default:
772       {
773         DEBUG(1,("unknown state type received in response_netbios_packet\n"));
774         break;
775       }
776     }
777 }
778
779
780 /****************************************************************************
781   response from a netbios packet.
782   ****************************************************************************/
783 void response_netbios_packet(struct packet_struct *p)
784 {
785   struct nmb_packet *nmb = &p->packet.nmb;
786   struct nmb_name *ans_name = NULL;
787   BOOL bcast = nmb->header.nm_flags.bcast;
788   struct response_record *n;
789   struct subnet_record *d = NULL;
790
791   if (!(n = find_response_record(&d,nmb->header.name_trn_id))) {
792     DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
793     return;
794   }
795
796   if (!d)
797     {
798       DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip)));
799       return;
800     }
801
802   /* args wrong way round: spotted by ccm@shentel.net */
803   if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
804     {
805       DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
806       DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
807     }
808   
809   if (nmb->answers == NULL)
810     {
811       /* hm. the packet received was a response, but with no answer. wierd! */
812       DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
813                inet_ntoa(p->ip), BOOLSTR(bcast)));
814       return;
815     }
816
817   ans_name = &nmb->answers->rr_name;
818   DEBUG(3,("response for %s from %s (bcast=%s)\n",
819            namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast)));
820   
821   debug_rr_type(nmb->answers->rr_type);
822   
823   n->num_msgs++; /* count number of responses received */
824   n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */
825   
826   debug_state_type(n->state);
827   
828   /* problem checking: multiple responses etc */
829   if (response_problem_check(n, nmb, ans_name->name))
830     return;
831   
832   /* now deal with the current state */
833   response_process(d, p, n, nmb, bcast, ans_name);
834 }