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