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