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