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