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