first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[nivanova/samba-autobuild/.git] / source3 / nmbd / nmbd_winsserver.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5
6    Copyright (C) Jeremy Allison 1994-1998
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21    
22 */
23
24 #include "includes.h"
25
26 #define WINS_LIST "wins.dat"
27 #define WINS_VERSION 1
28
29 extern int DEBUGLEVEL;
30 extern struct in_addr ipzero;
31
32
33 /****************************************************************************
34 possibly call the WINS hook external program when a WINS change is made
35 *****************************************************************************/
36 static void wins_hook(char *operation, struct name_record *namerec, int ttl)
37 {
38         pstring command;
39         char *cmd = lp_wins_hook();
40         char *p;
41         int i;
42
43         if (!cmd || !*cmd) return;
44
45         for (p=namerec->name.name; *p; p++) {
46                 if (!(isalnum((int)*p) || strchr("._-",*p))) {
47                         DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
48                         return;
49                 }
50         }
51         
52         p = command;
53         p += slprintf(p, sizeof(command), "%s %s %s %02x %d", 
54                       cmd,
55                       operation, 
56                       namerec->name.name,
57                       namerec->name.name_type,
58                       ttl);
59
60         for (i=0;i<namerec->data.num_ips;i++) {
61                 p += slprintf(p, sizeof(command) - (p-command), " %s", inet_ntoa(namerec->data.ip[i]));
62         }
63
64         DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
65         smbrun(command, NULL, False);
66 }
67
68
69 /****************************************************************************
70 hash our interfaces and netbios names settings
71 *****************************************************************************/
72 static unsigned wins_hash(void)
73 {
74         int i;
75         unsigned ret = iface_hash();
76         extern char **my_netbios_names;
77
78         for (i=0;my_netbios_names[i];i++)
79                 ret ^= str_checksum(my_netbios_names[i]);
80         
81         ret ^= str_checksum(lp_workgroup());
82
83         return ret;
84 }
85         
86
87 /****************************************************************************
88 Determine if this packet should be allocated to the WINS server.
89 *****************************************************************************/
90
91 BOOL packet_is_for_wins_server(struct packet_struct *packet)
92 {
93   struct nmb_packet *nmb = &packet->packet.nmb;
94
95   /* Only unicast packets go to a WINS server. */
96   if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
97   {
98     DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
99     return False;
100   }
101
102   /* Check for node status requests. */
103   if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
104     return False;
105
106   switch(nmb->header.opcode)
107   { 
108     /*
109      * A WINS server issues WACKS, not receives them.
110      */
111     case NMB_WACK_OPCODE:
112       DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
113       return False;
114     /*
115      * A WINS server only processes registration and
116      * release requests, not responses.
117      */
118     case NMB_NAME_REG_OPCODE:
119     case NMB_NAME_MULTIHOMED_REG_OPCODE:
120     case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
121     case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
122       if(nmb->header.response)
123       {
124         DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
125         return False;
126       }
127       break;
128
129     case NMB_NAME_RELEASE_OPCODE:
130       if(nmb->header.response)
131       {
132         DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
133         return False;
134       }
135       break;
136
137     /*
138      * Only process unicast name queries with rd = 1.
139      */
140     case NMB_NAME_QUERY_OPCODE:
141       if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
142       {
143         DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
144         return False;
145       }
146       break;
147   }
148
149   return True;
150 }
151
152 /****************************************************************************
153 Utility function to decide what ttl to give a register/refresh request.
154 *****************************************************************************/
155
156 static int get_ttl_from_packet(struct nmb_packet *nmb)
157 {
158   int ttl = nmb->additional->ttl;
159
160   if(ttl < lp_min_wins_ttl() )
161     ttl = lp_min_wins_ttl();
162
163   if(ttl > lp_max_wins_ttl() )
164     ttl = lp_max_wins_ttl();
165
166   return ttl;
167 }
168
169 /****************************************************************************
170 Load or create the WINS database.
171 *****************************************************************************/
172
173 BOOL initialise_wins(void)
174 {
175   pstring fname;
176   time_t time_now = time(NULL);
177   FILE *fp;
178   pstring line;
179
180   if(!lp_we_are_a_wins_server())
181     return True;
182
183   add_samba_names_to_subnet(wins_server_subnet);
184
185   pstrcpy(fname,lp_lockdir());
186   trim_string(fname,NULL,"/");
187   pstrcat(fname,"/");
188   pstrcat(fname,WINS_LIST);
189
190   if((fp = sys_fopen(fname,"r")) == NULL)
191   {
192     DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
193            fname, strerror(errno) ));
194     return True;
195   }
196
197   while (!feof(fp))
198   {
199     pstring name_str, ip_str, ttl_str, nb_flags_str;
200     unsigned int num_ips;
201     pstring name;
202     struct in_addr *ip_list;
203     int type = 0;
204     int nb_flags;
205     int ttl;
206     char *ptr;
207     char *p;
208     BOOL got_token;
209     BOOL was_ip;
210     int i;
211     unsigned hash;
212     int version;
213
214     /* Read a line from the wins.dat file. Strips whitespace
215        from the beginning and end of the line.
216      */
217     if (!fgets_slash(line,sizeof(pstring),fp))
218       continue;
219       
220     if (*line == '#')
221       continue;
222
223     if (strncmp(line,"VERSION ", 8) == 0) {
224             if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
225                 version != WINS_VERSION ||
226                 hash != wins_hash()) {
227                     DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
228                     fclose(fp);
229                     return True;
230             }
231             continue;
232     }
233
234     ptr = line;
235
236     /* 
237      * Now we handle multiple IP addresses per name we need
238      * to iterate over the line twice. The first time to
239      * determine how many IP addresses there are, the second
240      * time to actually parse them into the ip_list array.
241      */
242
243     if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) 
244     {
245       DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
246       continue;
247     }
248
249     if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
250     {
251       DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
252       continue;
253     }
254
255     /*
256      * Determine the number of IP addresses per line.
257      */
258     num_ips = 0;
259     do
260     {
261       got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
262       was_ip = False;
263
264       if(got_token && strchr(ip_str, '.'))
265       {
266         num_ips++;
267         was_ip = True;
268       }
269     } while( got_token && was_ip);
270
271     if(num_ips == 0)
272     {
273       DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
274       continue;
275     }
276
277     if(!got_token)
278     {
279       DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
280       continue;
281     }
282
283     /* Allocate the space for the ip_list. */
284     if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
285     {
286       DEBUG(0,("initialise_wins: Malloc fail !\n"));
287       return False;
288     }
289  
290     /* Reset and re-parse the line. */
291     ptr = line;
292     next_token(&ptr,name_str,NULL,sizeof(name_str)); 
293     next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
294     for(i = 0; i < num_ips; i++)
295     {
296       next_token(&ptr, ip_str, NULL, sizeof(ip_str));
297       ip_list[i] = *interpret_addr2(ip_str);
298     }
299     next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
300
301     /* 
302      * Deal with SELF or REGISTER name encoding. Default is REGISTER
303      * for compatibility with old nmbds.
304      */
305
306     if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
307     {
308       DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
309       free((char *)ip_list);
310       continue;
311     }
312       
313     if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
314       nb_flags_str[strlen(nb_flags_str)-1] = '\0';
315       
316     /* Netbios name. # divides the name from the type (hex): netbios#xx */
317     pstrcpy(name,name_str);
318       
319     if((p = strchr(name,'#')) != NULL)
320     {
321       *p = 0;
322       sscanf(p+1,"%x",&type);
323     }
324       
325     /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
326     sscanf(nb_flags_str,"%x",&nb_flags);
327     sscanf(ttl_str,"%d",&ttl);
328
329     /* add all entries that have 60 seconds or more to live */
330     if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
331     {
332       if(ttl != PERMANENT_TTL)
333         ttl -= time_now;
334     
335       DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
336            name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
337
338       (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 
339                                     ttl, REGISTER_NAME, num_ips, ip_list );
340
341     }
342     else
343     {
344       DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
345              name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
346     }
347
348     free((char *)ip_list);
349   } 
350     
351   fclose(fp);
352   return True;
353 }
354
355 /****************************************************************************
356 Send a WINS WACK (Wait ACKnowledgement) response.
357 **************************************************************************/
358
359 static void send_wins_wack_response(int ttl, struct packet_struct *p)
360 {
361   struct nmb_packet *nmb = &p->packet.nmb;
362   unsigned char rdata[2];
363
364   rdata[0] = rdata[1] = 0;
365
366   /* Taken from nmblib.c - we need to send back almost
367      identical bytes from the requesting packet header. */
368
369   rdata[0] = (nmb->header.opcode & 0xF) << 3;
370   if (nmb->header.nm_flags.authoritative &&
371       nmb->header.response) rdata[0] |= 0x4;
372   if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
373   if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
374   if (nmb->header.nm_flags.recursion_available &&
375       nmb->header.response) rdata[1] |= 0x80;
376   if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
377
378   reply_netbios_packet(p,                             /* Packet to reply to. */
379                        0,                             /* Result code. */
380                        NMB_WAIT_ACK,                  /* nmbd type code. */
381                        NMB_WACK_OPCODE,               /* opcode. */
382                        ttl,                           /* ttl. */
383                        (char *)rdata,                 /* data to send. */
384                        2);                            /* data length. */
385 }
386
387 /****************************************************************************
388 Send a WINS name registration response.
389 **************************************************************************/
390
391 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
392 {
393   struct nmb_packet *nmb = &p->packet.nmb;
394   char rdata[6];
395
396   memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
397
398   reply_netbios_packet(p,                             /* Packet to reply to. */
399                        rcode,                         /* Result code. */
400                        WINS_REG,                      /* nmbd type code. */
401                        NMB_NAME_REG_OPCODE,           /* opcode. */
402                        ttl,                           /* ttl. */
403                        rdata,                         /* data to send. */
404                        6);                            /* data length. */
405 }
406
407 /***********************************************************************
408  Deal with a name refresh request to a WINS server.
409 ************************************************************************/
410
411 void wins_process_name_refresh_request(struct subnet_record *subrec,
412                                             struct packet_struct *p)
413 {
414   struct nmb_packet *nmb = &p->packet.nmb;
415   struct nmb_name *question = &nmb->question.question_name;
416   BOOL bcast = nmb->header.nm_flags.bcast;
417   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
418   BOOL group = (nb_flags & NB_GROUP) ? True : False;
419   struct name_record *namerec = NULL;
420   int ttl = get_ttl_from_packet(nmb);
421   struct in_addr from_ip;
422
423   putip((char *)&from_ip,&nmb->additional->rdata[2]);
424
425   if(bcast)
426   {
427     /*
428      * We should only get unicast name refresh packets here.
429      * Anyone trying to refresh broadcast should not be going to a WINS
430      * server. Log an error here.
431      */
432
433     DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
434 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
435           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
436     return;
437   }
438
439   DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
440 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
441
442   /* 
443    * See if the name already exists.
444    */
445
446   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
447
448   /*
449    * If this is a refresh request and the name doesn't exist then
450    * treat it like a registration request. This allows us to recover 
451    * from errors (tridge)
452    */
453
454   if(namerec == NULL)
455   {
456     DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
457 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
458     wins_process_name_registration_request(subrec,p);
459     return;
460   }
461
462   /*
463    * Check that the group bits for the refreshing name and the
464    * name in our database match.
465    */
466
467   if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
468   {
469     DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
470 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
471     send_wins_name_registration_response(RFS_ERR, 0, p);
472     return;
473   }
474
475   /*
476    * For a unique name check that the person refreshing the name is one of the registered IP
477    * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
478    * Just return success for unique 0x1d refreshes. For normal group names update the ttl
479    * and return success.
480    */
481
482   if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
483   {
484     /*
485      * Update the ttl.
486      */
487     update_name_ttl(namerec, ttl);
488     send_wins_name_registration_response(0, ttl, p);
489     wins_hook("refresh", namerec, ttl);
490     return;
491   }
492   else if(group)
493   {
494     /* 
495      * Normal groups are all registered with an IP address of 255.255.255.255 
496      * so we can't search for the IP address.
497      */
498     update_name_ttl(namerec, ttl);
499     send_wins_name_registration_response(0, ttl, p);
500     return;
501   }
502   else if(!group && (question->name_type == 0x1d))
503   {
504     /*
505      * Special name type - just pretend the refresh succeeded.
506      */
507     send_wins_name_registration_response(0, ttl, p);
508     return;
509   }
510   else
511   {
512     /*
513      * Fail the refresh.
514      */
515
516     DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
517 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
518     send_wins_name_registration_response(RFS_ERR, 0, p);
519     return;
520   }
521 }
522
523 /***********************************************************************
524  Deal with a name registration request query success to a client that
525  owned the name.
526
527  We have a locked pointer to the original packet stashed away in the
528  userdata pointer. The success here is actually a failure as it means
529  the client we queried wants to keep the name, so we must return
530  a registration failure to the original requestor.
531 ************************************************************************/
532
533 static void wins_register_query_success(struct subnet_record *subrec,
534                                              struct userdata_struct *userdata,
535                                              struct nmb_name *question_name,
536                                              struct in_addr ip,
537                                              struct res_rec *answers)
538 {
539   struct packet_struct *orig_reg_packet;
540
541   memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
542
543   DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
544 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
545
546   send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
547
548   orig_reg_packet->locked = False;
549   free_packet(orig_reg_packet);
550 }
551
552 /***********************************************************************
553  Deal with a name registration request query failure to a client that
554  owned the name.
555
556  We have a locked pointer to the original packet stashed away in the
557  userdata pointer. The failure here is actually a success as it means
558  the client we queried didn't want to keep the name, so we can remove
559  the old name record and then successfully add the new name.
560 ************************************************************************/
561
562 static void wins_register_query_fail(struct subnet_record *subrec,
563                                           struct response_record *rrec,
564                                           struct nmb_name *question_name,
565                                           int rcode)
566 {
567   struct userdata_struct *userdata = rrec->userdata;
568   struct packet_struct *orig_reg_packet;
569   struct name_record *namerec = NULL;
570
571   memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
572
573   /*
574    * We want to just add the name, as we now know the original owner
575    * didn't want it. But we can't just do that as an arbitary
576    * amount of time may have taken place between the name query
577    * request and this timeout/error response. So we check that
578    * the name still exists and is in the same state - if so
579    * we remove it and call wins_process_name_registration_request()
580    * as we know it will do the right thing now.
581    */
582
583   namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
584
585   if( (namerec != NULL)
586    && (namerec->data.source == REGISTER_NAME)
587    && ip_equal(rrec->packet->ip, *namerec->data.ip) )
588   {
589     remove_name_from_namelist( subrec, namerec);
590     namerec = NULL;
591   }
592
593   if(namerec == NULL)
594     wins_process_name_registration_request(subrec, orig_reg_packet);
595   else
596     DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
597 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
598
599   orig_reg_packet->locked = False;
600   free_packet(orig_reg_packet);
601 }
602
603 /***********************************************************************
604  Deal with a name registration request to a WINS server.
605
606  Use the following pseudocode :
607
608  registering_group
609      |
610      |
611      +--------name exists
612      |                  |
613      |                  |
614      |                  +--- existing name is group
615      |                  |                      |
616      |                  |                      |
617      |                  |                      +--- add name (return).
618      |                  |
619      |                  |
620      |                  +--- exiting name is unique
621      |                                         |
622      |                                         |
623      |                                         +--- query existing owner (return).
624      |
625      |
626      +--------name doesn't exist
627                         |
628                         |
629                         +--- add name (return).
630
631  registering_unique
632      |
633      |
634      +--------name exists
635      |                  |
636      |                  |
637      |                  +--- existing name is group 
638      |                  |                      |
639      |                  |                      |
640      |                  |                      +--- fail add (return).
641      |                  | 
642      |                  |
643      |                  +--- exiting name is unique
644      |                                         |
645      |                                         |
646      |                                         +--- query existing owner (return).
647      |
648      |
649      +--------name doesn't exist
650                         |
651                         |
652                         +--- add name (return).
653
654  As can be seen from the above, the two cases may be collapsed onto each
655  other with the exception of the case where the name already exists and
656  is a group name. This case we handle with an if statement.
657  
658 ************************************************************************/
659
660 void wins_process_name_registration_request(struct subnet_record *subrec,
661                                             struct packet_struct *p)
662 {
663   struct nmb_packet *nmb = &p->packet.nmb;
664   struct nmb_name *question = &nmb->question.question_name;
665   BOOL bcast = nmb->header.nm_flags.bcast;
666   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
667   int ttl = get_ttl_from_packet(nmb);
668   struct name_record *namerec = NULL;
669   struct in_addr from_ip;
670   BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
671
672   putip((char *)&from_ip,&nmb->additional->rdata[2]);
673
674   if(bcast)
675   {
676     /*
677      * We should only get unicast name registration packets here.
678      * Anyone trying to register broadcast should not be going to a WINS
679      * server. Log an error here.
680      */
681
682     DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
683 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
684           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
685     return;
686   }
687
688   DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
689 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
690
691   /*
692    * See if the name already exists.
693    */
694
695   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
696
697   /*
698    * Deal with the case where the name found was a dns entry.
699    * Remove it as we now have a NetBIOS client registering the
700    * name.
701    */
702
703   if( (namerec != NULL)
704    && ( (namerec->data.source == DNS_NAME)
705      || (namerec->data.source == DNSFAIL_NAME) ) )
706   {
707     DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
708 a dns lookup - removing it.\n", nmb_namestr(question) ));
709     remove_name_from_namelist( subrec, namerec );
710     namerec = NULL;
711   }
712
713   /*
714    * Reject if the name exists and is not a REGISTER_NAME.
715    * (ie. Don't allow any static names to be overwritten.
716    */
717
718   if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
719   {
720     DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
721 to register name %s. Name already exists in WINS with source type %d.\n",
722                 nmb_namestr(question), namerec->data.source ));
723     send_wins_name_registration_response(RFS_ERR, 0, p);
724     return;
725   }
726
727   /*
728    * Special policy decisions based on MS documentation.
729    * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
730    * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
731    */
732
733   /*
734    * A group name is always added as the local broadcast address, except
735    * for group names ending in 0x1c.
736    * Group names with type 0x1c are registered with individual IP addresses.
737    */
738
739   if(registering_group_name && (question->name_type != 0x1c))
740     from_ip = *interpret_addr2("255.255.255.255");
741
742   /*
743    * Ignore all attempts to register a unique 0x1d name, although return success.
744    */
745
746   if(!registering_group_name && (question->name_type == 0x1d))
747   {
748     DEBUG(3,("wins_process_name_registration_request: Ignoring request \
749 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
750     send_wins_name_registration_response(0, ttl, p);
751     return;
752   }
753
754   /*
755    * Next two cases are the 'if statement' mentioned above.
756    */
757
758   if((namerec != NULL) && NAME_GROUP(namerec))
759   {
760     if(registering_group_name)
761     {
762       /*
763        * If we are adding a group name, the name exists and is also a group entry just add this
764        * IP address to it and update the ttl.
765        */
766
767       DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
768             inet_ntoa(from_ip), nmb_namestr(question) ));
769       /* 
770        * Check the ip address is not already in the group.
771        */
772       if(!find_ip_in_name_record(namerec, from_ip))
773         add_ip_to_name_record(namerec, from_ip);
774       update_name_ttl(namerec, ttl);
775       send_wins_name_registration_response(0, ttl, p);
776       return;
777     }
778     else
779     {
780       /*
781        * If we are adding a unique name, the name exists in the WINS db 
782        * and is a group name then reject the registration.
783        */
784
785       DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
786 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
787       send_wins_name_registration_response(RFS_ERR, 0, p);
788       return;
789     } 
790   }
791
792   /*
793    * From here on down we know that if the name exists in the WINS db it is
794    * a unique name, not a group name.
795    */
796
797   /* 
798    * If the name exists and is one of our names then check the
799    * registering IP address. If it's not one of ours then automatically
800    * reject without doing the query - we know we will reject it.
801    */
802
803   if((namerec != NULL) && (is_myname(namerec->name.name)) )
804   {
805     if(!ismyip(from_ip))
806     {
807       DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
808 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
809       send_wins_name_registration_response(RFS_ERR, 0, p);
810       return;
811     }
812     else
813     {
814       /*
815        * It's one of our names and one of our IP's - update the ttl.
816        */
817       update_name_ttl(namerec, ttl);
818       send_wins_name_registration_response(0, ttl, p);
819       wins_hook("refresh", namerec, ttl);
820       return;
821     }
822   }
823
824   /*
825    * If the name exists and it is a unique registration and the registering IP 
826    * is the same as the the (single) already registered IP then just update the ttl.
827    */
828
829   if( !registering_group_name
830    && (namerec != NULL)
831    && (namerec->data.num_ips == 1)
832    && ip_equal( namerec->data.ip[0], from_ip ) )
833   {
834     update_name_ttl( namerec, ttl );
835     send_wins_name_registration_response( 0, ttl, p );
836     wins_hook("refresh", namerec, ttl);
837     return;
838   }
839
840   /*
841    * Finally if the name exists do a query to the registering machine 
842    * to see if they still claim to have the name.
843    */
844
845   if( namerec != NULL )
846   {
847     char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
848     struct userdata_struct *userdata = (struct userdata_struct *)ud;
849
850     /*
851      * First send a WACK to the registering machine.
852      */
853
854     send_wins_wack_response(60, p);
855
856     /*
857      * When the reply comes back we need the original packet.
858      * Lock this so it won't be freed and then put it into
859      * the userdata structure.
860      */
861
862     p->locked = True;
863
864     userdata = (struct userdata_struct *)ud;
865
866     userdata->copy_fn = NULL;
867     userdata->free_fn = NULL;
868     userdata->userdata_len = sizeof(struct packet_struct *);
869     memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
870
871     /*
872      * Use the new call to send a query directly to an IP address.
873      * This sends the query directly to the IP address, and ensures
874      * the recursion desired flag is not set (you were right Luke :-).
875      * This function should *only* be called from the WINS server
876      * code. JRA.
877      */
878
879     query_name_from_wins_server( *namerec->data.ip,
880                                   question->name,
881                                   question->name_type, 
882                                   wins_register_query_success,
883                                   wins_register_query_fail,
884                                   userdata );
885     return;
886   }
887
888   /*
889    * Name did not exist - add it.
890    */
891
892   (void)add_name_to_subnet( subrec, question->name, question->name_type,
893                             nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
894   if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
895           wins_hook("add", namerec, ttl);
896   }
897
898   send_wins_name_registration_response(0, ttl, p);
899 }
900
901 /***********************************************************************
902  Deal with a mutihomed name query success to the machine that
903  requested the multihomed name registration.
904
905  We have a locked pointer to the original packet stashed away in the
906  userdata pointer.
907 ************************************************************************/
908
909 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
910                                              struct userdata_struct *userdata,
911                                              struct nmb_name *question_name,
912                                              struct in_addr ip,
913                                              struct res_rec *answers)
914 {
915   struct packet_struct *orig_reg_packet;
916   struct nmb_packet *nmb;
917   struct name_record *namerec = NULL;
918   struct in_addr from_ip;
919   int ttl;
920
921   memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
922
923   nmb = &orig_reg_packet->packet.nmb;
924
925   putip((char *)&from_ip,&nmb->additional->rdata[2]);
926   ttl = get_ttl_from_packet(nmb);
927
928   /*
929    * We want to just add the new IP, as we now know the requesting
930    * machine claims to own it. But we can't just do that as an arbitary
931    * amount of time may have taken place between the name query
932    * request and this response. So we check that
933    * the name still exists and is in the same state - if so
934    * we just add the extra IP and update the ttl.
935    */
936
937   namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
938
939   if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) )
940   {
941     DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
942 a subsequent IP addess.\n", nmb_namestr(question_name) ));
943     send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
944
945     orig_reg_packet->locked = False;
946     free_packet(orig_reg_packet);
947
948     return;
949   }
950
951   if(!find_ip_in_name_record(namerec, from_ip))
952     add_ip_to_name_record(namerec, from_ip);
953   update_name_ttl(namerec, ttl);
954   send_wins_name_registration_response(0, ttl, orig_reg_packet);
955   wins_hook("add", namerec, ttl);
956
957   orig_reg_packet->locked = False;
958   free_packet(orig_reg_packet);
959 }
960
961 /***********************************************************************
962  Deal with a name registration request query failure to a client that
963  owned the name.
964
965  We have a locked pointer to the original packet stashed away in the
966  userdata pointer.
967 ************************************************************************/
968
969 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
970                                           struct response_record *rrec,
971                                           struct nmb_name *question_name,
972                                           int rcode)
973 {
974   struct userdata_struct *userdata = rrec->userdata;
975   struct packet_struct *orig_reg_packet;
976
977   memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
978
979   DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
980 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
981   send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
982
983   orig_reg_packet->locked = False;
984   free_packet(orig_reg_packet);
985   return;
986 }
987
988 /***********************************************************************
989  Deal with a multihomed name registration request to a WINS server.
990  These cannot be group name registrations.
991 ***********************************************************************/
992
993 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
994                                                         struct packet_struct *p)
995 {
996   struct nmb_packet *nmb = &p->packet.nmb;
997   struct nmb_name *question = &nmb->question.question_name;
998   BOOL bcast = nmb->header.nm_flags.bcast;
999   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1000   int ttl = get_ttl_from_packet(nmb);
1001   struct name_record *namerec = NULL;
1002   struct in_addr from_ip;
1003   BOOL group = (nb_flags & NB_GROUP) ? True : False;;
1004
1005   putip((char *)&from_ip,&nmb->additional->rdata[2]);
1006
1007   if(bcast)
1008   {
1009     /*
1010      * We should only get unicast name registration packets here.
1011      * Anyone trying to register broadcast should not be going to a WINS
1012      * server. Log an error here.
1013      */
1014
1015     DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1016 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1017           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1018     return;
1019   }
1020
1021   /*
1022    * Only unique names should be registered multihomed.
1023    */
1024
1025   if(group)
1026   {
1027     DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1028 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1029           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1030     return;
1031   }
1032
1033   DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1034 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1035
1036   /*
1037    * Deal with policy regarding 0x1d names.
1038    */
1039
1040   if(question->name_type == 0x1d)
1041   {
1042     DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1043 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1044     send_wins_name_registration_response(0, ttl, p);  
1045     return;
1046   }
1047
1048   /*
1049    * See if the name already exists.
1050    */
1051
1052   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1053
1054   /*
1055    * Deal with the case where the name found was a dns entry.
1056    * Remove it as we now have a NetBIOS client registering the
1057    * name.
1058    */
1059
1060   if( (namerec != NULL)
1061    && ( (namerec->data.source == DNS_NAME)
1062      || (namerec->data.source == DNSFAIL_NAME) ) )
1063   {
1064     DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1065 - removing it.\n", nmb_namestr(question) ));
1066     remove_name_from_namelist( subrec, namerec);
1067     namerec = NULL;
1068   }
1069
1070   /*
1071    * Reject if the name exists and is not a REGISTER_NAME.
1072    * (ie. Don't allow any static names to be overwritten.
1073    */
1074
1075   if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1076   {
1077     DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1078 to register name %s. Name already exists in WINS with source type %d.\n",
1079     nmb_namestr(question), namerec->data.source ));
1080     send_wins_name_registration_response(RFS_ERR, 0, p);
1081     return;
1082   }
1083
1084   /*
1085    * Reject if the name exists and is a GROUP name.
1086    */
1087
1088   if((namerec != NULL) && NAME_GROUP(namerec))
1089   {
1090     DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1091 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1092     send_wins_name_registration_response(RFS_ERR, 0, p);
1093     return;
1094   } 
1095
1096   /*
1097    * From here on down we know that if the name exists in the WINS db it is
1098    * a unique name, not a group name.
1099    */
1100
1101   /*
1102    * If the name exists and is one of our names then check the
1103    * registering IP address. If it's not one of ours then automatically
1104    * reject without doing the query - we know we will reject it.
1105    */
1106
1107   if((namerec != NULL) && (is_myname(namerec->name.name)) )
1108   {
1109     if(!ismyip(from_ip))
1110     {
1111       DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1112 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1113       send_wins_name_registration_response(RFS_ERR, 0, p);
1114       return;
1115     }
1116     else
1117     {
1118       /*
1119        * It's one of our names and one of our IP's. Ensure the IP is in the record and
1120        *  update the ttl.
1121        */
1122             if(!find_ip_in_name_record(namerec, from_ip)) {
1123                     add_ip_to_name_record(namerec, from_ip);
1124                     wins_hook("add", namerec, ttl);
1125             } else {
1126                     wins_hook("refresh", namerec, ttl);
1127             }
1128
1129             update_name_ttl(namerec, ttl);
1130             send_wins_name_registration_response(0, ttl, p);
1131             return;
1132     }
1133   }
1134
1135   /*
1136    * If the name exists check if the IP address is already registered
1137    * to that name. If so then update the ttl and reply success.
1138    */
1139
1140   if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip))
1141   {
1142     update_name_ttl(namerec, ttl);
1143     send_wins_name_registration_response(0, ttl, p);
1144     wins_hook("refresh", namerec, ttl);
1145     return;
1146   }
1147
1148   /*
1149    * If the name exists do a query to the owner
1150    * to see if they still want the name.
1151    */
1152
1153   if(namerec != NULL)
1154   {
1155     char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
1156     struct userdata_struct *userdata = (struct userdata_struct *)ud;
1157
1158     /*
1159      * First send a WACK to the registering machine.
1160      */
1161
1162     send_wins_wack_response(60, p);
1163
1164     /*
1165      * When the reply comes back we need the original packet.
1166      * Lock this so it won't be freed and then put it into
1167      * the userdata structure.
1168      */
1169
1170     p->locked = True;
1171
1172     userdata = (struct userdata_struct *)ud;
1173
1174     userdata->copy_fn = NULL;
1175     userdata->free_fn = NULL;
1176     userdata->userdata_len = sizeof(struct packet_struct *);
1177     memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1178
1179     /* 
1180      * Use the new call to send a query directly to an IP address.
1181      * This sends the query directly to the IP address, and ensures
1182      * the recursion desired flag is not set (you were right Luke :-).
1183      * This function should *only* be called from the WINS server
1184      * code. JRA.
1185      */
1186
1187     query_name_from_wins_server( p->ip,
1188                                  question->name,
1189                                  question->name_type, 
1190                                  wins_multihomed_register_query_success,
1191                                  wins_multihomed_register_query_fail,
1192                                  userdata );
1193
1194     return;
1195   }
1196
1197   /*
1198    * Name did not exist - add it.
1199    */
1200
1201   (void)add_name_to_subnet( subrec, question->name, question->name_type,
1202                             nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
1203
1204   if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1205           wins_hook("add", namerec, ttl);
1206   }
1207
1208   send_wins_name_registration_response(0, ttl, p);
1209 }
1210
1211 /***********************************************************************
1212  Deal with the special name query for *<1b>.
1213 ***********************************************************************/
1214    
1215 static void process_wins_dmb_query_request(struct subnet_record *subrec,  
1216                                            struct packet_struct *p)
1217 {  
1218   struct name_record *namerec = NULL;
1219   char *prdata;
1220   int num_ips;
1221
1222   /*
1223    * Go through all the names in the WINS db looking for those
1224    * ending in <1b>. Use this to calculate the number of IP
1225    * addresses we need to return.
1226    */
1227
1228   num_ips = 0;
1229   for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1230        namerec;
1231        namerec = (struct name_record *)ubi_trNext( namerec ) )
1232   {
1233     if( namerec->name.name_type == 0x1b )
1234       num_ips += namerec->data.num_ips;
1235   }
1236
1237   if(num_ips == 0)
1238   {
1239     /*
1240      * There are no 0x1b names registered. Return name query fail.
1241      */
1242     send_wins_name_query_response(NAM_ERR, p, NULL);
1243     return;
1244   }
1245
1246   if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1247   {
1248     DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1249     return;
1250   }
1251
1252   /*
1253    * Go through all the names again in the WINS db looking for those
1254    * ending in <1b>. Add their IP addresses into the list we will
1255    * return.
1256    */ 
1257
1258   num_ips = 0;
1259   for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1260        namerec;
1261        namerec = (struct name_record *)ubi_trNext( namerec ) )
1262   {
1263     if(namerec->name.name_type == 0x1b)
1264     {
1265       int i;
1266       for(i = 0; i < namerec->data.num_ips; i++)
1267       {
1268         set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1269         putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1270         num_ips++;
1271       }
1272     }
1273   }
1274
1275   /*
1276    * Send back the reply containing the IP list.
1277    */
1278
1279   reply_netbios_packet(p,                             /* Packet to reply to. */
1280                        0,                             /* Result code. */
1281                        WINS_QUERY,                    /* nmbd type code. */
1282                        NMB_NAME_QUERY_OPCODE,         /* opcode. */
1283                        lp_min_wins_ttl(),             /* ttl. */
1284                        prdata,                        /* data to send. */
1285                        num_ips*6);                    /* data length. */
1286
1287   free(prdata);
1288 }
1289
1290 /****************************************************************************
1291 Send a WINS name query response.
1292 **************************************************************************/
1293
1294 void send_wins_name_query_response(int rcode, struct packet_struct *p, 
1295                                           struct name_record *namerec)
1296 {
1297   char rdata[6];
1298   char *prdata = rdata;
1299   int reply_data_len = 0;
1300   int ttl = 0;
1301   int i;
1302
1303   memset(rdata,'\0',6);
1304
1305   if(rcode == 0)
1306   {
1307     ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1308              namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1309
1310     /* Copy all known ip addresses into the return data. */
1311     /* Optimise for the common case of one IP address so
1312        we don't need a malloc. */
1313
1314     if( namerec->data.num_ips == 1 )
1315       prdata = rdata;
1316     else
1317     {
1318       if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1319       {
1320         DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1321         return;
1322       }
1323     }
1324
1325     for(i = 0; i < namerec->data.num_ips; i++)
1326     {
1327       set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1328       putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1329     }
1330
1331     sort_query_replies(prdata, i, p->ip);
1332
1333     reply_data_len = namerec->data.num_ips * 6;
1334   }
1335
1336   reply_netbios_packet(p,                             /* Packet to reply to. */
1337                        rcode,                         /* Result code. */
1338                        WINS_QUERY,                    /* nmbd type code. */
1339                        NMB_NAME_QUERY_OPCODE,         /* opcode. */
1340                        ttl,                           /* ttl. */
1341                        prdata,                        /* data to send. */
1342                        reply_data_len);               /* data length. */
1343
1344   if((prdata != rdata) && (prdata != NULL))
1345     free(prdata);
1346 }
1347
1348 /***********************************************************************
1349  Deal with a name query.
1350 ***********************************************************************/
1351
1352 void wins_process_name_query_request(struct subnet_record *subrec, 
1353                                      struct packet_struct *p)
1354 {
1355   struct nmb_packet *nmb = &p->packet.nmb;
1356   struct nmb_name *question = &nmb->question.question_name;
1357   struct name_record *namerec = NULL;
1358
1359   DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 
1360             nmb_namestr(question), inet_ntoa(p->ip) ));
1361
1362   /*
1363    * Special name code. If the queried name is *<1b> then search
1364    * the entire WINS database and return a list of all the IP addresses
1365    * registered to any <1b> name. This is to allow domain master browsers
1366    * to discover other domains that may not have a presence on their subnet.
1367    */
1368
1369   if(strequal( question->name, "*") && (question->name_type == 0x1b))
1370   {
1371     process_wins_dmb_query_request( subrec, p);
1372     return;
1373   }
1374
1375   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1376
1377   if(namerec != NULL)
1378   {
1379     /* 
1380      * If it's a DNSFAIL_NAME then reply name not found.
1381      */
1382
1383     if( namerec->data.source == DNSFAIL_NAME )
1384     {
1385       DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1386              nmb_namestr(question) ));
1387       send_wins_name_query_response(NAM_ERR, p, namerec);
1388       return;
1389     }
1390
1391     /*
1392      * If the name has expired then reply name not found.
1393      */
1394
1395     if( (namerec->data.death_time != PERMANENT_TTL)
1396      && (namerec->data.death_time < p->timestamp) )
1397     {
1398       DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1399                 nmb_namestr(question) ));
1400       send_wins_name_query_response(NAM_ERR, p, namerec);
1401       return;
1402     }
1403
1404     DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1405            nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1406
1407     send_wins_name_query_response(0, p, namerec);
1408     return;
1409   }
1410
1411   /* 
1412    * Name not found in WINS - try a dns query if it's a 0x20 name.
1413    */
1414
1415   if(lp_dns_proxy() && 
1416      ((question->name_type == 0x20) || question->name_type == 0))
1417   {
1418
1419     DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1420               nmb_namestr(question) ));
1421
1422     queue_dns_query(p, question, &namerec);
1423     return;
1424   }
1425
1426   /*
1427    * Name not found - return error.
1428    */
1429
1430   send_wins_name_query_response(NAM_ERR, p, NULL);
1431 }
1432
1433 /****************************************************************************
1434 Send a WINS name release response.
1435 **************************************************************************/
1436
1437 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1438 {
1439   struct nmb_packet *nmb = &p->packet.nmb;
1440   char rdata[6];
1441
1442   memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1443
1444   reply_netbios_packet(p,                            /* Packet to reply to. */
1445                        rcode,                        /* Result code. */
1446                        NMB_REL,                      /* nmbd type code. */
1447                        NMB_NAME_RELEASE_OPCODE,      /* opcode. */
1448                        0,                            /* ttl. */
1449                        rdata,                        /* data to send. */
1450                        6);                           /* data length. */
1451 }
1452
1453 /***********************************************************************
1454  Deal with a name release.
1455 ***********************************************************************/
1456
1457 void wins_process_name_release_request(struct subnet_record *subrec,
1458                                        struct packet_struct *p)
1459 {
1460   struct nmb_packet *nmb = &p->packet.nmb;
1461   struct nmb_name *question = &nmb->question.question_name;
1462   BOOL bcast = nmb->header.nm_flags.bcast;
1463   uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1464   struct name_record *namerec = NULL;
1465   struct in_addr from_ip;
1466   BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1467
1468   putip((char *)&from_ip,&nmb->additional->rdata[2]);
1469
1470   if(bcast)
1471   {
1472     /*
1473      * We should only get unicast name registration packets here.
1474      * Anyone trying to register broadcast should not be going to a WINS
1475      * server. Log an error here.
1476      */
1477
1478     DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1479 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1480           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1481     return;
1482   }
1483   
1484   DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1485 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1486     
1487   /*
1488    * Deal with policy regarding 0x1d names.
1489    */
1490
1491   if(!releasing_group_name && (question->name_type == 0x1d))
1492   {
1493     DEBUG(3,("wins_process_name_release_request: Ignoring request \
1494 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1495     send_wins_name_release_response(0, p);
1496     return;
1497   }
1498
1499   /*
1500    * See if the name already exists.
1501    */
1502     
1503   namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1504
1505   if( (namerec == NULL)
1506    || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1507   {
1508     send_wins_name_release_response(NAM_ERR, p);
1509     return;
1510   }
1511
1512   /* 
1513    * Check that the sending machine has permission to release this name.
1514    * If it's a group name not ending in 0x1c then just say yes and let
1515    * the group time out.
1516    */
1517
1518   if(releasing_group_name && (question->name_type != 0x1c))
1519   {
1520     send_wins_name_release_response(0, p);
1521     return;
1522   }
1523
1524   /* 
1525    * Check that the releasing node is on the list of IP addresses
1526    * for this name. Disallow the release if not.
1527    */
1528
1529   if(!find_ip_in_name_record(namerec, from_ip))
1530   {
1531     DEBUG(3,("wins_process_name_release_request: Refusing request to \
1532 release name %s as IP %s is not one of the known IP's for this name.\n",
1533            nmb_namestr(question), inet_ntoa(from_ip) ));
1534     send_wins_name_release_response(NAM_ERR, p);
1535     return;
1536   }    
1537
1538   /* 
1539    * Release the name and then remove the IP from the known list.
1540    */
1541
1542   send_wins_name_release_response(0, p);
1543   remove_ip_from_name_record(namerec, from_ip);
1544
1545   wins_hook("delete", namerec, 0);
1546
1547   /* 
1548    * Remove the name entirely if no IP addresses left.
1549    */
1550   if (namerec->data.num_ips == 0)
1551     remove_name_from_namelist(subrec, namerec);
1552
1553 }
1554
1555 /*******************************************************************
1556  WINS time dependent processing.
1557 ******************************************************************/
1558
1559 void initiate_wins_processing(time_t t)
1560 {
1561   static time_t lasttime = 0;
1562
1563   if (!lasttime)
1564     lasttime = t;
1565   if (t - lasttime < 20)
1566     return;
1567
1568   lasttime = t;
1569
1570   if(!lp_we_are_a_wins_server())
1571     return;
1572
1573   expire_names_on_subnet(wins_server_subnet, t);
1574
1575   if(wins_server_subnet->namelist_changed)
1576     wins_write_database(True);
1577
1578   wins_server_subnet->namelist_changed = False;
1579 }
1580
1581 /*******************************************************************
1582  Write out the current WINS database.
1583 ******************************************************************/
1584 void wins_write_database(BOOL background)
1585 {
1586   struct name_record *namerec;
1587   pstring fname, fnamenew;
1588
1589   FILE *fp;
1590    
1591   if(!lp_we_are_a_wins_server())
1592     return;
1593
1594   /* we will do the writing in a child process to ensure that the parent
1595      doesn't block while this is done */
1596   if (background) {
1597           CatchChild();
1598           if (fork()) {
1599                   return;
1600           }
1601   }
1602
1603   slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST);
1604   all_string_sub(fname,"//", "/", 0);
1605   slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid());
1606
1607   if((fp = sys_fopen(fnamenew,"w")) == NULL)
1608   {
1609     DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1610     if (background) {
1611             _exit(0);
1612     }
1613     return;
1614   }
1615
1616   DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1617
1618   fprintf(fp,"VERSION %d %u\n", WINS_VERSION, wins_hash());
1619  
1620   for( namerec 
1621            = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1622        namerec;
1623        namerec = (struct name_record *)ubi_trNext( namerec ) )
1624   {
1625     int i;
1626     struct tm *tm;
1627
1628     DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1629
1630     if( namerec->data.death_time != PERMANENT_TTL )
1631     {
1632       char *ts, *nl;
1633
1634       tm = LocalTime(&namerec->data.death_time);
1635       ts = asctime(tm);
1636       nl = strrchr( ts, '\n' );
1637       if( NULL != nl )
1638         *nl = '\0';
1639       DEBUGADD(4,("TTL = %s  ", ts ));
1640     }
1641     else
1642       DEBUGADD(4,("TTL = PERMANENT                 "));
1643
1644     for (i = 0; i < namerec->data.num_ips; i++)
1645       DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1646     DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1647
1648     if( namerec->data.source == REGISTER_NAME )
1649     {
1650       fprintf(fp, "\"%s#%02x\" %d ",
1651               namerec->name.name,namerec->name.name_type, /* Ignore scope. */
1652               (int)namerec->data.death_time);
1653
1654       for (i = 0; i < namerec->data.num_ips; i++)
1655         fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1656       fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1657     }
1658   }
1659   
1660   fclose(fp);
1661   chmod(fnamenew,0644);
1662   unlink(fname);
1663   rename(fnamenew,fname);
1664   if (background) {
1665           _exit(0);
1666   }
1667 }