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