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