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