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