s3:nmbd: Fix size type in nmbd_browsesync.c
[samba.git] / source3 / nmbd / nmbd_winsserver.c
1 /* 
2    Unix SMB/CIFS implementation.
3    NBT netbios routines and daemon - version 2
4
5    Copyright (C) Jeremy Allison 1994-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 3 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, see <http://www.gnu.org/licenses/>.
19
20    Converted to store WINS data in a tdb. Dec 2005. JRA.
21 */
22
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "nmbd/nmbd.h"
26 #include "util_tdb.h"
27
28 #define WINS_LIST "wins.dat"
29 #define WINS_VERSION 1
30 #define WINSDB_VERSION 1
31
32 /****************************************************************************
33  We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
34  name (65 bytes with the last byte being the name type).
35 *****************************************************************************/
36
37 TDB_CONTEXT *wins_tdb;
38
39 /****************************************************************************
40  Delete all the temporary name records on the in-memory linked list.
41 *****************************************************************************/
42
43 static void wins_delete_all_tmp_in_memory_records(void)
44 {
45         struct name_record *nr = NULL;
46         struct name_record *nrnext = NULL;
47
48         /* Delete all temporary name records on the wins subnet linked list. */
49         for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
50                 nrnext = nr->next;
51                 DLIST_REMOVE(wins_server_subnet->namelist, nr);
52                 SAFE_FREE(nr->data.ip);
53                 SAFE_FREE(nr);
54         }
55 }
56
57 /****************************************************************************
58  Delete all the temporary 1b name records on the in-memory linked list.
59 *****************************************************************************/
60
61 static void wins_delete_all_1b_in_memory_records(void)
62 {
63         struct name_record *nr = NULL;
64         struct name_record *nrnext = NULL;
65
66         /* Delete all temporary 1b name records on the wins subnet linked list. */
67         for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
68                 nrnext = nr->next;
69                 if (nr->name.name_type == 0x1b) {
70                         DLIST_REMOVE(wins_server_subnet->namelist, nr);
71                         SAFE_FREE(nr->data.ip);
72                         SAFE_FREE(nr);
73                 }
74         }
75 }
76
77 /****************************************************************************
78  Convert a wins.tdb record to a struct name_record. Add in our lp_netbios_scope().
79 *****************************************************************************/
80
81 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
82 {
83         struct name_record *namerec = NULL;
84         uint16_t nb_flags;
85         unsigned char nr_src;
86         uint32_t death_time, refresh_time;
87         uint32_t id_low, id_high;
88         uint32_t saddr;
89         uint32_t wins_flags;
90         uint32_t num_ips;
91         size_t len;
92         int i;
93
94         if (data.dptr == NULL || data.dsize == 0) {
95                 return NULL;
96         }
97
98         /* Min size is "wbddddddd" + 1 ip address (4). */
99         if (data.dsize < 2 + 1 + (7*4) + 4) {
100                 return NULL;
101         }
102
103         len = tdb_unpack(data.dptr, data.dsize,
104                         "wbddddddd",
105                         &nb_flags,
106                         &nr_src,
107                         &death_time,
108                         &refresh_time,
109                         &id_low,
110                         &id_high,
111                         &saddr,
112                         &wins_flags,
113                         &num_ips );
114
115         namerec = SMB_MALLOC_P(struct name_record);
116         if (!namerec) {
117                 return NULL;
118         }
119         ZERO_STRUCTP(namerec);
120
121         namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
122         if (!namerec->data.ip) {
123                 SAFE_FREE(namerec);
124                 return NULL;
125         }
126
127         namerec->subnet = wins_server_subnet;
128         push_ascii_nstring(namerec->name.name, (const char *)key.dptr);
129         namerec->name.name_type = key.dptr[sizeof(unstring)];
130         /* Add the scope. */
131         push_ascii(namerec->name.scope, lp_netbios_scope(), 64, STR_TERMINATE);
132
133         /* We're using a byte-by-byte compare, so we must be sure that
134          * unused space doesn't have garbage in it.
135          */
136
137         for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
138                 namerec->name.name[i] = '\0';
139         }
140         for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
141                 namerec->name.scope[i] = '\0';
142         }
143
144         namerec->data.nb_flags = nb_flags;
145         namerec->data.source = (enum name_source)nr_src;
146         namerec->data.death_time = (time_t)death_time;
147         namerec->data.refresh_time = (time_t)refresh_time;
148         namerec->data.id = id_low;
149         namerec->data.id |= ((uint64_t)id_high << 32);
150         namerec->data.wins_ip.s_addr = saddr;
151         namerec->data.wins_flags = wins_flags,
152         namerec->data.num_ips = num_ips;
153
154         for (i = 0; i < num_ips; i++) {
155                 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
156         }
157
158         return namerec;
159 }
160
161 /****************************************************************************
162  Convert a struct name_record to a wins.tdb record. Ignore the scope.
163 *****************************************************************************/
164
165 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
166 {
167         TDB_DATA data;
168         size_t len = 0;
169         int i;
170         uint32_t id_low = (namerec->data.id & 0xFFFFFFFF);
171         uint32_t id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
172
173         ZERO_STRUCT(data);
174
175         len = (2 + 1 + (7*4)); /* "wbddddddd" */
176         len += (namerec->data.num_ips * 4);
177
178         data.dptr = (uint8_t *)SMB_MALLOC(len);
179         if (!data.dptr) {
180                 return data;
181         }
182         data.dsize = len;
183
184         len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
185                         namerec->data.nb_flags,
186                         (unsigned char)namerec->data.source,
187                         (uint32_t)namerec->data.death_time,
188                         (uint32_t)namerec->data.refresh_time,
189                         id_low,
190                         id_high,
191                         (uint32_t)namerec->data.wins_ip.s_addr,
192                         (uint32_t)namerec->data.wins_flags,
193                         (uint32_t)namerec->data.num_ips );
194
195         for (i = 0; i < namerec->data.num_ips; i++) {
196                 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
197         }
198
199         return data;
200 }
201
202 /****************************************************************************
203  Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
204 *****************************************************************************/
205
206 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
207 {
208         static char keydata[sizeof(unstring) + 1];
209         TDB_DATA key;
210
211         memset(keydata, '\0', sizeof(keydata));
212
213         pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
214         (void)strupper_m(keydata);
215         keydata[sizeof(unstring)] = nmbname->name_type;
216         key.dptr = (uint8_t *)keydata;
217         key.dsize = sizeof(keydata);
218
219         return key;
220 }
221
222 /****************************************************************************
223  Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
224  on the linked list. We will free this later in XXXX().
225 *****************************************************************************/
226
227 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only)
228 {
229         TDB_DATA data, key;
230         struct name_record *nr = NULL;
231         struct name_record *namerec = NULL;
232
233         if (!wins_tdb) {
234                 return NULL;
235         }
236
237         key = name_to_key(nmbname);
238         data = tdb_fetch(wins_tdb, key);
239
240         if (data.dsize == 0) {
241                 return NULL;
242         }
243
244         namerec = wins_record_to_name_record(key, data);
245
246         /* done with the this */
247
248         SAFE_FREE( data.dptr );
249
250         if (!namerec) {
251                 return NULL;
252         }
253
254         /* Self names only - these include permanent names. */
255         if( self_only && (namerec->data.source != SELF_NAME) && (namerec->data.source != PERMANENT_NAME) ) {
256                 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname) ) );
257                 SAFE_FREE(namerec->data.ip);
258                 SAFE_FREE(namerec);
259                 return NULL;
260         }
261
262         /* Search for this name record on the list. Replace it if found. */
263
264         for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
265                 if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
266                         /* Delete it. */
267                         DLIST_REMOVE(wins_server_subnet->namelist, nr);
268                         SAFE_FREE(nr->data.ip);
269                         SAFE_FREE(nr);
270                         break;
271                 }
272         }
273
274         DLIST_ADD(wins_server_subnet->namelist, namerec);
275         return namerec;
276 }
277
278 /****************************************************************************
279  Overwrite or add a given name in the wins.tdb.
280 *****************************************************************************/
281
282 static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
283 {
284         TDB_DATA key, data;
285         int ret;
286
287         if (!wins_tdb) {
288                 return False;
289         }
290
291         key = name_to_key(&namerec->name);
292         data = name_record_to_wins_record(namerec);
293
294         if (data.dptr == NULL) {
295                 return False;
296         }
297
298         ret = tdb_store(wins_tdb, key, data, tdb_flag);
299
300         SAFE_FREE(data.dptr);
301         return (ret == 0) ? True : False;
302 }
303
304 /****************************************************************************
305  Overwrite a given name in the wins.tdb.
306 *****************************************************************************/
307
308 bool wins_store_changed_namerec(const struct name_record *namerec)
309 {
310         return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
311 }
312
313 /****************************************************************************
314  Primary interface into creating and overwriting records in the wins.tdb.
315 *****************************************************************************/
316
317 bool add_name_to_wins_subnet(const struct name_record *namerec)
318 {
319         return store_or_replace_wins_namerec(namerec, TDB_INSERT);
320 }
321
322 /****************************************************************************
323  Delete a given name in the tdb and remove the temporary malloc'ed data struct
324  on the linked list.
325 *****************************************************************************/
326
327 bool remove_name_from_wins_namelist(struct name_record *namerec)
328 {
329         TDB_DATA key;
330         int ret;
331
332         if (!wins_tdb) {
333                 return False;
334         }
335
336         key = name_to_key(&namerec->name);
337         ret = tdb_delete(wins_tdb, key);
338
339         DLIST_REMOVE(wins_server_subnet->namelist, namerec);
340
341         /* namerec must be freed by the caller */
342
343         return (ret == 0) ? True : False;
344 }
345
346 /****************************************************************************
347  Dump out the complete namelist.
348 *****************************************************************************/
349
350 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
351 {
352         struct name_record *namerec = NULL;
353         FILE *fp = (FILE *)state;
354
355         if (kbuf.dsize != sizeof(unstring) + 1) {
356                 return 0;
357         }
358
359         namerec = wins_record_to_name_record(kbuf, dbuf);
360         if (!namerec) {
361                 return 0;
362         }
363
364         dump_name_record(namerec, fp);
365
366         SAFE_FREE(namerec->data.ip);
367         SAFE_FREE(namerec);
368         return 0;
369 }
370
371 void dump_wins_subnet_namelist(FILE *fp)
372 {
373         tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
374 }
375
376 /****************************************************************************
377  Change the wins owner address in the record.
378 *****************************************************************************/
379
380 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
381 {
382         namerec->data.wins_ip=wins_ip;
383 }
384
385 /****************************************************************************
386  Create the wins flags based on the nb flags and the input value.
387 *****************************************************************************/
388
389 static void update_wins_flag(struct name_record *namerec, int flags)
390 {
391         namerec->data.wins_flags=0x0;
392
393         /* if it's a group, it can be a normal or a special one */
394         if (namerec->data.nb_flags & NB_GROUP) {
395                 if (namerec->name.name_type==0x1C) {
396                         namerec->data.wins_flags|=WINS_SGROUP;
397                 } else {
398                         if (namerec->data.num_ips>1) {
399                                 namerec->data.wins_flags|=WINS_SGROUP;
400                         } else {
401                                 namerec->data.wins_flags|=WINS_NGROUP;
402                         }
403                 }
404         } else {
405                 /* can be unique or multi-homed */
406                 if (namerec->data.num_ips>1) {
407                         namerec->data.wins_flags|=WINS_MHOMED;
408                 } else {
409                         namerec->data.wins_flags|=WINS_UNIQUE;
410                 }
411         }
412
413         /* the node type are the same bits */
414         namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
415
416         /* the static bit is elsewhere */
417         if (namerec->data.death_time == PERMANENT_TTL) {
418                 namerec->data.wins_flags|=WINS_STATIC;
419         }
420
421         /* and add the given bits */
422         namerec->data.wins_flags|=flags;
423
424         DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: %d, flags: 0x%x, winsflags: 0x%x\n", 
425                  namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
426 }
427
428 /****************************************************************************
429  Return the general ID value and increase it if requested.
430 *****************************************************************************/
431
432 static void get_global_id_and_update(uint64_t *current_id, bool update)
433 {
434         /*
435          * it's kept as a static here, to prevent people from messing
436          * with the value directly
437          */
438
439         static uint64_t general_id = 1;
440
441         DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
442
443         *current_id = general_id;
444
445         if (update) {
446                 general_id++;
447         }
448 }
449
450 /****************************************************************************
451  Possibly call the WINS hook external program when a WINS change is made.
452  Also stores the changed record back in the wins_tdb.
453 *****************************************************************************/
454
455 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
456 {
457         char *command = NULL;
458         char *cmd = lp_wins_hook(talloc_tos());
459         char *p, *namestr;
460         int i;
461         TALLOC_CTX *ctx = talloc_tos();
462
463         wins_store_changed_namerec(namerec);
464
465         if (!cmd || !*cmd) {
466                 return;
467         }
468
469         for (p=namerec->name.name; *p; p++) {
470                 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
471                         DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
472                         return;
473                 }
474         }
475
476         /* Use the name without the nametype (and scope) appended */
477
478         namestr = nmb_namestr(&namerec->name);
479         if ((p = strchr(namestr, '<'))) {
480                 *p = 0;
481         }
482
483         command = talloc_asprintf(ctx,
484                                 "%s %s %s %02x %d",
485                                 cmd,
486                                 operation,
487                                 namestr,
488                                 namerec->name.name_type,
489                                 ttl);
490         if (!command) {
491                 return;
492         }
493
494         for (i=0;i<namerec->data.num_ips;i++) {
495                 command = talloc_asprintf_append(command,
496                                                 " %s",
497                                                 inet_ntoa(namerec->data.ip[i]));
498                 if (!command) {
499                         return;
500                 }
501         }
502
503         DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
504         smbrun(command, NULL, NULL);
505         TALLOC_FREE(command);
506 }
507
508 /****************************************************************************
509 Determine if this packet should be allocated to the WINS server.
510 *****************************************************************************/
511
512 bool packet_is_for_wins_server(struct packet_struct *packet)
513 {
514         struct nmb_packet *nmb = &packet->packet.nmb;
515
516         /* Only unicast packets go to a WINS server. */
517         if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
518                 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
519                 return False;
520         }
521
522         /* Check for node status requests. */
523         if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
524                 return False;
525         }
526
527         switch(nmb->header.opcode) { 
528                 /*
529                  * A WINS server issues WACKS, not receives them.
530                  */
531                 case NMB_WACK_OPCODE:
532                         DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
533                         return False;
534                 /*
535                  * A WINS server only processes registration and
536                  * release requests, not responses.
537                  */
538                 case NMB_NAME_REG_OPCODE:
539                 case NMB_NAME_MULTIHOMED_REG_OPCODE:
540                 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
541                 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
542                         if(nmb->header.response) {
543                                 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
544                                 return False;
545                         }
546                         break;
547
548                 case NMB_NAME_RELEASE_OPCODE:
549                         if(nmb->header.response) {
550                                 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
551                                 return False;
552                         }
553                         break;
554
555                 /*
556                  * Only process unicast name queries with rd = 1.
557                  */
558                 case NMB_NAME_QUERY_OPCODE:
559                         if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
560                                 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
561                                 return False;
562                         }
563                         break;
564         }
565
566         return True;
567 }
568
569 /****************************************************************************
570 Utility function to decide what ttl to give a register/refresh request.
571 *****************************************************************************/
572
573 static int get_ttl_from_packet(struct nmb_packet *nmb)
574 {
575         int ttl = nmb->additional->ttl;
576
577         if (ttl < lp_min_wins_ttl()) {
578                 ttl = lp_min_wins_ttl();
579         }
580
581         if (ttl > lp_max_wins_ttl()) {
582                 ttl = lp_max_wins_ttl();
583         }
584
585         return ttl;
586 }
587
588 /****************************************************************************
589 Load or create the WINS database.
590 *****************************************************************************/
591
592 bool initialise_wins(void)
593 {
594         time_t time_now = time(NULL);
595         FILE *fp;
596         char line[1024];
597         char *db_path;
598         char *list_path;
599
600         if(!lp_we_are_a_wins_server()) {
601                 return True;
602         }
603
604         db_path = state_path("wins.tdb");
605         if (db_path == NULL) {
606                 return false;
607         }
608
609         /* Open the wins.tdb. */
610         wins_tdb = tdb_open_log(db_path, 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
611                         O_CREAT|O_RDWR, 0600);
612         TALLOC_FREE(db_path);
613         if (!wins_tdb) {
614                 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
615                         strerror(errno) ));
616                 return False;
617         }
618
619         tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
620
621         add_samba_names_to_subnet(wins_server_subnet);
622
623         list_path = state_path(WINS_LIST);
624         if (list_path == NULL) {
625                 tdb_close(wins_tdb);
626                 return false;
627         }
628
629         fp = fopen(list_path, "r");
630         TALLOC_FREE(list_path);
631         if (fp == NULL) {
632                 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
633                         WINS_LIST, strerror(errno) ));
634                 return True;
635         }
636
637         while (!feof(fp)) {
638                 char *name_str = NULL;
639                 char *ip_str = NULL;
640                 char *ttl_str = NULL, *nb_flags_str = NULL;
641                 unsigned int num_ips;
642                 char *name = NULL;
643                 struct in_addr *ip_list = NULL;
644                 int type = 0;
645                 int nb_flags;
646                 int ttl;
647                 const char *ptr;
648                 char *p = NULL;
649                 bool got_token;
650                 bool was_ip;
651                 int i;
652                 unsigned int hash;
653                 int version;
654                 TALLOC_CTX *frame = NULL;
655
656                 /* Read a line from the wins.dat file. Strips whitespace
657                         from the beginning and end of the line.  */
658                 if (!fgets_slash(NULL, line, sizeof(line), fp)) {
659                         continue;
660                 }
661
662                 if (*line == '#') {
663                         continue;
664                 }
665
666                 if (strncmp(line,"VERSION ", 8) == 0) {
667                         if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
668                                                 version != WINS_VERSION) {
669                                 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
670                                 fclose(fp);
671                                 return True;
672                         }
673                         continue;
674                 }
675
676                 ptr = line;
677
678                 /*
679                  * Now we handle multiple IP addresses per name we need
680                  * to iterate over the line twice. The first time to
681                  * determine how many IP addresses there are, the second
682                  * time to actually parse them into the ip_list array.
683                  */
684
685                 frame = talloc_stackframe();
686                 if (!next_token_talloc(frame,&ptr,&name_str,NULL)) {
687                         DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
688                         TALLOC_FREE(frame);
689                         continue;
690                 }
691
692                 if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) {
693                         DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
694                         TALLOC_FREE(frame);
695                         continue;
696                 }
697
698                 /*
699                  * Determine the number of IP addresses per line.
700                  */
701                 num_ips = 0;
702                 do {
703                         got_token = next_token_talloc(frame,&ptr,&ip_str,NULL);
704                         was_ip = False;
705
706                         if(got_token && strchr(ip_str, '.')) {
707                                 num_ips++;
708                                 was_ip = True;
709                         }
710                 } while(got_token && was_ip);
711
712                 if(num_ips == 0) {
713                         DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
714                         TALLOC_FREE(frame);
715                         continue;
716                 }
717
718                 if(!got_token) {
719                         DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
720                         TALLOC_FREE(frame);
721                         continue;
722                 }
723
724                 /* Allocate the space for the ip_list. */
725                 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
726                         DEBUG(0,("initialise_wins: Malloc fail !\n"));
727                         fclose(fp);
728                         TALLOC_FREE(frame);
729                         return False;
730                 }
731
732                 /* Reset and re-parse the line. */
733                 ptr = line;
734                 next_token_talloc(frame,&ptr,&name_str,NULL);
735                 next_token_talloc(frame,&ptr,&ttl_str,NULL);
736                 for(i = 0; i < num_ips; i++) {
737                         next_token_talloc(frame,&ptr, &ip_str, NULL);
738                         ip_list[i] = interpret_addr2(ip_str);
739                 }
740                 next_token_talloc(frame,&ptr,&nb_flags_str,NULL);
741
742                 /*
743                  * Deal with SELF or REGISTER name encoding. Default is REGISTER
744                  * for compatibility with old nmbds.
745                  */
746
747                 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
748                         DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
749                         SAFE_FREE(ip_list);
750                         TALLOC_FREE(frame);
751                         continue;
752                 }
753
754                 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
755                         nb_flags_str[strlen(nb_flags_str)-1] = '\0';
756                 }
757
758                 /* Netbios name. # divides the name from the type (hex): netbios#xx */
759                 name = name_str;
760
761                 if((p = strchr(name,'#')) != NULL) {
762                         *p = 0;
763                         sscanf(p+1,"%x",&type);
764                 }
765
766                 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
767                 sscanf(nb_flags_str,"%x",&nb_flags);
768                 sscanf(ttl_str,"%d",&ttl);
769
770                 /* add all entries that have 60 seconds or more to live */
771                 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
772                         if(ttl != PERMANENT_TTL) {
773                                 ttl -= time_now;
774                         }
775
776                         DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
777                                 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
778
779                         (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, 
780                                         ttl, REGISTER_NAME, num_ips, ip_list );
781                 } else {
782                         DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
783                                 "%s#%02x ttl = %d first IP %s flags = %2x\n",
784                                 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
785                 }
786
787                 TALLOC_FREE(frame);
788                 SAFE_FREE(ip_list);
789         }
790
791         fclose(fp);
792         return True;
793 }
794
795 /****************************************************************************
796 Send a WINS WACK (Wait ACKnowledgement) response.
797 **************************************************************************/
798
799 static void send_wins_wack_response(int ttl, struct packet_struct *p)
800 {
801         struct nmb_packet *nmb = &p->packet.nmb;
802         unsigned char rdata[2];
803
804         rdata[0] = rdata[1] = 0;
805
806         /* Taken from nmblib.c - we need to send back almost
807                 identical bytes from the requesting packet header. */
808
809         rdata[0] = (nmb->header.opcode & 0xF) << 3;
810         if (nmb->header.nm_flags.authoritative && nmb->header.response) {
811                 rdata[0] |= 0x4;
812         }
813         if (nmb->header.nm_flags.trunc) {
814                 rdata[0] |= 0x2;
815         }
816         if (nmb->header.nm_flags.recursion_desired) {
817                 rdata[0] |= 0x1;
818         }
819         if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
820                 rdata[1] |= 0x80;
821         }
822         if (nmb->header.nm_flags.bcast) {
823                 rdata[1] |= 0x10;
824         }
825
826         reply_netbios_packet(p,                                /* Packet to reply to. */
827                                 0,                             /* Result code. */
828                                 NMB_WAIT_ACK,                  /* nmbd type code. */
829                                 NMB_WACK_OPCODE,               /* opcode. */
830                                 ttl,                           /* ttl. */
831                                 (char *)rdata,                 /* data to send. */
832                                 2);                            /* data length. */
833 }
834
835 /****************************************************************************
836 Send a WINS name registration response.
837 **************************************************************************/
838
839 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
840 {
841         struct nmb_packet *nmb = &p->packet.nmb;
842         char rdata[6];
843
844         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
845
846         reply_netbios_packet(p,                                /* Packet to reply to. */
847                                 rcode,                         /* Result code. */
848                                 WINS_REG,                      /* nmbd type code. */
849                                 NMB_NAME_REG_OPCODE,           /* opcode. */
850                                 ttl,                           /* ttl. */
851                                 rdata,                         /* data to send. */
852                                 6);                            /* data length. */
853 }
854
855 /***********************************************************************
856  Deal with a name refresh request to a WINS server.
857 ************************************************************************/
858
859 void wins_process_name_refresh_request( struct subnet_record *subrec,
860                                         struct packet_struct *p )
861 {
862         struct nmb_packet *nmb = &p->packet.nmb;
863         struct nmb_name *question = &nmb->question.question_name;
864         bool bcast = nmb->header.nm_flags.bcast;
865         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
866         bool group = (nb_flags & NB_GROUP) ? True : False;
867         struct name_record *namerec = NULL;
868         int ttl = get_ttl_from_packet(nmb);
869         struct in_addr from_ip;
870         struct in_addr our_fake_ip;
871
872         our_fake_ip = interpret_addr2("0.0.0.0");
873         putip( (char *)&from_ip, &nmb->additional->rdata[2] );
874
875         if(bcast) {
876                 /*
877                  * We should only get unicast name refresh packets here.
878                  * Anyone trying to refresh broadcast should not be going
879                  * to a WINS server.  Log an error here.
880                  */
881                 if( DEBUGLVL( 0 ) ) {
882                         dbgtext( "wins_process_name_refresh_request: " );
883                         dbgtext( "Broadcast name refresh request received " );
884                         dbgtext( "for name %s ", nmb_namestr(question) );
885                         dbgtext( "from IP %s ", inet_ntoa(from_ip) );
886                         dbgtext( "on subnet %s.  ", subrec->subnet_name );
887                         dbgtext( "Error - Broadcasts should not be sent " );
888                         dbgtext( "to a WINS server\n" );
889                 }
890                 return;
891         }
892
893         if( DEBUGLVL( 3 ) ) {
894                 dbgtext( "wins_process_name_refresh_request: " );
895                 dbgtext( "Name refresh for name %s IP %s\n",
896                          nmb_namestr(question), inet_ntoa(from_ip) );
897         }
898
899         /* 
900          * See if the name already exists.
901          * If not, handle it as a name registration and return.
902          */
903         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
904
905         /*
906          * If this is a refresh request and the name doesn't exist then
907          * treat it like a registration request. This allows us to recover 
908          * from errors (tridge)
909          */
910         if(namerec == NULL) {
911                 if( DEBUGLVL( 3 ) ) {
912                         dbgtext( "wins_process_name_refresh_request: " );
913                         dbgtext( "Name refresh for name %s ",
914                                  nmb_namestr( question ) );
915                         dbgtext( "and the name does not exist.  Treating " );
916                         dbgtext( "as registration.\n" );
917                 }
918                 wins_process_name_registration_request(subrec,p);
919                 return;
920         }
921
922         /*
923          * if the name is present but not active, simply remove it
924          * and treat the refresh request as a registration & return.
925          */
926         if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
927                 if( DEBUGLVL( 5 ) ) {
928                         dbgtext( "wins_process_name_refresh_request: " );
929                         dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
930                         dbgtext( "was not active - removing it.\n" );
931                 }
932                 remove_name_from_namelist( subrec, namerec );
933                 namerec = NULL;
934                 wins_process_name_registration_request( subrec, p );
935                 return;
936         }
937
938         /*
939          * Check that the group bits for the refreshing name and the
940          * name in our database match.  If not, refuse the refresh.
941          * [crh:  Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
942          */
943         if( (namerec != NULL) &&
944             ( (group && !NAME_GROUP(namerec))
945            || (!group && NAME_GROUP(namerec)) ) ) {
946                 if( DEBUGLVL( 3 ) ) {
947                         dbgtext( "wins_process_name_refresh_request: " );
948                         dbgtext( "Name %s ", nmb_namestr(question) );
949                         dbgtext( "group bit = %s does not match ",
950                                  group ? "True" : "False" );
951                         dbgtext( "group bit in WINS for this name.\n" );
952                 }
953                 send_wins_name_registration_response(RFS_ERR, 0, p);
954                 return;
955         }
956
957         /*
958          * For a unique name check that the person refreshing the name is
959          * one of the registered IP addresses. If not - fail the refresh.
960          * Do the same for group names with a type of 0x1c.
961          * Just return success for unique 0x1d refreshes. For normal group
962          * names update the ttl and return success.
963          */
964         if( (!group || (group && (question->name_type == 0x1c)))
965                         && find_ip_in_name_record(namerec, from_ip) ) {
966                 /*
967                  * Update the ttl.
968                  */
969                 update_name_ttl(namerec, ttl);
970
971                 /*
972                  * if the record is a replica:
973                  * we take ownership and update the version ID.
974                  */
975                 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
976                         update_wins_owner(namerec, our_fake_ip);
977                         get_global_id_and_update(&namerec->data.id, True);
978                 }
979
980                 send_wins_name_registration_response(0, ttl, p);
981                 wins_hook("refresh", namerec, ttl);
982                 return;
983         } else if((group && (question->name_type == 0x1c))) {
984                 /*
985                  * Added by crh for bug #1079.
986                  * Fix from Bert Driehuis
987                  */
988                 if( DEBUGLVL( 3 ) ) {
989                         dbgtext( "wins_process_name_refresh_request: " );
990                         dbgtext( "Name refresh for name %s, ",
991                                  nmb_namestr(question) );
992                         dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
993                         dbgtext( "is not yet associated with " );
994                         dbgtext( "that name. Treating as registration.\n" );
995                 }
996                 wins_process_name_registration_request(subrec,p);
997                 return;
998         } else if(group) {
999                 /* 
1000                  * Normal groups are all registered with an IP address of
1001                  * 255.255.255.255  so we can't search for the IP address.
1002                  */
1003                 update_name_ttl(namerec, ttl);
1004                 wins_hook("refresh", namerec, ttl);
1005                 send_wins_name_registration_response(0, ttl, p);
1006                 return;
1007         } else if(!group && (question->name_type == 0x1d)) {
1008                 /*
1009                  * Special name type - just pretend the refresh succeeded.
1010                  */
1011                 send_wins_name_registration_response(0, ttl, p);
1012                 return;
1013         } else {
1014                 /*
1015                  * Fail the refresh.
1016                  */
1017                 if( DEBUGLVL( 3 ) ) {
1018                         dbgtext( "wins_process_name_refresh_request: " );
1019                         dbgtext( "Name refresh for name %s with IP %s ",
1020                                  nmb_namestr(question), inet_ntoa(from_ip) );
1021                         dbgtext( "and is IP is not known to the name.\n" );
1022                 }
1023                 send_wins_name_registration_response(RFS_ERR, 0, p);
1024                 return;
1025         }
1026 }
1027
1028 /***********************************************************************
1029  Deal with a name registration request query success to a client that
1030  owned the name.
1031
1032  We have a locked pointer to the original packet stashed away in the
1033  userdata pointer. The success here is actually a failure as it means
1034  the client we queried wants to keep the name, so we must return
1035  a registration failure to the original requestor.
1036 ************************************************************************/
1037
1038 static void wins_register_query_success(struct subnet_record *subrec,
1039                                              struct userdata_struct *userdata,
1040                                              struct nmb_name *question_name,
1041                                              struct in_addr ip,
1042                                              struct res_rec *answers)
1043 {
1044         struct packet_struct *orig_reg_packet;
1045
1046         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1047
1048         DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1049 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
1050
1051         send_wins_name_registration_response(ACT_ERR, 0, orig_reg_packet);
1052
1053         orig_reg_packet->locked = False;
1054         free_packet(orig_reg_packet);
1055 }
1056
1057 /***********************************************************************
1058  Deal with a name registration request query failure to a client that
1059  owned the name.
1060
1061  We have a locked pointer to the original packet stashed away in the
1062  userdata pointer. The failure here is actually a success as it means
1063  the client we queried didn't want to keep the name, so we can remove
1064  the old name record and then successfully add the new name.
1065 ************************************************************************/
1066
1067 static void wins_register_query_fail(struct subnet_record *subrec,
1068                                           struct response_record *rrec,
1069                                           struct nmb_name *question_name,
1070                                           int rcode)
1071 {
1072         struct userdata_struct *userdata = rrec->userdata;
1073         struct packet_struct *orig_reg_packet;
1074         struct name_record *namerec = NULL;
1075
1076         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1077
1078         /*
1079          * We want to just add the name, as we now know the original owner
1080          * didn't want it. But we can't just do that as an arbitary
1081          * amount of time may have taken place between the name query
1082          * request and this timeout/error response. So we check that
1083          * the name still exists and is in the same state - if so
1084          * we remove it and call wins_process_name_registration_request()
1085          * as we know it will do the right thing now.
1086          */
1087
1088         namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1089
1090         if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1091                         ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1092                 remove_name_from_namelist( subrec, namerec);
1093                 namerec = NULL;
1094         }
1095
1096         if(namerec == NULL) {
1097                 wins_process_name_registration_request(subrec, orig_reg_packet);
1098         } else {
1099                 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1100                         "querying for name %s in order to replace it and this reply.\n",
1101                         nmb_namestr(question_name) ));
1102         }
1103
1104         orig_reg_packet->locked = False;
1105         free_packet(orig_reg_packet);
1106 }
1107
1108 /***********************************************************************
1109  Deal with a name registration request to a WINS server.
1110
1111  Use the following pseudocode :
1112
1113  registering_group
1114      |
1115      |
1116      +--------name exists
1117      |                  |
1118      |                  |
1119      |                  +--- existing name is group
1120      |                  |                      |
1121      |                  |                      |
1122      |                  |                      +--- add name (return).
1123      |                  |
1124      |                  |
1125      |                  +--- exiting name is unique
1126      |                                         |
1127      |                                         |
1128      |                                         +--- query existing owner (return).
1129      |
1130      |
1131      +--------name doesn't exist
1132                         |
1133                         |
1134                         +--- add name (return).
1135
1136  registering_unique
1137      |
1138      |
1139      +--------name exists
1140      |                  |
1141      |                  |
1142      |                  +--- existing name is group 
1143      |                  |                      |
1144      |                  |                      |
1145      |                  |                      +--- fail add (return).
1146      |                  | 
1147      |                  |
1148      |                  +--- exiting name is unique
1149      |                                         |
1150      |                                         |
1151      |                                         +--- query existing owner (return).
1152      |
1153      |
1154      +--------name doesn't exist
1155                         |
1156                         |
1157                         +--- add name (return).
1158
1159  As can be seen from the above, the two cases may be collapsed onto each
1160  other with the exception of the case where the name already exists and
1161  is a group name. This case we handle with an if statement.
1162  
1163 ************************************************************************/
1164
1165 void wins_process_name_registration_request(struct subnet_record *subrec,
1166                                             struct packet_struct *p)
1167 {
1168         unstring name;
1169         struct nmb_packet *nmb = &p->packet.nmb;
1170         struct nmb_name *question = &nmb->question.question_name;
1171         bool bcast = nmb->header.nm_flags.bcast;
1172         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
1173         int ttl = get_ttl_from_packet(nmb);
1174         struct name_record *namerec = NULL;
1175         struct in_addr from_ip;
1176         bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1177         struct in_addr our_fake_ip;
1178
1179         our_fake_ip = interpret_addr2("0.0.0.0");
1180         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1181
1182         if(bcast) {
1183                 /*
1184                  * We should only get unicast name registration packets here.
1185                  * Anyone trying to register broadcast should not be going to a WINS
1186                  * server. Log an error here.
1187                  */
1188
1189                 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1190 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1191                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1192                 return;
1193         }
1194
1195         DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1196 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1197
1198         /*
1199          * See if the name already exists.
1200          */
1201
1202         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1203
1204         /*
1205          * if the record exists but NOT in active state,
1206          * consider it dead.
1207          */
1208         if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1209                 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1210 not active - removing it.\n", nmb_namestr(question) ));
1211                 remove_name_from_namelist( subrec, namerec );
1212                 namerec = NULL;
1213         }
1214
1215         /*
1216          * Deal with the case where the name found was a dns entry.
1217          * Remove it as we now have a NetBIOS client registering the
1218          * name.
1219          */
1220
1221         if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1222                 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1223 a dns lookup - removing it.\n", nmb_namestr(question) ));
1224                 remove_name_from_namelist( subrec, namerec );
1225                 namerec = NULL;
1226         }
1227
1228         /*
1229          * Reject if the name exists and is not a REGISTER_NAME.
1230          * (ie. Don't allow any static names to be overwritten.
1231          */
1232
1233         if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1234                 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1235 to register name %s. Name already exists in WINS with source type %d.\n",
1236                         nmb_namestr(question), namerec->data.source ));
1237                 send_wins_name_registration_response(RFS_ERR, 0, p);
1238                 return;
1239         }
1240
1241         /*
1242          * Special policy decisions based on MS documentation.
1243          * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1244          * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1245          */
1246
1247         /*
1248          * A group name is always added as the local broadcast address, except
1249          * for group names ending in 0x1c.
1250          * Group names with type 0x1c are registered with individual IP addresses.
1251          */
1252
1253         if(registering_group_name && (question->name_type != 0x1c)) {
1254                 from_ip = interpret_addr2("255.255.255.255");
1255         }
1256
1257         /*
1258          * Ignore all attempts to register a unique 0x1d name, although return success.
1259          */
1260
1261         if(!registering_group_name && (question->name_type == 0x1d)) {
1262                 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1263 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1264                 send_wins_name_registration_response(0, ttl, p);
1265                 return;
1266         }
1267
1268         /*
1269          * Next two cases are the 'if statement' mentioned above.
1270          */
1271
1272         if((namerec != NULL) && NAME_GROUP(namerec)) {
1273                 if(registering_group_name) {
1274                         /*
1275                          * If we are adding a group name, the name exists and is also a group entry just add this
1276                          * IP address to it and update the ttl.
1277                          */
1278
1279                         DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1280                                 inet_ntoa(from_ip), nmb_namestr(question) ));
1281
1282                         /* 
1283                          * Check the ip address is not already in the group.
1284                          */
1285
1286                         if(!find_ip_in_name_record(namerec, from_ip)) {
1287                                 /*
1288                                  * Need to emulate the behaviour of Windows, as
1289                                  * described in:
1290                                  * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1291                                  * (is there an MS reference for this
1292                                  * somewhere?) because if the 1c list gets over
1293                                  * 86 entries, the reply packet is too big
1294                                  * (rdata>576 bytes) so no reply is sent.
1295                                  *
1296                                  * Keep only the "latest" 25 records, while
1297                                  * ensuring that the PDC (0x1b) is never removed
1298                                  * We do this by removing the first entry that
1299                                  * isn't the 1b entry for the same name,
1300                                  * on the grounds that insertion is at the end
1301                                  * of the list, so the oldest entries are at
1302                                  * the start.
1303                                  *
1304                                  */
1305                                 while(namerec->data.num_ips>=25) {
1306                                         struct name_record *name1brec = NULL;
1307
1308                                         /* We only do this for 1c types. */
1309                                         if (namerec->name.name_type != 0x1c) {
1310                                                 break;
1311                                         }
1312                                         DEBUG(3,("wins_process_name_registration_request: "
1313                                                 "More than 25 IPs already in "
1314                                                 "the list. Looking for a 1b "
1315                                                 "record\n"));
1316
1317                                         /* Ensure we have all the active 1b
1318                                          * names on the list. */
1319                                         wins_delete_all_1b_in_memory_records();
1320                                         fetch_all_active_wins_1b_names();
1321
1322                                         /* Per the above, find the 1b record,
1323                                            and then remove the first IP that isn't the same */
1324                                         for(name1brec = subrec->namelist;
1325                                                         name1brec;
1326                                                         name1brec = name1brec->next ) {
1327                                                 if( WINS_STATE_ACTIVE(name1brec) &&
1328                                                                 name1brec->name.name_type == 0x1b) {
1329                                                         DEBUG(3,("wins_process_name_registration_request: "
1330                                                                 "Found the #1b record "
1331                                                                 "with ip %s\n",
1332                                                                 inet_ntoa(name1brec->data.ip[0])));
1333                                                         break;
1334                                                 }
1335                                         }
1336                                         if(!name1brec) {
1337                                                 DEBUG(3,("wins_process_name_registration_request: "
1338                                                         "Didn't find a #1b name record. "
1339                                                         "Removing the first available "
1340                                                         "entry %s\n",
1341                                                         inet_ntoa(namerec->data.ip[0])));
1342                                                 remove_ip_from_name_record(namerec, namerec->data.ip[0]);
1343                                                 wins_hook("delete", namerec, 0);
1344                                         } else {
1345                                                 int i;
1346                                                 for(i=0; i<namerec->data.num_ips; i++) {
1347                                                         /* The name1brec should only have
1348                                                          * the single IP address in it,
1349                                                          * so we only check against the first one*/
1350                                                         if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) {
1351                                                                 /* The i'th entry isn't the 1b address; delete it  */
1352                                                                 DEBUG(3,("wins_process_name_registration_request: "
1353                                                                         "Entry at %d is not the #1b address. "
1354                                                                         "About to remove it\n",
1355                                                                         i));
1356                                                                 remove_ip_from_name_record(namerec, namerec->data.ip[i]);
1357                                                                 wins_hook("delete", namerec, 0);
1358                                                                 break;
1359                                                         }
1360                                                 }
1361                                         }
1362                                 }
1363                                 /* The list is guaranteed to be < 25 entries now
1364                                  * - safe to add a new one  */
1365                                 add_ip_to_name_record(namerec, from_ip);
1366                                 /* we need to update the record for replication */
1367                                 get_global_id_and_update(&namerec->data.id, True);
1368
1369                                 /*
1370                                  * if the record is a replica, we must change
1371                                  * the wins owner to us to make the replication updates
1372                                  * it on the other wins servers.
1373                                  * And when the partner will receive this record,
1374                                  * it will update its own record.
1375                                  */
1376
1377                                 update_wins_owner(namerec, our_fake_ip);
1378                         }
1379                         update_name_ttl(namerec, ttl);
1380                         wins_hook("refresh", namerec, ttl);
1381                         send_wins_name_registration_response(0, ttl, p);
1382                         return;
1383                 } else {
1384
1385                         /*
1386                          * If we are adding a unique name, the name exists in the WINS db 
1387                          * and is a group name then reject the registration.
1388                          *
1389                          * explanation: groups have a higher priority than unique names.
1390                          */
1391
1392                         DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1393 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1394                         send_wins_name_registration_response(RFS_ERR, 0, p);
1395                         return;
1396                 } 
1397         }
1398
1399         /*
1400          * From here on down we know that if the name exists in the WINS db it is
1401          * a unique name, not a group name.
1402          */
1403
1404         /* 
1405          * If the name exists and is one of our names then check the
1406          * registering IP address. If it's not one of ours then automatically
1407          * reject without doing the query - we know we will reject it.
1408          */
1409
1410         if ( namerec != NULL ) {
1411                 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1412                 if( is_myname(name) ) {
1413                         if(!ismyip_v4(from_ip)) {
1414                                 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1415 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1416                                 send_wins_name_registration_response(RFS_ERR, 0, p);
1417                                 return;
1418                         } else {
1419                                 /*
1420                                  * It's one of our names and one of our IP's - update the ttl.
1421                                  */
1422                                 update_name_ttl(namerec, ttl);
1423                                 wins_hook("refresh", namerec, ttl);
1424                                 send_wins_name_registration_response(0, ttl, p);
1425                                 return;
1426                         }
1427                 }
1428         } else {
1429                 name[0] = '\0';
1430         }
1431
1432         /*
1433          * If the name exists and it is a unique registration and the registering IP 
1434          * is the same as the (single) already registered IP then just update the ttl.
1435          *
1436          * But not if the record is an active replica. IF it's a replica, it means it can be
1437          * the same client which has moved and not yet expired. So we don't update
1438          * the ttl in this case and go beyond to do a WACK and query the old client
1439          */
1440
1441         if( !registering_group_name
1442                         && (namerec != NULL)
1443                         && (namerec->data.num_ips == 1)
1444                         && ip_equal_v4( namerec->data.ip[0], from_ip )
1445                         && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1446                 update_name_ttl( namerec, ttl );
1447                 wins_hook("refresh", namerec, ttl);
1448                 send_wins_name_registration_response( 0, ttl, p );
1449                 return;
1450         }
1451
1452         /*
1453          * Finally if the name exists do a query to the registering machine 
1454          * to see if they still claim to have the name.
1455          */
1456
1457         if( namerec != NULL ) {
1458                 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1459                 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1460
1461                 /*
1462                  * First send a WACK to the registering machine.
1463                  */
1464
1465                 send_wins_wack_response(60, p);
1466
1467                 /*
1468                  * When the reply comes back we need the original packet.
1469                  * Lock this so it won't be freed and then put it into
1470                  * the userdata structure.
1471                  */
1472
1473                 p->locked = True;
1474
1475                 userdata = (struct userdata_struct *)ud;
1476
1477                 userdata->copy_fn = NULL;
1478                 userdata->free_fn = NULL;
1479                 userdata->userdata_len = sizeof(struct packet_struct *);
1480                 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1481
1482                 /*
1483                  * Use the new call to send a query directly to an IP address.
1484                  * This sends the query directly to the IP address, and ensures
1485                  * the recursion desired flag is not set (you were right Luke :-).
1486                  * This function should *only* be called from the WINS server
1487                  * code. JRA.
1488                  */
1489
1490                 pull_ascii_nstring(name, sizeof(name), question->name);
1491                 query_name_from_wins_server( *namerec->data.ip,
1492                                 name,
1493                                 question->name_type, 
1494                                 wins_register_query_success,
1495                                 wins_register_query_fail,
1496                                 userdata );
1497                 return;
1498         }
1499
1500         /*
1501          * Name did not exist - add it.
1502          */
1503
1504         pull_ascii_nstring(name, sizeof(name), question->name);
1505         add_name_to_subnet( subrec, name, question->name_type,
1506                         nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1507
1508         if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1509                 get_global_id_and_update(&namerec->data.id, True);
1510                 update_wins_owner(namerec, our_fake_ip);
1511                 update_wins_flag(namerec, WINS_ACTIVE);
1512                 wins_hook("add", namerec, ttl);
1513         }
1514
1515         send_wins_name_registration_response(0, ttl, p);
1516 }
1517
1518 /***********************************************************************
1519  Deal with a mutihomed name query success to the machine that
1520  requested the multihomed name registration.
1521
1522  We have a locked pointer to the original packet stashed away in the
1523  userdata pointer.
1524 ************************************************************************/
1525
1526 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1527                                              struct userdata_struct *userdata,
1528                                              struct nmb_name *question_name,
1529                                              struct in_addr ip,
1530                                              struct res_rec *answers)
1531 {
1532         struct packet_struct *orig_reg_packet;
1533         struct nmb_packet *nmb;
1534         struct name_record *namerec = NULL;
1535         struct in_addr from_ip;
1536         int ttl;
1537         struct in_addr our_fake_ip;
1538
1539         our_fake_ip = interpret_addr2("0.0.0.0");
1540         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1541
1542         nmb = &orig_reg_packet->packet.nmb;
1543
1544         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1545         ttl = get_ttl_from_packet(nmb);
1546
1547         /*
1548          * We want to just add the new IP, as we now know the requesting
1549          * machine claims to own it. But we can't just do that as an arbitary
1550          * amount of time may have taken place between the name query
1551          * request and this response. So we check that
1552          * the name still exists and is in the same state - if so
1553          * we just add the extra IP and update the ttl.
1554          */
1555
1556         namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1557
1558         if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1559                 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1560 a subsequent IP address.\n", nmb_namestr(question_name) ));
1561                 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1562
1563                 orig_reg_packet->locked = False;
1564                 free_packet(orig_reg_packet);
1565
1566                 return;
1567         }
1568
1569         if(!find_ip_in_name_record(namerec, from_ip)) {
1570                 add_ip_to_name_record(namerec, from_ip);
1571         }
1572
1573         get_global_id_and_update(&namerec->data.id, True);
1574         update_wins_owner(namerec, our_fake_ip);
1575         update_wins_flag(namerec, WINS_ACTIVE);
1576         update_name_ttl(namerec, ttl);
1577         wins_hook("add", namerec, ttl);
1578         send_wins_name_registration_response(0, ttl, orig_reg_packet);
1579
1580         orig_reg_packet->locked = False;
1581         free_packet(orig_reg_packet);
1582 }
1583
1584 /***********************************************************************
1585  Deal with a name registration request query failure to a client that
1586  owned the name.
1587
1588  We have a locked pointer to the original packet stashed away in the
1589  userdata pointer.
1590 ************************************************************************/
1591
1592 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1593                                           struct response_record *rrec,
1594                                           struct nmb_name *question_name,
1595                                           int rcode)
1596 {
1597         struct userdata_struct *userdata = rrec->userdata;
1598         struct packet_struct *orig_reg_packet;
1599
1600         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1601
1602         DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1603 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1604         send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1605
1606         orig_reg_packet->locked = False;
1607         free_packet(orig_reg_packet);
1608         return;
1609 }
1610
1611 /***********************************************************************
1612  Deal with a multihomed name registration request to a WINS server.
1613  These cannot be group name registrations.
1614 ***********************************************************************/
1615
1616 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1617                                                         struct packet_struct *p)
1618 {
1619         struct nmb_packet *nmb = &p->packet.nmb;
1620         struct nmb_name *question = &nmb->question.question_name;
1621         bool bcast = nmb->header.nm_flags.bcast;
1622         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
1623         int ttl = get_ttl_from_packet(nmb);
1624         struct name_record *namerec = NULL;
1625         struct in_addr from_ip;
1626         bool group = (nb_flags & NB_GROUP) ? True : False;
1627         struct in_addr our_fake_ip;
1628         unstring qname;
1629
1630         our_fake_ip = interpret_addr2("0.0.0.0");
1631         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1632
1633         if(bcast) {
1634                 /*
1635                  * We should only get unicast name registration packets here.
1636                  * Anyone trying to register broadcast should not be going to a WINS
1637                  * server. Log an error here.
1638                  */
1639
1640                 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1641 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1642                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1643                 return;
1644         }
1645
1646         /*
1647          * Only unique names should be registered multihomed.
1648          */
1649
1650         if(group) {
1651                 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1652 received for name %s from IP %s on subnet %s. Error - group names should not be multihomed.\n",
1653                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1654                 return;
1655         }
1656
1657         DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1658 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1659
1660         /*
1661          * Deal with policy regarding 0x1d names.
1662          */
1663
1664         if(question->name_type == 0x1d) {
1665                 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1666 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1667                 send_wins_name_registration_response(0, ttl, p);  
1668                 return;
1669         }
1670
1671         /*
1672          * See if the name already exists.
1673          */
1674
1675         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1676
1677         /*
1678          * if the record exists but NOT in active state,
1679          * consider it dead.
1680          */
1681
1682         if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1683                 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1684                 remove_name_from_namelist(subrec, namerec);
1685                 namerec = NULL;
1686         }
1687
1688         /*
1689          * Deal with the case where the name found was a dns entry.
1690          * Remove it as we now have a NetBIOS client registering the
1691          * name.
1692          */
1693
1694         if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1695                 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1696 - removing it.\n", nmb_namestr(question) ));
1697                 remove_name_from_namelist( subrec, namerec);
1698                 namerec = NULL;
1699         }
1700
1701         /*
1702          * Reject if the name exists and is not a REGISTER_NAME.
1703          * (ie. Don't allow any static names to be overwritten.
1704          */
1705
1706         if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1707                 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1708 to register name %s. Name already exists in WINS with source type %d.\n",
1709                         nmb_namestr(question), namerec->data.source ));
1710                 send_wins_name_registration_response(RFS_ERR, 0, p);
1711                 return;
1712         }
1713
1714         /*
1715          * Reject if the name exists and is a GROUP name and is active.
1716          */
1717
1718         if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1719                 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1720 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1721                 send_wins_name_registration_response(RFS_ERR, 0, p);
1722                 return;
1723         } 
1724
1725         /*
1726          * From here on down we know that if the name exists in the WINS db it is
1727          * a unique name, not a group name.
1728          */
1729
1730         /*
1731          * If the name exists and is one of our names then check the
1732          * registering IP address. If it's not one of ours then automatically
1733          * reject without doing the query - we know we will reject it.
1734          */
1735
1736         if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1737                 if(!ismyip_v4(from_ip)) {
1738                         DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1739 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1740                         send_wins_name_registration_response(RFS_ERR, 0, p);
1741                         return;
1742                 } else {
1743                         /*
1744                          * It's one of our names and one of our IP's. Ensure the IP is in the record and
1745                          *  update the ttl. Update the version ID to force replication.
1746                          */
1747                         update_name_ttl(namerec, ttl);
1748
1749                         if(!find_ip_in_name_record(namerec, from_ip)) {
1750                                 get_global_id_and_update(&namerec->data.id, True);
1751                                 update_wins_owner(namerec, our_fake_ip);
1752                                 update_wins_flag(namerec, WINS_ACTIVE);
1753
1754                                 add_ip_to_name_record(namerec, from_ip);
1755                         }
1756
1757                         wins_hook("refresh", namerec, ttl);
1758                         send_wins_name_registration_response(0, ttl, p);
1759                         return;
1760                 }
1761         }
1762
1763         /*
1764          * If the name exists and is active, check if the IP address is already registered
1765          * to that name. If so then update the ttl and reply success.
1766          */
1767
1768         if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1769                 update_name_ttl(namerec, ttl);
1770
1771                 /*
1772                  * If it's a replica, we need to become the wins owner
1773                  * to force the replication
1774                  */
1775                 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1776                         get_global_id_and_update(&namerec->data.id, True);
1777                         update_wins_owner(namerec, our_fake_ip);
1778                         update_wins_flag(namerec, WINS_ACTIVE);
1779                 }
1780
1781                 wins_hook("refresh", namerec, ttl);
1782                 send_wins_name_registration_response(0, ttl, p);
1783                 return;
1784         }
1785
1786         /*
1787          * If the name exists do a query to the owner
1788          * to see if they still want the name.
1789          */
1790
1791         if(namerec != NULL) {
1792                 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1793                 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1794
1795                 /*
1796                  * First send a WACK to the registering machine.
1797                  */
1798
1799                 send_wins_wack_response(60, p);
1800
1801                 /*
1802                  * When the reply comes back we need the original packet.
1803                  * Lock this so it won't be freed and then put it into
1804                  * the userdata structure.
1805                  */
1806
1807                 p->locked = True;
1808
1809                 userdata = (struct userdata_struct *)ud;
1810
1811                 userdata->copy_fn = NULL;
1812                 userdata->free_fn = NULL;
1813                 userdata->userdata_len = sizeof(struct packet_struct *);
1814                 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1815
1816                 /* 
1817                  * Use the new call to send a query directly to an IP address.
1818                  * This sends the query directly to the IP address, and ensures
1819                  * the recursion desired flag is not set (you were right Luke :-).
1820                  * This function should *only* be called from the WINS server
1821                  * code. JRA.
1822                  *
1823                  * Note that this packet is sent to the current owner of the name,
1824                  * not the person who sent the packet 
1825                  */
1826
1827                 pull_ascii_nstring( qname, sizeof(qname), question->name);
1828                 query_name_from_wins_server( namerec->data.ip[0],
1829                                 qname,
1830                                 question->name_type, 
1831                                 wins_multihomed_register_query_success,
1832                                 wins_multihomed_register_query_fail,
1833                                 userdata );
1834
1835                 return;
1836         }
1837
1838         /*
1839          * Name did not exist - add it.
1840          */
1841
1842         pull_ascii_nstring( qname, sizeof(qname), question->name);
1843         add_name_to_subnet( subrec, qname, question->name_type,
1844                         nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1845
1846         if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1847                 get_global_id_and_update(&namerec->data.id, True);
1848                 update_wins_owner(namerec, our_fake_ip);
1849                 update_wins_flag(namerec, WINS_ACTIVE);
1850                 wins_hook("add", namerec, ttl);
1851         }
1852
1853         send_wins_name_registration_response(0, ttl, p);
1854 }
1855
1856 /***********************************************************************
1857  Fetch all *<1b> names from the WINS db and store on the namelist.
1858 ***********************************************************************/
1859
1860 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1861 {
1862         struct name_record *namerec = NULL;
1863
1864         if (kbuf.dsize != sizeof(unstring) + 1) {
1865                 return 0;
1866         }
1867
1868         /* Filter out all non-1b names. */
1869         if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1870                 return 0;
1871         }
1872
1873         namerec = wins_record_to_name_record(kbuf, dbuf);
1874         if (!namerec) {
1875                 return 0;
1876         }
1877
1878         DLIST_ADD(wins_server_subnet->namelist, namerec);
1879         return 0;
1880 }
1881
1882 void fetch_all_active_wins_1b_names(void)
1883 {
1884         tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1885 }
1886
1887 /***********************************************************************
1888  Deal with the special name query for *<1b>.
1889 ***********************************************************************/
1890
1891 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1892                                            struct packet_struct *p)
1893 {
1894         struct name_record *namerec = NULL;
1895         char *prdata;
1896         int num_ips;
1897
1898         /*
1899          * Go through all the ACTIVE names in the WINS db looking for those
1900          * ending in <1b>. Use this to calculate the number of IP
1901          * addresses we need to return.
1902          */
1903
1904         num_ips = 0;
1905
1906         /* First, clear the in memory list - we're going to re-populate
1907            it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1908
1909         wins_delete_all_tmp_in_memory_records();
1910
1911         fetch_all_active_wins_1b_names();
1912
1913         for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1914                 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1915                         num_ips += namerec->data.num_ips;
1916                 }
1917         }
1918
1919         if(num_ips == 0) {
1920                 /*
1921                  * There are no 0x1b names registered. Return name query fail.
1922                  */
1923                 send_wins_name_query_response(NAM_ERR, p, NULL);
1924                 return;
1925         }
1926
1927         if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1928                 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1929                 return;
1930         }
1931
1932         /*
1933          * Go through all the names again in the WINS db looking for those
1934          * ending in <1b>. Add their IP addresses into the list we will
1935          * return.
1936          */ 
1937
1938         num_ips = 0;
1939         for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1940                 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1941                         int i;
1942                         for(i = 0; i < namerec->data.num_ips; i++) {
1943                                 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1944                                 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1945                                 num_ips++;
1946                         }
1947                 }
1948         }
1949
1950         /*
1951          * Send back the reply containing the IP list.
1952          */
1953
1954         reply_netbios_packet(p,                                /* Packet to reply to. */
1955                                 0,                             /* Result code. */
1956                                 WINS_QUERY,                    /* nmbd type code. */
1957                                 NMB_NAME_QUERY_OPCODE,         /* opcode. */
1958                                 lp_min_wins_ttl(),             /* ttl. */
1959                                 prdata,                        /* data to send. */
1960                                 num_ips*6);                    /* data length. */
1961
1962         SAFE_FREE(prdata);
1963 }
1964
1965 /****************************************************************************
1966 Send a WINS name query response.
1967 **************************************************************************/
1968
1969 void send_wins_name_query_response(int rcode, struct packet_struct *p, 
1970                                           struct name_record *namerec)
1971 {
1972         char rdata[6];
1973         char *prdata = rdata;
1974         int reply_data_len = 0;
1975         int ttl = 0;
1976         int i;
1977
1978         memset(rdata,'\0',6);
1979
1980         if(rcode == 0) {
1981
1982                 int ip_count;
1983
1984                 ttl = (namerec->data.death_time != PERMANENT_TTL) ?  namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1985
1986                 /* The netbios reply packet data section is limited to 576 bytes.  In theory 
1987                  * this should give us space for 96 addresses, but in practice, 86 appears 
1988                  * to be the max (don't know why).  If we send any more than that, 
1989                  * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer 
1990                  * overflow.  Keep the count to 85 and it will be ok */
1991                 ip_count=namerec->data.num_ips;
1992                 if(ip_count>85) {
1993                         ip_count=85;    
1994                 }
1995
1996                 /* Copy all known ip addresses into the return data. */
1997                 /* Optimise for the common case of one IP address so we don't need a malloc. */
1998
1999                 if( ip_count == 1 ) {
2000                         prdata = rdata;
2001                 } else {
2002                         if((prdata = (char *)SMB_MALLOC( ip_count * 6 )) == NULL) {
2003                                 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
2004                                 return;
2005                         }
2006                 }
2007
2008                 for(i = 0; i < ip_count; i++) {
2009                         set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
2010                         putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
2011                 }
2012
2013                 sort_query_replies(prdata, i, p->ip);
2014                 reply_data_len = ip_count * 6;
2015         }
2016
2017         reply_netbios_packet(p,                                /* Packet to reply to. */
2018                                 rcode,                         /* Result code. */
2019                                 WINS_QUERY,                    /* nmbd type code. */
2020                                 NMB_NAME_QUERY_OPCODE,         /* opcode. */
2021                                 ttl,                           /* ttl. */
2022                                 prdata,                        /* data to send. */
2023                                 reply_data_len);               /* data length. */
2024
2025         if(prdata != rdata) {
2026                 SAFE_FREE(prdata);
2027         }
2028 }
2029
2030 /***********************************************************************
2031  Deal with a name query.
2032 ***********************************************************************/
2033
2034 void wins_process_name_query_request(struct subnet_record *subrec, 
2035                                      struct packet_struct *p)
2036 {
2037         struct nmb_packet *nmb = &p->packet.nmb;
2038         struct nmb_name *question = &nmb->question.question_name;
2039         struct name_record *namerec = NULL;
2040         unstring qname;
2041
2042         DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 
2043                 nmb_namestr(question), inet_ntoa(p->ip) ));
2044
2045         /*
2046          * Special name code. If the queried name is *<1b> then search
2047          * the entire WINS database and return a list of all the IP addresses
2048          * registered to any <1b> name. This is to allow domain master browsers
2049          * to discover other domains that may not have a presence on their subnet.
2050          */
2051
2052         pull_ascii_nstring(qname, sizeof(qname), question->name);
2053         if(strequal( qname, "*") && (question->name_type == 0x1b)) {
2054                 process_wins_dmb_query_request( subrec, p);
2055                 return;
2056         }
2057
2058         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2059
2060         if(namerec != NULL) {
2061                 /*
2062                  * If the name is not anymore in active state then reply not found.
2063                  * it's fair even if we keep it in the cache for days.
2064                  */
2065                 if (!WINS_STATE_ACTIVE(namerec)) {
2066                         DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2067                                 nmb_namestr(question) ));
2068                         send_wins_name_query_response(NAM_ERR, p, namerec);
2069                         return;
2070                 }
2071
2072                 /* 
2073                  * If it's a DNSFAIL_NAME then reply name not found.
2074                  */
2075
2076                 if( namerec->data.source == DNSFAIL_NAME ) {
2077                         DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2078                                 nmb_namestr(question) ));
2079                         send_wins_name_query_response(NAM_ERR, p, namerec);
2080                         return;
2081                 }
2082
2083                 /*
2084                  * If the name has expired then reply name not found.
2085                  */
2086
2087                 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
2088                         DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2089                                         nmb_namestr(question) ));
2090                         send_wins_name_query_response(NAM_ERR, p, namerec);
2091                         return;
2092                 }
2093
2094                 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2095                                 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
2096
2097                 send_wins_name_query_response(0, p, namerec);
2098                 return;
2099         }
2100
2101         /* 
2102          * Name not found in WINS - try a dns query if it's a 0x20 name.
2103          */
2104
2105         if(lp_wins_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
2106                 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2107                                 nmb_namestr(question) ));
2108
2109                 queue_dns_query(p, question);
2110                 return;
2111         }
2112
2113         /*
2114          * Name not found - return error.
2115          */
2116
2117         send_wins_name_query_response(NAM_ERR, p, NULL);
2118 }
2119
2120 /****************************************************************************
2121 Send a WINS name release response.
2122 **************************************************************************/
2123
2124 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
2125 {
2126         struct nmb_packet *nmb = &p->packet.nmb;
2127         char rdata[6];
2128
2129         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
2130
2131         reply_netbios_packet(p,                               /* Packet to reply to. */
2132                                 rcode,                        /* Result code. */
2133                                 NMB_REL,                      /* nmbd type code. */
2134                                 NMB_NAME_RELEASE_OPCODE,      /* opcode. */
2135                                 0,                            /* ttl. */
2136                                 rdata,                        /* data to send. */
2137                                 6);                           /* data length. */
2138 }
2139
2140 /***********************************************************************
2141  Deal with a name release.
2142 ***********************************************************************/
2143
2144 void wins_process_name_release_request(struct subnet_record *subrec,
2145                                        struct packet_struct *p)
2146 {
2147         struct nmb_packet *nmb = &p->packet.nmb;
2148         struct nmb_name *question = &nmb->question.question_name;
2149         bool bcast = nmb->header.nm_flags.bcast;
2150         uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
2151         struct name_record *namerec = NULL;
2152         struct in_addr from_ip;
2153         bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;
2154
2155         putip((char *)&from_ip,&nmb->additional->rdata[2]);
2156
2157         if(bcast) {
2158                 /*
2159                  * We should only get unicast name registration packets here.
2160                  * Anyone trying to register broadcast should not be going to a WINS
2161                  * server. Log an error here.
2162                  */
2163
2164                 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2165 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2166                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2167                 return;
2168         }
2169
2170         DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2171 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2172
2173         /*
2174          * Deal with policy regarding 0x1d names.
2175          */
2176
2177         if(!releasing_group_name && (question->name_type == 0x1d)) {
2178                 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2179 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2180                 send_wins_name_release_response(0, p);
2181                 return;
2182         }
2183
2184         /*
2185          * See if the name already exists.
2186          */
2187
2188         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2189
2190         if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2191                 send_wins_name_release_response(NAM_ERR, p);
2192                 return;
2193         }
2194
2195         /* 
2196          * Check that the sending machine has permission to release this name.
2197          * If it's a group name not ending in 0x1c then just say yes and let
2198          * the group time out.
2199          */
2200
2201         if(releasing_group_name && (question->name_type != 0x1c)) {
2202                 send_wins_name_release_response(0, p);
2203                 return;
2204         }
2205
2206         /* 
2207          * Check that the releasing node is on the list of IP addresses
2208          * for this name. Disallow the release if not.
2209          */
2210
2211         if(!find_ip_in_name_record(namerec, from_ip)) {
2212                 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2213 release name %s as IP %s is not one of the known IP's for this name.\n",
2214                         nmb_namestr(question), inet_ntoa(from_ip) ));
2215                 send_wins_name_release_response(NAM_ERR, p);
2216                 return;
2217         }
2218
2219         /*
2220          * Check if the record is active. IF it's already released
2221          * or tombstoned, refuse the release.
2222          */
2223
2224         if (!WINS_STATE_ACTIVE(namerec)) {
2225                 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2226 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2227                 send_wins_name_release_response(NAM_ERR, p);
2228                 return;
2229         }    
2230
2231         /*
2232          * Check if the record is a 0x1c group
2233          * and has more then one ip
2234          * remove only this address.
2235          */
2236
2237         if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2238                 remove_ip_from_name_record(namerec, from_ip);
2239                 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2240                                 inet_ntoa(from_ip),nmb_namestr(question)));
2241                 wins_hook("delete", namerec, 0);
2242                 send_wins_name_release_response(0, p);
2243                 return;
2244         }
2245
2246         /* 
2247          * Send a release response.
2248          * Flag the name as released and update the ttl
2249          */
2250
2251         namerec->data.wins_flags |= WINS_RELEASED;
2252         update_name_ttl(namerec, EXTINCTION_INTERVAL);
2253
2254         wins_hook("delete", namerec, 0);
2255         send_wins_name_release_response(0, p);
2256 }
2257
2258 /*******************************************************************
2259  WINS time dependent processing.
2260 ******************************************************************/
2261
2262 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2263 {
2264         time_t t = *(time_t *)state;
2265         bool store_record = False;
2266         struct name_record *namerec = NULL;
2267         struct in_addr our_fake_ip;
2268
2269         our_fake_ip = interpret_addr2("0.0.0.0");
2270         if (kbuf.dsize != sizeof(unstring) + 1) {
2271                 return 0;
2272         }
2273
2274         namerec = wins_record_to_name_record(kbuf, dbuf);
2275         if (!namerec) {
2276                 return 0;
2277         }
2278
2279         if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2280                 if( namerec->data.source == SELF_NAME ) {
2281                         DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n", 
2282                                    wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2283                         namerec->data.death_time += 300;
2284                         store_record = True;
2285                         goto done;
2286                 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2287                         DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2288                                         nmb_namestr(&namerec->name)));
2289                         remove_name_from_wins_namelist(namerec );
2290                         goto done;
2291                 }
2292
2293                 /* handle records, samba is the wins owner */
2294                 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2295                         switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2296                                 case WINS_ACTIVE:
2297                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2298                                         namerec->data.wins_flags|=WINS_RELEASED;
2299                                         namerec->data.death_time = t + EXTINCTION_INTERVAL;
2300                                         DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2301                                                 nmb_namestr(&namerec->name)));
2302                                         store_record = True;
2303                                         goto done;
2304                                 case WINS_RELEASED:
2305                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2306                                         namerec->data.wins_flags|=WINS_TOMBSTONED;
2307                                         namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2308                                         get_global_id_and_update(&namerec->data.id, True);
2309                                         DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2310                                                 nmb_namestr(&namerec->name)));
2311                                         store_record = True;
2312                                         goto done;
2313                                 case WINS_TOMBSTONED:
2314                                         DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2315                                                 nmb_namestr(&namerec->name)));
2316                                         remove_name_from_wins_namelist(namerec );
2317                                         goto done;
2318                         }
2319                 } else {
2320                         switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2321                                 case WINS_ACTIVE:
2322                                         /* that's not as MS says it should be */
2323                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2324                                         namerec->data.wins_flags|=WINS_TOMBSTONED;
2325                                         namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2326                                         DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2327                                                 nmb_namestr(&namerec->name)));
2328                                         store_record = True;
2329                                         goto done;
2330                                 case WINS_TOMBSTONED:
2331                                         DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2332                                                 nmb_namestr(&namerec->name)));
2333                                         remove_name_from_wins_namelist(namerec );
2334                                         goto done;
2335                                 case WINS_RELEASED:
2336                                         DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2337 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2338                                         goto done;
2339                         }
2340                 }
2341         }
2342
2343   done:
2344
2345         if (store_record) {
2346                 wins_store_changed_namerec(namerec);
2347         }
2348
2349         SAFE_FREE(namerec->data.ip);
2350         SAFE_FREE(namerec);
2351
2352         return 0;
2353 }
2354
2355 /*******************************************************************
2356  Time dependent wins processing.
2357 ******************************************************************/
2358
2359 void initiate_wins_processing(time_t t)
2360 {
2361         static time_t lasttime = 0;
2362
2363         if (!lasttime) {
2364                 lasttime = t;
2365         }
2366         if (t - lasttime < 20) {
2367                 return;
2368         }
2369
2370         if(!lp_we_are_a_wins_server()) {
2371                 lasttime = t;
2372                 return;
2373         }
2374
2375         tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2376
2377         wins_delete_all_tmp_in_memory_records();
2378
2379         wins_write_database(t, True);
2380
2381         lasttime = t;
2382 }
2383
2384 /*******************************************************************
2385  Write out one record.
2386 ******************************************************************/
2387
2388 void wins_write_name_record(struct name_record *namerec, FILE *fp)
2389 {
2390         int i;
2391         struct tm *tm;
2392
2393         DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2394
2395         if( namerec->data.death_time != PERMANENT_TTL ) {
2396                 char *ts, *nl;
2397
2398                 tm = localtime(&namerec->data.death_time);
2399                 if (!tm) {
2400                         return;
2401                 }
2402                 ts = asctime(tm);
2403                 if (!ts) {
2404                         return;
2405                 }
2406                 nl = strrchr( ts, '\n' );
2407                 if( NULL != nl ) {
2408                         *nl = '\0';
2409                 }
2410                 DEBUGADD(4,("TTL = %s  ", ts ));
2411         } else {
2412                 DEBUGADD(4,("TTL = PERMANENT                 "));
2413         }
2414
2415         for (i = 0; i < namerec->data.num_ips; i++) {
2416                 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2417         }
2418         DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2419
2420         if( namerec->data.source == REGISTER_NAME ) {
2421                 unstring name;
2422                 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2423                 fprintf(fp, "\"%s#%02x\" %d ", name,
2424                         namerec->name.name_type, /* Ignore scope. */
2425                         (int)namerec->data.death_time);
2426
2427                 for (i = 0; i < namerec->data.num_ips; i++)
2428                         fprintf(fp, "%s ", inet_ntoa(namerec->data.ip[i]));
2429                 fprintf(fp, "%2xR\n", namerec->data.nb_flags);
2430         }
2431 }
2432
2433 /*******************************************************************
2434  Write out the current WINS database.
2435 ******************************************************************/
2436
2437 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2438 {
2439         struct name_record *namerec = NULL;
2440         FILE *fp = (FILE *)state;
2441
2442         if (kbuf.dsize != sizeof(unstring) + 1) {
2443                 return 0;
2444         }
2445
2446         namerec = wins_record_to_name_record(kbuf, dbuf);
2447         if (!namerec) {
2448                 return 0;
2449         }
2450
2451         wins_write_name_record(namerec, fp);
2452
2453         SAFE_FREE(namerec->data.ip);
2454         SAFE_FREE(namerec);
2455         return 0;
2456 }
2457
2458
2459 void wins_write_database(time_t t, bool background)
2460 {
2461         static time_t last_write_time = 0;
2462         char *fname = NULL;
2463         char *fnamenew = NULL;
2464
2465         int fd;
2466         FILE *fp;
2467
2468         if (background) {
2469                 if (!last_write_time) {
2470                         last_write_time = t;
2471                 }
2472                 if (t - last_write_time < 120) {
2473                         return;
2474                 }
2475
2476         }
2477
2478         if(!lp_we_are_a_wins_server()) {
2479                 return;
2480         }
2481
2482         /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2483         if (background) {
2484                 CatchChild();
2485                 if (fork()) {
2486                         return;
2487                 }
2488                 if (tdb_reopen(wins_tdb)) {
2489                         DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2490                                 strerror(errno)));
2491                         _exit(0);
2492                         return;
2493                 }
2494         }
2495
2496         if (!(fname = state_path(WINS_LIST))) {
2497                 goto err_exit;
2498         }
2499         /* This is safe as the 0 length means "don't expand". */
2500         all_string_sub(fname,"//", "/", 0);
2501
2502         if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)getpid()) < 0) {
2503                 goto err_exit;
2504         }
2505
2506         fd = open(fnamenew, O_WRONLY|O_CREAT, 0644);
2507         if (fd == -1) {
2508                 DBG_ERR("Can't open %s: %s\n", fnamenew, strerror(errno));
2509                 goto err_exit;
2510         }
2511
2512         fp = fdopen(fd, "w");
2513         if (fp == NULL) {
2514                 DBG_ERR("fdopen failed: %s\n", strerror(errno));
2515                 close(fd);
2516                 goto err_exit;
2517         }
2518         fd = -1;
2519
2520         DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2521
2522         fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2523
2524         tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2525
2526         fclose(fp);
2527         chmod(fnamenew,0644);
2528         unlink(fname);
2529         rename(fnamenew,fname);
2530
2531   err_exit:
2532
2533         SAFE_FREE(fnamenew);
2534         TALLOC_FREE(fname);
2535
2536         if (background) {
2537                 _exit(0);
2538         }
2539 }
2540
2541 #if 0
2542         Until winsrepl is done.
2543 /****************************************************************************
2544  Process a internal Samba message receiving a wins record.
2545 ***************************************************************************/
2546
2547 void nmbd_wins_new_entry(struct messaging_context *msg,
2548                                        void *private_data,
2549                                        uint32_t msg_type,
2550                                        struct server_id server_id,
2551                                        DATA_BLOB *data)
2552 {
2553         WINS_RECORD *record;
2554         struct name_record *namerec = NULL;
2555         struct name_record *new_namerec = NULL;
2556         struct nmb_name question;
2557         bool overwrite=False;
2558         struct in_addr our_fake_ip;
2559         int i;
2560
2561         our_fake_ip = interpret_addr2("0.0.0.0");
2562         if (buf==NULL) {
2563                 return;
2564         }
2565
2566         /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2567         record=(WINS_RECORD *)buf;
2568
2569         make_nmb_name(&question, record->name, record->type);
2570
2571         namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2572
2573         /* record doesn't exist, add it */
2574         if (namerec == NULL) {
2575                 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 
2576                           record->name, record->type, inet_ntoa(record->wins_ip)));
2577
2578                 new_namerec=add_name_to_subnet( wins_server_subnet,
2579                                                 record->name,
2580                                                 record->type,
2581                                                 record->nb_flags, 
2582                                                 EXTINCTION_INTERVAL,
2583                                                 REGISTER_NAME,
2584                                                 record->num_ips,
2585                                                 record->ip);
2586
2587                 if (new_namerec!=NULL) {
2588                                 update_wins_owner(new_namerec, record->wins_ip);
2589                                 update_wins_flag(new_namerec, record->wins_flags);
2590                                 new_namerec->data.id=record->id;
2591
2592                                 wins_server_subnet->namelist_changed = True;
2593                         }
2594         }
2595
2596         /* check if we have a conflict */
2597         if (namerec != NULL) {
2598                 /* both records are UNIQUE */
2599                 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2600
2601                         /* the database record is a replica */
2602                         if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2603                                 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2604                                         if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2605                                                 overwrite=True;
2606                                 } else
2607                                         overwrite=True;
2608                         } else {
2609                         /* we are the wins owner of the database record */
2610                                 /* the 2 records have the same IP address */
2611                                 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2612                                         if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2613                                                 get_global_id_and_update(&namerec->data.id, True);
2614                                         else
2615                                                 overwrite=True;
2616
2617                                 } else {
2618                                 /* the 2 records have different IP address */
2619                                         if (namerec->data.wins_flags&WINS_ACTIVE) {
2620                                                 if (record->wins_flags&WINS_TOMBSTONED)
2621                                                         get_global_id_and_update(&namerec->data.id, True);
2622                                                 if (record->wins_flags&WINS_ACTIVE)
2623                                                         /* send conflict challenge to the replica node */
2624                                                         ;
2625                                         } else
2626                                                 overwrite=True;
2627                                 }
2628
2629                         }
2630                 }
2631
2632                 /* the replica is a standard group */
2633                 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2634                         /* if the database record is unique and active force a name release */
2635                         if (namerec->data.wins_flags&WINS_UNIQUE)
2636                                 /* send a release name to the unique node */
2637                                 ;
2638                         overwrite=True;
2639
2640                 }
2641
2642                 /* the replica is a special group */
2643                 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2644                         if (namerec->data.wins_flags&WINS_ACTIVE) {
2645                                 for (i=0; i<record->num_ips; i++)
2646                                         if(!find_ip_in_name_record(namerec, record->ip[i]))
2647                                                 add_ip_to_name_record(namerec, record->ip[i]);
2648                         } else {
2649                                 overwrite=True;
2650                         }
2651                 }
2652
2653                 /* the replica is a multihomed host */
2654
2655                 /* I'm giving up on multi homed. Too much complex to understand */
2656
2657                 if (record->wins_flags&WINS_MHOMED) {
2658                         if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2659                                 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2660                                         overwrite=True;
2661                         }
2662                         else {
2663                                 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2664                                         overwrite=True;
2665
2666                                 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2667                                         if (namerec->data.wins_flags&WINS_UNIQUE)
2668                                                 get_global_id_and_update(&namerec->data.id, True);
2669
2670                         }
2671
2672                         if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2673                                 if (namerec->data.wins_flags&WINS_UNIQUE ||
2674                                     namerec->data.wins_flags&WINS_MHOMED)
2675                                         if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2676                                                 overwrite=True;
2677
2678                 }
2679
2680                 if (overwrite == False)
2681                         DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 
2682                                   record->name, record->type, inet_ntoa(record->wins_ip)));
2683                 else {
2684                         DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 
2685                                   record->name, record->type, inet_ntoa(record->wins_ip)));
2686
2687                         /* remove the old record and add a new one */
2688                         remove_name_from_namelist( wins_server_subnet, namerec );
2689                         new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 
2690                                                 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2691                         if (new_namerec!=NULL) {
2692                                 update_wins_owner(new_namerec, record->wins_ip);
2693                                 update_wins_flag(new_namerec, record->wins_flags);
2694                                 new_namerec->data.id=record->id;
2695
2696                                 wins_server_subnet->namelist_changed = True;
2697                         }
2698
2699                         wins_server_subnet->namelist_changed = True;
2700                 }
2701
2702         }
2703 }
2704 #endif