Remove more static data from lib/util_sock.c and
[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(state_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                         (void)interpret_addr2(&ip_list[i], 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;
814
815         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
816         putip( (char *)&from_ip, &nmb->additional->rdata[2] );
817
818         if(bcast) {
819                 /*
820                  * We should only get unicast name refresh packets here.
821                  * Anyone trying to refresh broadcast should not be going
822                  * to a WINS server.  Log an error here.
823                  */
824                 if( DEBUGLVL( 0 ) ) {
825                         dbgtext( "wins_process_name_refresh_request: " );
826                         dbgtext( "Broadcast name refresh request received " );
827                         dbgtext( "for name %s ", nmb_namestr(question) );
828                         dbgtext( "from IP %s ", inet_ntoa(from_ip) );
829                         dbgtext( "on subnet %s.  ", subrec->subnet_name );
830                         dbgtext( "Error - Broadcasts should not be sent " );
831                         dbgtext( "to a WINS server\n" );
832                 }
833                 return;
834         }
835
836         if( DEBUGLVL( 3 ) ) {
837                 dbgtext( "wins_process_name_refresh_request: " );
838                 dbgtext( "Name refresh for name %s IP %s\n",
839                          nmb_namestr(question), inet_ntoa(from_ip) );
840         }
841
842         /* 
843          * See if the name already exists.
844          * If not, handle it as a name registration and return.
845          */
846         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
847
848         /*
849          * If this is a refresh request and the name doesn't exist then
850          * treat it like a registration request. This allows us to recover 
851          * from errors (tridge)
852          */
853         if(namerec == NULL) {
854                 if( DEBUGLVL( 3 ) ) {
855                         dbgtext( "wins_process_name_refresh_request: " );
856                         dbgtext( "Name refresh for name %s ",
857                                  nmb_namestr( question ) );
858                         dbgtext( "and the name does not exist.  Treating " );
859                         dbgtext( "as registration.\n" );
860                 }
861                 wins_process_name_registration_request(subrec,p);
862                 return;
863         }
864
865         /*
866          * if the name is present but not active, simply remove it
867          * and treat the refresh request as a registration & return.
868          */
869         if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
870                 if( DEBUGLVL( 5 ) ) {
871                         dbgtext( "wins_process_name_refresh_request: " );
872                         dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
873                         dbgtext( "was not active - removing it.\n" );
874                 }
875                 remove_name_from_namelist( subrec, namerec );
876                 namerec = NULL;
877                 wins_process_name_registration_request( subrec, p );
878                 return;
879         }
880
881         /*
882          * Check that the group bits for the refreshing name and the
883          * name in our database match.  If not, refuse the refresh.
884          * [crh:  Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
885          */
886         if( (namerec != NULL) &&
887             ( (group && !NAME_GROUP(namerec))
888            || (!group && NAME_GROUP(namerec)) ) ) {
889                 if( DEBUGLVL( 3 ) ) {
890                         dbgtext( "wins_process_name_refresh_request: " );
891                         dbgtext( "Name %s ", nmb_namestr(question) );
892                         dbgtext( "group bit = %s does not match ",
893                                  group ? "True" : "False" );
894                         dbgtext( "group bit in WINS for this name.\n" );
895                 }
896                 send_wins_name_registration_response(RFS_ERR, 0, p);
897                 return;
898         }
899
900         /*
901          * For a unique name check that the person refreshing the name is
902          * one of the registered IP addresses. If not - fail the refresh.
903          * Do the same for group names with a type of 0x1c.
904          * Just return success for unique 0x1d refreshes. For normal group
905          * names update the ttl and return success.
906          */
907         if( (!group || (group && (question->name_type == 0x1c)))
908                         && find_ip_in_name_record(namerec, from_ip) ) {
909                 /*
910                  * Update the ttl.
911                  */
912                 update_name_ttl(namerec, ttl);
913
914                 /*
915                  * if the record is a replica:
916                  * we take ownership and update the version ID.
917                  */
918                 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
919                         update_wins_owner(namerec, our_fake_ip);
920                         get_global_id_and_update(&namerec->data.id, True);
921                 }
922
923                 send_wins_name_registration_response(0, ttl, p);
924                 wins_hook("refresh", namerec, ttl);
925                 return;
926         } else if((group && (question->name_type == 0x1c))) {
927                 /*
928                  * Added by crh for bug #1079.
929                  * Fix from Bert Driehuis
930                  */
931                 if( DEBUGLVL( 3 ) ) {
932                         dbgtext( "wins_process_name_refresh_request: " );
933                         dbgtext( "Name refresh for name %s, ",
934                                  nmb_namestr(question) );
935                         dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
936                         dbgtext( "is not yet associated with " );
937                         dbgtext( "that name. Treating as registration.\n" );
938                 }
939                 wins_process_name_registration_request(subrec,p);
940                 return;
941         } else if(group) {
942                 /* 
943                  * Normal groups are all registered with an IP address of
944                  * 255.255.255.255  so we can't search for the IP address.
945                  */
946                 update_name_ttl(namerec, ttl);
947                 wins_hook("refresh", namerec, ttl);
948                 send_wins_name_registration_response(0, ttl, p);
949                 return;
950         } else if(!group && (question->name_type == 0x1d)) {
951                 /*
952                  * Special name type - just pretend the refresh succeeded.
953                  */
954                 send_wins_name_registration_response(0, ttl, p);
955                 return;
956         } else {
957                 /*
958                  * Fail the refresh.
959                  */
960                 if( DEBUGLVL( 3 ) ) {
961                         dbgtext( "wins_process_name_refresh_request: " );
962                         dbgtext( "Name refresh for name %s with IP %s ",
963                                  nmb_namestr(question), inet_ntoa(from_ip) );
964                         dbgtext( "and is IP is not known to the name.\n" );
965                 }
966                 send_wins_name_registration_response(RFS_ERR, 0, p);
967                 return;
968         }
969 }
970
971 /***********************************************************************
972  Deal with a name registration request query success to a client that
973  owned the name.
974
975  We have a locked pointer to the original packet stashed away in the
976  userdata pointer. The success here is actually a failure as it means
977  the client we queried wants to keep the name, so we must return
978  a registration failure to the original requestor.
979 ************************************************************************/
980
981 static void wins_register_query_success(struct subnet_record *subrec,
982                                              struct userdata_struct *userdata,
983                                              struct nmb_name *question_name,
984                                              struct in_addr ip,
985                                              struct res_rec *answers)
986 {
987         struct packet_struct *orig_reg_packet;
988
989         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
990
991         DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
992 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
993
994         send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
995
996         orig_reg_packet->locked = False;
997         free_packet(orig_reg_packet);
998 }
999
1000 /***********************************************************************
1001  Deal with a name registration request query failure to a client that
1002  owned the name.
1003
1004  We have a locked pointer to the original packet stashed away in the
1005  userdata pointer. The failure here is actually a success as it means
1006  the client we queried didn't want to keep the name, so we can remove
1007  the old name record and then successfully add the new name.
1008 ************************************************************************/
1009
1010 static void wins_register_query_fail(struct subnet_record *subrec,
1011                                           struct response_record *rrec,
1012                                           struct nmb_name *question_name,
1013                                           int rcode)
1014 {
1015         struct userdata_struct *userdata = rrec->userdata;
1016         struct packet_struct *orig_reg_packet;
1017         struct name_record *namerec = NULL;
1018
1019         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1020
1021         /*
1022          * We want to just add the name, as we now know the original owner
1023          * didn't want it. But we can't just do that as an arbitary
1024          * amount of time may have taken place between the name query
1025          * request and this timeout/error response. So we check that
1026          * the name still exists and is in the same state - if so
1027          * we remove it and call wins_process_name_registration_request()
1028          * as we know it will do the right thing now.
1029          */
1030
1031         namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1032
1033         if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1034                         ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1035                 remove_name_from_namelist( subrec, namerec);
1036                 namerec = NULL;
1037         }
1038
1039         if(namerec == NULL) {
1040                 wins_process_name_registration_request(subrec, orig_reg_packet);
1041         } else {
1042                 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1043                         "querying for name %s in order to replace it and this reply.\n",
1044                         nmb_namestr(question_name) ));
1045         }
1046
1047         orig_reg_packet->locked = False;
1048         free_packet(orig_reg_packet);
1049 }
1050
1051 /***********************************************************************
1052  Deal with a name registration request to a WINS server.
1053
1054  Use the following pseudocode :
1055
1056  registering_group
1057      |
1058      |
1059      +--------name exists
1060      |                  |
1061      |                  |
1062      |                  +--- existing name is group
1063      |                  |                      |
1064      |                  |                      |
1065      |                  |                      +--- add name (return).
1066      |                  |
1067      |                  |
1068      |                  +--- exiting name is unique
1069      |                                         |
1070      |                                         |
1071      |                                         +--- query existing owner (return).
1072      |
1073      |
1074      +--------name doesn't exist
1075                         |
1076                         |
1077                         +--- add name (return).
1078
1079  registering_unique
1080      |
1081      |
1082      +--------name exists
1083      |                  |
1084      |                  |
1085      |                  +--- existing name is group 
1086      |                  |                      |
1087      |                  |                      |
1088      |                  |                      +--- fail add (return).
1089      |                  | 
1090      |                  |
1091      |                  +--- exiting name is unique
1092      |                                         |
1093      |                                         |
1094      |                                         +--- query existing owner (return).
1095      |
1096      |
1097      +--------name doesn't exist
1098                         |
1099                         |
1100                         +--- add name (return).
1101
1102  As can be seen from the above, the two cases may be collapsed onto each
1103  other with the exception of the case where the name already exists and
1104  is a group name. This case we handle with an if statement.
1105  
1106 ************************************************************************/
1107
1108 void wins_process_name_registration_request(struct subnet_record *subrec,
1109                                             struct packet_struct *p)
1110 {
1111         unstring name;
1112         struct nmb_packet *nmb = &p->packet.nmb;
1113         struct nmb_name *question = &nmb->question.question_name;
1114         bool bcast = nmb->header.nm_flags.bcast;
1115         uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1116         int ttl = get_ttl_from_packet(nmb);
1117         struct name_record *namerec = NULL;
1118         struct in_addr from_ip;
1119         bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1120         struct in_addr our_fake_ip;
1121
1122         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1123         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1124
1125         if(bcast) {
1126                 /*
1127                  * We should only get unicast name registration packets here.
1128                  * Anyone trying to register broadcast should not be going to a WINS
1129                  * server. Log an error here.
1130                  */
1131
1132                 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1133 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1134                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1135                 return;
1136         }
1137
1138         DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1139 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1140
1141         /*
1142          * See if the name already exists.
1143          */
1144
1145         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1146
1147         /*
1148          * if the record exists but NOT in active state,
1149          * consider it dead.
1150          */
1151         if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1152                 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1153 not active - removing it.\n", nmb_namestr(question) ));
1154                 remove_name_from_namelist( subrec, namerec );
1155                 namerec = NULL;
1156         }
1157
1158         /*
1159          * Deal with the case where the name found was a dns entry.
1160          * Remove it as we now have a NetBIOS client registering the
1161          * name.
1162          */
1163
1164         if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1165                 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1166 a dns lookup - removing it.\n", nmb_namestr(question) ));
1167                 remove_name_from_namelist( subrec, namerec );
1168                 namerec = NULL;
1169         }
1170
1171         /*
1172          * Reject if the name exists and is not a REGISTER_NAME.
1173          * (ie. Don't allow any static names to be overwritten.
1174          */
1175
1176         if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1177                 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1178 to register name %s. Name already exists in WINS with source type %d.\n",
1179                         nmb_namestr(question), namerec->data.source ));
1180                 send_wins_name_registration_response(RFS_ERR, 0, p);
1181                 return;
1182         }
1183
1184         /*
1185          * Special policy decisions based on MS documentation.
1186          * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1187          * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1188          */
1189
1190         /*
1191          * A group name is always added as the local broadcast address, except
1192          * for group names ending in 0x1c.
1193          * Group names with type 0x1c are registered with individual IP addresses.
1194          */
1195
1196         if(registering_group_name && (question->name_type != 0x1c)) {
1197                 (void)interpret_addr2(&from_ip, "255.255.255.255");
1198         }
1199
1200         /*
1201          * Ignore all attempts to register a unique 0x1d name, although return success.
1202          */
1203
1204         if(!registering_group_name && (question->name_type == 0x1d)) {
1205                 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1206 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1207                 send_wins_name_registration_response(0, ttl, p);
1208                 return;
1209         }
1210
1211         /*
1212          * Next two cases are the 'if statement' mentioned above.
1213          */
1214
1215         if((namerec != NULL) && NAME_GROUP(namerec)) {
1216                 if(registering_group_name) {
1217                         /*
1218                          * If we are adding a group name, the name exists and is also a group entry just add this
1219                          * IP address to it and update the ttl.
1220                          */
1221
1222                         DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1223                                 inet_ntoa(from_ip), nmb_namestr(question) ));
1224
1225                         /* 
1226                          * Check the ip address is not already in the group.
1227                          */
1228
1229                         if(!find_ip_in_name_record(namerec, from_ip)) {
1230                                 add_ip_to_name_record(namerec, from_ip);
1231                                 /* we need to update the record for replication */
1232                                 get_global_id_and_update(&namerec->data.id, True);
1233
1234                                 /*
1235                                  * if the record is a replica, we must change
1236                                  * the wins owner to us to make the replication updates
1237                                  * it on the other wins servers.
1238                                  * And when the partner will receive this record,
1239                                  * it will update its own record.
1240                                  */
1241
1242                                 update_wins_owner(namerec, our_fake_ip);
1243                         }
1244                         update_name_ttl(namerec, ttl);
1245                         wins_hook("refresh", namerec, ttl);
1246                         send_wins_name_registration_response(0, ttl, p);
1247                         return;
1248                 } else {
1249
1250                         /*
1251                          * If we are adding a unique name, the name exists in the WINS db 
1252                          * and is a group name then reject the registration.
1253                          *
1254                          * explanation: groups have a higher priority than unique names.
1255                          */
1256
1257                         DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1258 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1259                         send_wins_name_registration_response(RFS_ERR, 0, p);
1260                         return;
1261                 } 
1262         }
1263
1264         /*
1265          * From here on down we know that if the name exists in the WINS db it is
1266          * a unique name, not a group name.
1267          */
1268
1269         /* 
1270          * If the name exists and is one of our names then check the
1271          * registering IP address. If it's not one of ours then automatically
1272          * reject without doing the query - we know we will reject it.
1273          */
1274
1275         if ( namerec != NULL ) {
1276                 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1277                 if( is_myname(name) ) {
1278                         if(!ismyip_v4(from_ip)) {
1279                                 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1280 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1281                                 send_wins_name_registration_response(RFS_ERR, 0, p);
1282                                 return;
1283                         } else {
1284                                 /*
1285                                  * It's one of our names and one of our IP's - update the ttl.
1286                                  */
1287                                 update_name_ttl(namerec, ttl);
1288                                 wins_hook("refresh", namerec, ttl);
1289                                 send_wins_name_registration_response(0, ttl, p);
1290                                 return;
1291                         }
1292                 }
1293         } else {
1294                 name[0] = '\0';
1295         }
1296
1297         /*
1298          * If the name exists and it is a unique registration and the registering IP 
1299          * is the same as the (single) already registered IP then just update the ttl.
1300          *
1301          * But not if the record is an active replica. IF it's a replica, it means it can be
1302          * the same client which has moved and not yet expired. So we don't update
1303          * the ttl in this case and go beyond to do a WACK and query the old client
1304          */
1305
1306         if( !registering_group_name
1307                         && (namerec != NULL)
1308                         && (namerec->data.num_ips == 1)
1309                         && ip_equal_v4( namerec->data.ip[0], from_ip )
1310                         && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1311                 update_name_ttl( namerec, ttl );
1312                 wins_hook("refresh", namerec, ttl);
1313                 send_wins_name_registration_response( 0, ttl, p );
1314                 return;
1315         }
1316
1317         /*
1318          * Finally if the name exists do a query to the registering machine 
1319          * to see if they still claim to have the name.
1320          */
1321
1322         if( namerec != NULL ) {
1323                 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1324                 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1325
1326                 /*
1327                  * First send a WACK to the registering machine.
1328                  */
1329
1330                 send_wins_wack_response(60, p);
1331
1332                 /*
1333                  * When the reply comes back we need the original packet.
1334                  * Lock this so it won't be freed and then put it into
1335                  * the userdata structure.
1336                  */
1337
1338                 p->locked = True;
1339
1340                 userdata = (struct userdata_struct *)ud;
1341
1342                 userdata->copy_fn = NULL;
1343                 userdata->free_fn = NULL;
1344                 userdata->userdata_len = sizeof(struct packet_struct *);
1345                 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1346
1347                 /*
1348                  * Use the new call to send a query directly to an IP address.
1349                  * This sends the query directly to the IP address, and ensures
1350                  * the recursion desired flag is not set (you were right Luke :-).
1351                  * This function should *only* be called from the WINS server
1352                  * code. JRA.
1353                  */
1354
1355                 pull_ascii_nstring(name, sizeof(name), question->name);
1356                 query_name_from_wins_server( *namerec->data.ip,
1357                                 name,
1358                                 question->name_type, 
1359                                 wins_register_query_success,
1360                                 wins_register_query_fail,
1361                                 userdata );
1362                 return;
1363         }
1364
1365         /*
1366          * Name did not exist - add it.
1367          */
1368
1369         pull_ascii_nstring(name, sizeof(name), question->name);
1370         add_name_to_subnet( subrec, name, question->name_type,
1371                         nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1372
1373         if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1374                 get_global_id_and_update(&namerec->data.id, True);
1375                 update_wins_owner(namerec, our_fake_ip);
1376                 update_wins_flag(namerec, WINS_ACTIVE);
1377                 wins_hook("add", namerec, ttl);
1378         }
1379
1380         send_wins_name_registration_response(0, ttl, p);
1381 }
1382
1383 /***********************************************************************
1384  Deal with a mutihomed name query success to the machine that
1385  requested the multihomed name registration.
1386
1387  We have a locked pointer to the original packet stashed away in the
1388  userdata pointer.
1389 ************************************************************************/
1390
1391 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1392                                              struct userdata_struct *userdata,
1393                                              struct nmb_name *question_name,
1394                                              struct in_addr ip,
1395                                              struct res_rec *answers)
1396 {
1397         struct packet_struct *orig_reg_packet;
1398         struct nmb_packet *nmb;
1399         struct name_record *namerec = NULL;
1400         struct in_addr from_ip;
1401         int ttl;
1402         struct in_addr our_fake_ip;
1403
1404         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1405         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1406
1407         nmb = &orig_reg_packet->packet.nmb;
1408
1409         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1410         ttl = get_ttl_from_packet(nmb);
1411
1412         /*
1413          * We want to just add the new IP, as we now know the requesting
1414          * machine claims to own it. But we can't just do that as an arbitary
1415          * amount of time may have taken place between the name query
1416          * request and this response. So we check that
1417          * the name still exists and is in the same state - if so
1418          * we just add the extra IP and update the ttl.
1419          */
1420
1421         namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1422
1423         if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1424                 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1425 a subsequent IP address.\n", nmb_namestr(question_name) ));
1426                 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1427
1428                 orig_reg_packet->locked = False;
1429                 free_packet(orig_reg_packet);
1430
1431                 return;
1432         }
1433
1434         if(!find_ip_in_name_record(namerec, from_ip)) {
1435                 add_ip_to_name_record(namerec, from_ip);
1436         }
1437
1438         get_global_id_and_update(&namerec->data.id, True);
1439         update_wins_owner(namerec, our_fake_ip);
1440         update_wins_flag(namerec, WINS_ACTIVE);
1441         update_name_ttl(namerec, ttl);
1442         wins_hook("add", namerec, ttl);
1443         send_wins_name_registration_response(0, ttl, orig_reg_packet);
1444
1445         orig_reg_packet->locked = False;
1446         free_packet(orig_reg_packet);
1447 }
1448
1449 /***********************************************************************
1450  Deal with a name registration request query failure to a client that
1451  owned the name.
1452
1453  We have a locked pointer to the original packet stashed away in the
1454  userdata pointer.
1455 ************************************************************************/
1456
1457 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1458                                           struct response_record *rrec,
1459                                           struct nmb_name *question_name,
1460                                           int rcode)
1461 {
1462         struct userdata_struct *userdata = rrec->userdata;
1463         struct packet_struct *orig_reg_packet;
1464
1465         memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1466
1467         DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1468 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1469         send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1470
1471         orig_reg_packet->locked = False;
1472         free_packet(orig_reg_packet);
1473         return;
1474 }
1475
1476 /***********************************************************************
1477  Deal with a multihomed name registration request to a WINS server.
1478  These cannot be group name registrations.
1479 ***********************************************************************/
1480
1481 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1482                                                         struct packet_struct *p)
1483 {
1484         struct nmb_packet *nmb = &p->packet.nmb;
1485         struct nmb_name *question = &nmb->question.question_name;
1486         bool bcast = nmb->header.nm_flags.bcast;
1487         uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1488         int ttl = get_ttl_from_packet(nmb);
1489         struct name_record *namerec = NULL;
1490         struct in_addr from_ip;
1491         bool group = (nb_flags & NB_GROUP) ? True : False;
1492         struct in_addr our_fake_ip;
1493         unstring qname;
1494
1495         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1496         putip((char *)&from_ip,&nmb->additional->rdata[2]);
1497
1498         if(bcast) {
1499                 /*
1500                  * We should only get unicast name registration packets here.
1501                  * Anyone trying to register broadcast should not be going to a WINS
1502                  * server. Log an error here.
1503                  */
1504
1505                 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1506 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1507                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1508                 return;
1509         }
1510
1511         /*
1512          * Only unique names should be registered multihomed.
1513          */
1514
1515         if(group) {
1516                 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1517 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1518                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1519                 return;
1520         }
1521
1522         DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1523 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1524
1525         /*
1526          * Deal with policy regarding 0x1d names.
1527          */
1528
1529         if(question->name_type == 0x1d) {
1530                 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1531 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1532                 send_wins_name_registration_response(0, ttl, p);  
1533                 return;
1534         }
1535
1536         /*
1537          * See if the name already exists.
1538          */
1539
1540         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1541
1542         /*
1543          * if the record exists but NOT in active state,
1544          * consider it dead.
1545          */
1546
1547         if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1548                 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1549                 remove_name_from_namelist(subrec, namerec);
1550                 namerec = NULL;
1551         }
1552   
1553         /*
1554          * Deal with the case where the name found was a dns entry.
1555          * Remove it as we now have a NetBIOS client registering the
1556          * name.
1557          */
1558
1559         if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1560                 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1561 - removing it.\n", nmb_namestr(question) ));
1562                 remove_name_from_namelist( subrec, namerec);
1563                 namerec = NULL;
1564         }
1565
1566         /*
1567          * Reject if the name exists and is not a REGISTER_NAME.
1568          * (ie. Don't allow any static names to be overwritten.
1569          */
1570
1571         if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1572                 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1573 to register name %s. Name already exists in WINS with source type %d.\n",
1574                         nmb_namestr(question), namerec->data.source ));
1575                 send_wins_name_registration_response(RFS_ERR, 0, p);
1576                 return;
1577         }
1578
1579         /*
1580          * Reject if the name exists and is a GROUP name and is active.
1581          */
1582
1583         if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1584                 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1585 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1586                 send_wins_name_registration_response(RFS_ERR, 0, p);
1587                 return;
1588         } 
1589
1590         /*
1591          * From here on down we know that if the name exists in the WINS db it is
1592          * a unique name, not a group name.
1593          */
1594
1595         /*
1596          * If the name exists and is one of our names then check the
1597          * registering IP address. If it's not one of ours then automatically
1598          * reject without doing the query - we know we will reject it.
1599          */
1600
1601         if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1602                 if(!ismyip_v4(from_ip)) {
1603                         DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1604 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1605                         send_wins_name_registration_response(RFS_ERR, 0, p);
1606                         return;
1607                 } else {
1608                         /*
1609                          * It's one of our names and one of our IP's. Ensure the IP is in the record and
1610                          *  update the ttl. Update the version ID to force replication.
1611                          */
1612                         update_name_ttl(namerec, ttl);
1613
1614                         if(!find_ip_in_name_record(namerec, from_ip)) {
1615                                 get_global_id_and_update(&namerec->data.id, True);
1616                                 update_wins_owner(namerec, our_fake_ip);
1617                                 update_wins_flag(namerec, WINS_ACTIVE);
1618
1619                                 add_ip_to_name_record(namerec, from_ip);
1620                         }
1621
1622                         wins_hook("refresh", namerec, ttl);
1623                         send_wins_name_registration_response(0, ttl, p);
1624                         return;
1625                 }
1626         }
1627
1628         /*
1629          * If the name exists and is active, check if the IP address is already registered
1630          * to that name. If so then update the ttl and reply success.
1631          */
1632
1633         if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1634                 update_name_ttl(namerec, ttl);
1635
1636                 /*
1637                  * If it's a replica, we need to become the wins owner
1638                  * to force the replication
1639                  */
1640                 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1641                         get_global_id_and_update(&namerec->data.id, True);
1642                         update_wins_owner(namerec, our_fake_ip);
1643                         update_wins_flag(namerec, WINS_ACTIVE);
1644                 }
1645     
1646                 wins_hook("refresh", namerec, ttl);
1647                 send_wins_name_registration_response(0, ttl, p);
1648                 return;
1649         }
1650
1651         /*
1652          * If the name exists do a query to the owner
1653          * to see if they still want the name.
1654          */
1655
1656         if(namerec != NULL) {
1657                 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1658                 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1659
1660                 /*
1661                  * First send a WACK to the registering machine.
1662                  */
1663
1664                 send_wins_wack_response(60, p);
1665
1666                 /*
1667                  * When the reply comes back we need the original packet.
1668                  * Lock this so it won't be freed and then put it into
1669                  * the userdata structure.
1670                  */
1671
1672                 p->locked = True;
1673
1674                 userdata = (struct userdata_struct *)ud;
1675
1676                 userdata->copy_fn = NULL;
1677                 userdata->free_fn = NULL;
1678                 userdata->userdata_len = sizeof(struct packet_struct *);
1679                 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1680
1681                 /* 
1682                  * Use the new call to send a query directly to an IP address.
1683                  * This sends the query directly to the IP address, and ensures
1684                  * the recursion desired flag is not set (you were right Luke :-).
1685                  * This function should *only* be called from the WINS server
1686                  * code. JRA.
1687                  *
1688                  * Note that this packet is sent to the current owner of the name,
1689                  * not the person who sent the packet 
1690                  */
1691
1692                 pull_ascii_nstring( qname, sizeof(qname), question->name);
1693                 query_name_from_wins_server( namerec->data.ip[0],
1694                                 qname,
1695                                 question->name_type, 
1696                                 wins_multihomed_register_query_success,
1697                                 wins_multihomed_register_query_fail,
1698                                 userdata );
1699
1700                 return;
1701         }
1702
1703         /*
1704          * Name did not exist - add it.
1705          */
1706
1707         pull_ascii_nstring( qname, sizeof(qname), question->name);
1708         add_name_to_subnet( subrec, qname, question->name_type,
1709                         nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1710
1711         if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1712                 get_global_id_and_update(&namerec->data.id, True);
1713                 update_wins_owner(namerec, our_fake_ip);
1714                 update_wins_flag(namerec, WINS_ACTIVE);
1715                 wins_hook("add", namerec, ttl);
1716         }
1717
1718         send_wins_name_registration_response(0, ttl, p);
1719 }
1720
1721 /***********************************************************************
1722  Fetch all *<1b> names from the WINS db and store on the namelist.
1723 ***********************************************************************/
1724
1725 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1726 {
1727         struct name_record *namerec = NULL;
1728
1729         if (kbuf.dsize != sizeof(unstring) + 1) {
1730                 return 0;
1731         }
1732
1733         /* Filter out all non-1b names. */
1734         if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1735                 return 0;
1736         }
1737
1738         namerec = wins_record_to_name_record(kbuf, dbuf);
1739         if (!namerec) {
1740                 return 0;
1741         }
1742
1743         DLIST_ADD(wins_server_subnet->namelist, namerec);
1744         return 0;
1745 }
1746
1747 void fetch_all_active_wins_1b_names(void)
1748 {
1749         tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1750 }
1751
1752 /***********************************************************************
1753  Deal with the special name query for *<1b>.
1754 ***********************************************************************/
1755    
1756 static void process_wins_dmb_query_request(struct subnet_record *subrec,  
1757                                            struct packet_struct *p)
1758 {  
1759         struct name_record *namerec = NULL;
1760         char *prdata;
1761         int num_ips;
1762
1763         /*
1764          * Go through all the ACTIVE names in the WINS db looking for those
1765          * ending in <1b>. Use this to calculate the number of IP
1766          * addresses we need to return.
1767          */
1768
1769         num_ips = 0;
1770
1771         /* First, clear the in memory list - we're going to re-populate
1772            it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1773
1774         wins_delete_all_tmp_in_memory_records();
1775
1776         fetch_all_active_wins_1b_names();
1777
1778         for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1779                 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1780                         num_ips += namerec->data.num_ips;
1781                 }
1782         }
1783
1784         if(num_ips == 0) {
1785                 /*
1786                  * There are no 0x1b names registered. Return name query fail.
1787                  */
1788                 send_wins_name_query_response(NAM_ERR, p, NULL);
1789                 return;
1790         }
1791
1792         if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1793                 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1794                 return;
1795         }
1796
1797         /*
1798          * Go through all the names again in the WINS db looking for those
1799          * ending in <1b>. Add their IP addresses into the list we will
1800          * return.
1801          */ 
1802
1803         num_ips = 0;
1804         for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1805                 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1806                         int i;
1807                         for(i = 0; i < namerec->data.num_ips; i++) {
1808                                 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1809                                 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1810                                 num_ips++;
1811                         }
1812                 }
1813         }
1814
1815         /*
1816          * Send back the reply containing the IP list.
1817          */
1818
1819         reply_netbios_packet(p,                                /* Packet to reply to. */
1820                                 0,                             /* Result code. */
1821                                 WINS_QUERY,                    /* nmbd type code. */
1822                                 NMB_NAME_QUERY_OPCODE,         /* opcode. */
1823                                 lp_min_wins_ttl(),             /* ttl. */
1824                                 prdata,                        /* data to send. */
1825                                 num_ips*6);                    /* data length. */
1826
1827         SAFE_FREE(prdata);
1828 }
1829
1830 /****************************************************************************
1831 Send a WINS name query response.
1832 **************************************************************************/
1833
1834 void send_wins_name_query_response(int rcode, struct packet_struct *p, 
1835                                           struct name_record *namerec)
1836 {
1837         char rdata[6];
1838         char *prdata = rdata;
1839         int reply_data_len = 0;
1840         int ttl = 0;
1841         int i;
1842
1843         memset(rdata,'\0',6);
1844
1845         if(rcode == 0) {
1846                 ttl = (namerec->data.death_time != PERMANENT_TTL) ?  namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1847
1848                 /* Copy all known ip addresses into the return data. */
1849                 /* Optimise for the common case of one IP address so we don't need a malloc. */
1850
1851                 if( namerec->data.num_ips == 1 ) {
1852                         prdata = rdata;
1853                 } else {
1854                         if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1855                                 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1856                                 return;
1857                         }
1858                 }
1859
1860                 for(i = 0; i < namerec->data.num_ips; i++) {
1861                         set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1862                         putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1863                 }
1864
1865                 sort_query_replies(prdata, i, p->ip);
1866                 reply_data_len = namerec->data.num_ips * 6;
1867         }
1868
1869         reply_netbios_packet(p,                                /* Packet to reply to. */
1870                                 rcode,                         /* Result code. */
1871                                 WINS_QUERY,                    /* nmbd type code. */
1872                                 NMB_NAME_QUERY_OPCODE,         /* opcode. */
1873                                 ttl,                           /* ttl. */
1874                                 prdata,                        /* data to send. */
1875                                 reply_data_len);               /* data length. */
1876
1877         if(prdata != rdata) {
1878                 SAFE_FREE(prdata);
1879         }
1880 }
1881
1882 /***********************************************************************
1883  Deal with a name query.
1884 ***********************************************************************/
1885
1886 void wins_process_name_query_request(struct subnet_record *subrec, 
1887                                      struct packet_struct *p)
1888 {
1889         struct nmb_packet *nmb = &p->packet.nmb;
1890         struct nmb_name *question = &nmb->question.question_name;
1891         struct name_record *namerec = NULL;
1892         unstring qname;
1893
1894         DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", 
1895                 nmb_namestr(question), inet_ntoa(p->ip) ));
1896
1897         /*
1898          * Special name code. If the queried name is *<1b> then search
1899          * the entire WINS database and return a list of all the IP addresses
1900          * registered to any <1b> name. This is to allow domain master browsers
1901          * to discover other domains that may not have a presence on their subnet.
1902          */
1903
1904         pull_ascii_nstring(qname, sizeof(qname), question->name);
1905         if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1906                 process_wins_dmb_query_request( subrec, p);
1907                 return;
1908         }
1909
1910         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1911
1912         if(namerec != NULL) {
1913                 /*
1914                  * If the name is not anymore in active state then reply not found.
1915                  * it's fair even if we keep it in the cache for days.
1916                  */
1917                 if (!WINS_STATE_ACTIVE(namerec)) {
1918                         DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1919                                 nmb_namestr(question) ));
1920                         send_wins_name_query_response(NAM_ERR, p, namerec);
1921                         return;
1922                 }
1923
1924                 /* 
1925                  * If it's a DNSFAIL_NAME then reply name not found.
1926                  */
1927
1928                 if( namerec->data.source == DNSFAIL_NAME ) {
1929                         DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1930                                 nmb_namestr(question) ));
1931                         send_wins_name_query_response(NAM_ERR, p, namerec);
1932                         return;
1933                 }
1934
1935                 /*
1936                  * If the name has expired then reply name not found.
1937                  */
1938
1939                 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1940                         DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1941                                         nmb_namestr(question) ));
1942                         send_wins_name_query_response(NAM_ERR, p, namerec);
1943                         return;
1944                 }
1945
1946                 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1947                                 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1948
1949                 send_wins_name_query_response(0, p, namerec);
1950                 return;
1951         }
1952
1953         /* 
1954          * Name not found in WINS - try a dns query if it's a 0x20 name.
1955          */
1956
1957         if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1958                 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1959                                 nmb_namestr(question) ));
1960
1961                 queue_dns_query(p, question);
1962                 return;
1963         }
1964
1965         /*
1966          * Name not found - return error.
1967          */
1968
1969         send_wins_name_query_response(NAM_ERR, p, NULL);
1970 }
1971
1972 /****************************************************************************
1973 Send a WINS name release response.
1974 **************************************************************************/
1975
1976 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1977 {
1978         struct nmb_packet *nmb = &p->packet.nmb;
1979         char rdata[6];
1980
1981         memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1982
1983         reply_netbios_packet(p,                               /* Packet to reply to. */
1984                                 rcode,                        /* Result code. */
1985                                 NMB_REL,                      /* nmbd type code. */
1986                                 NMB_NAME_RELEASE_OPCODE,      /* opcode. */
1987                                 0,                            /* ttl. */
1988                                 rdata,                        /* data to send. */
1989                                 6);                           /* data length. */
1990 }
1991
1992 /***********************************************************************
1993  Deal with a name release.
1994 ***********************************************************************/
1995
1996 void wins_process_name_release_request(struct subnet_record *subrec,
1997                                        struct packet_struct *p)
1998 {
1999         struct nmb_packet *nmb = &p->packet.nmb;
2000         struct nmb_name *question = &nmb->question.question_name;
2001         bool bcast = nmb->header.nm_flags.bcast;
2002         uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
2003         struct name_record *namerec = NULL;
2004         struct in_addr from_ip;
2005         bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
2006
2007         putip((char *)&from_ip,&nmb->additional->rdata[2]);
2008
2009         if(bcast) {
2010                 /*
2011                  * We should only get unicast name registration packets here.
2012                  * Anyone trying to register broadcast should not be going to a WINS
2013                  * server. Log an error here.
2014                  */
2015
2016                 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2017 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2018                         nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2019                 return;
2020         }
2021   
2022         DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2023 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2024     
2025         /*
2026          * Deal with policy regarding 0x1d names.
2027          */
2028
2029         if(!releasing_group_name && (question->name_type == 0x1d)) {
2030                 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2031 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2032                 send_wins_name_release_response(0, p);
2033                 return;
2034         }
2035
2036         /*
2037          * See if the name already exists.
2038          */
2039     
2040         namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2041
2042         if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2043                 send_wins_name_release_response(NAM_ERR, p);
2044                 return;
2045         }
2046
2047         /* 
2048          * Check that the sending machine has permission to release this name.
2049          * If it's a group name not ending in 0x1c then just say yes and let
2050          * the group time out.
2051          */
2052
2053         if(releasing_group_name && (question->name_type != 0x1c)) {
2054                 send_wins_name_release_response(0, p);
2055                 return;
2056         }
2057
2058         /* 
2059          * Check that the releasing node is on the list of IP addresses
2060          * for this name. Disallow the release if not.
2061          */
2062
2063         if(!find_ip_in_name_record(namerec, from_ip)) {
2064                 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2065 release name %s as IP %s is not one of the known IP's for this name.\n",
2066                         nmb_namestr(question), inet_ntoa(from_ip) ));
2067                 send_wins_name_release_response(NAM_ERR, p);
2068                 return;
2069         }
2070
2071         /*
2072          * Check if the record is active. IF it's already released
2073          * or tombstoned, refuse the release.
2074          */
2075
2076         if (!WINS_STATE_ACTIVE(namerec)) {
2077                 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2078 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2079                 send_wins_name_release_response(NAM_ERR, p);
2080                 return;
2081         }    
2082
2083         /*
2084          * Check if the record is a 0x1c group
2085          * and has more then one ip
2086          * remove only this address.
2087          */
2088
2089         if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2090                 remove_ip_from_name_record(namerec, from_ip);
2091                 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2092                                 inet_ntoa(from_ip),nmb_namestr(question)));
2093                 wins_hook("delete", namerec, 0);
2094                 send_wins_name_release_response(0, p);
2095                 return;
2096         }
2097
2098         /* 
2099          * Send a release response.
2100          * Flag the name as released and update the ttl
2101          */
2102
2103         namerec->data.wins_flags |= WINS_RELEASED;
2104         update_name_ttl(namerec, EXTINCTION_INTERVAL);
2105
2106         wins_hook("delete", namerec, 0);
2107         send_wins_name_release_response(0, p);
2108 }
2109
2110 /*******************************************************************
2111  WINS time dependent processing.
2112 ******************************************************************/
2113
2114 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2115 {
2116         time_t t = *(time_t *)state;
2117         bool store_record = False;
2118         struct name_record *namerec = NULL;
2119         struct in_addr our_fake_ip;
2120
2121         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
2122         if (kbuf.dsize != sizeof(unstring) + 1) {
2123                 return 0;
2124         }
2125
2126         namerec = wins_record_to_name_record(kbuf, dbuf);
2127         if (!namerec) {
2128                 return 0;
2129         }
2130
2131         if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2132                 if( namerec->data.source == SELF_NAME ) {
2133                         DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n", 
2134                                    wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2135                         namerec->data.death_time += 300;
2136                         store_record = True;
2137                         goto done;
2138                 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2139                         DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2140                                         nmb_namestr(&namerec->name)));
2141                         remove_name_from_wins_namelist(namerec );
2142                         goto done;
2143                 }
2144
2145                 /* handle records, samba is the wins owner */
2146                 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2147                         switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2148                                 case WINS_ACTIVE:
2149                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2150                                         namerec->data.wins_flags|=WINS_RELEASED;
2151                                         namerec->data.death_time = t + EXTINCTION_INTERVAL;
2152                                         DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2153                                                 nmb_namestr(&namerec->name)));
2154                                         store_record = True;
2155                                         goto done;
2156                                 case WINS_RELEASED:
2157                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2158                                         namerec->data.wins_flags|=WINS_TOMBSTONED;
2159                                         namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2160                                         get_global_id_and_update(&namerec->data.id, True);
2161                                         DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2162                                                 nmb_namestr(&namerec->name)));
2163                                         store_record = True;
2164                                         goto done;
2165                                 case WINS_TOMBSTONED:
2166                                         DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2167                                                 nmb_namestr(&namerec->name)));
2168                                         remove_name_from_wins_namelist(namerec );
2169                                         goto done;
2170                         }
2171                 } else {
2172                         switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2173                                 case WINS_ACTIVE:
2174                                         /* that's not as MS says it should be */
2175                                         namerec->data.wins_flags&=~WINS_STATE_MASK;
2176                                         namerec->data.wins_flags|=WINS_TOMBSTONED;
2177                                         namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2178                                         DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2179                                                 nmb_namestr(&namerec->name)));
2180                                         store_record = True;
2181                                         goto done;
2182                                 case WINS_TOMBSTONED:
2183                                         DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2184                                                 nmb_namestr(&namerec->name)));
2185                                         remove_name_from_wins_namelist(namerec );
2186                                         goto done;
2187                                 case WINS_RELEASED:
2188                                         DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2189 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2190                                         goto done;
2191                         }
2192                 }
2193         }
2194
2195   done:
2196
2197         if (store_record) {
2198                 wins_store_changed_namerec(namerec);
2199         }
2200
2201         SAFE_FREE(namerec->data.ip);
2202         SAFE_FREE(namerec);
2203
2204         return 0;
2205 }
2206
2207 /*******************************************************************
2208  Time dependent wins processing.
2209 ******************************************************************/
2210
2211 void initiate_wins_processing(time_t t)
2212 {
2213         static time_t lasttime = 0;
2214
2215         if (!lasttime) {
2216                 lasttime = t;
2217         }
2218         if (t - lasttime < 20) {
2219                 return;
2220         }
2221
2222         if(!lp_we_are_a_wins_server()) {
2223                 lasttime = t;
2224                 return;
2225         }
2226
2227         tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2228
2229         wins_delete_all_tmp_in_memory_records();
2230
2231         wins_write_database(t, True);
2232
2233         lasttime = t;
2234 }
2235
2236 /*******************************************************************
2237  Write out one record.
2238 ******************************************************************/
2239
2240 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2241 {
2242         int i;
2243         struct tm *tm;
2244
2245         DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2246
2247         if( namerec->data.death_time != PERMANENT_TTL ) {
2248                 char *ts, *nl;
2249
2250                 tm = localtime(&namerec->data.death_time);
2251                 if (!tm) {
2252                         return;
2253                 }
2254                 ts = asctime(tm);
2255                 if (!ts) {
2256                         return;
2257                 }
2258                 nl = strrchr( ts, '\n' );
2259                 if( NULL != nl ) {
2260                         *nl = '\0';
2261                 }
2262                 DEBUGADD(4,("TTL = %s  ", ts ));
2263         } else {
2264                 DEBUGADD(4,("TTL = PERMANENT                 "));
2265         }
2266
2267         for (i = 0; i < namerec->data.num_ips; i++) {
2268                 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2269         }
2270         DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2271
2272         if( namerec->data.source == REGISTER_NAME ) {
2273                 unstring name;
2274                 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2275                 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2276                         (int)namerec->data.death_time);
2277
2278                 for (i = 0; i < namerec->data.num_ips; i++)
2279                         x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2280                 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2281         }
2282 }
2283
2284 /*******************************************************************
2285  Write out the current WINS database.
2286 ******************************************************************/
2287
2288 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2289 {
2290         struct name_record *namerec = NULL;
2291         XFILE *fp = (XFILE *)state;
2292
2293         if (kbuf.dsize != sizeof(unstring) + 1) {
2294                 return 0;
2295         }
2296
2297         namerec = wins_record_to_name_record(kbuf, dbuf);
2298         if (!namerec) {
2299                 return 0;
2300         }
2301
2302         wins_write_name_record(namerec, fp);
2303
2304         SAFE_FREE(namerec->data.ip);
2305         SAFE_FREE(namerec);
2306         return 0;
2307 }
2308
2309
2310 void wins_write_database(time_t t, bool background)
2311 {
2312         static time_t last_write_time = 0;
2313         pstring fname, fnamenew;
2314
2315         XFILE *fp;
2316    
2317         if (background) {
2318                 if (!last_write_time) {
2319                         last_write_time = t;
2320                 }
2321                 if (t - last_write_time < 120) {
2322                         return;
2323                 }
2324
2325         }
2326
2327         if(!lp_we_are_a_wins_server()) {
2328                 return;
2329         }
2330
2331         /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2332         if (background) {
2333                 CatchChild();
2334                 if (sys_fork()) {
2335                         return;
2336                 }
2337                 if (tdb_reopen(wins_tdb)) {
2338                         DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2339                                 strerror(errno)));
2340                         _exit(0);
2341                         return;
2342                 }
2343         }
2344
2345         slprintf(fname,sizeof(fname)-1,"%s/%s", dyn_STATEDIR(), WINS_LIST);
2346         all_string_sub(fname,"//", "/", 0);
2347         slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
2348
2349         if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2350                 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2351                 if (background) {
2352                         _exit(0);
2353                 }
2354                 return;
2355         }
2356
2357         DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2358
2359         x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2360  
2361         tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2362
2363         x_fclose(fp);
2364         chmod(fnamenew,0644);
2365         unlink(fname);
2366         rename(fnamenew,fname);
2367         if (background) {
2368                 _exit(0);
2369         }
2370 }
2371
2372 #if 0
2373         Until winsrepl is done.
2374 /****************************************************************************
2375  Process a internal Samba message receiving a wins record.
2376 ***************************************************************************/
2377
2378 void nmbd_wins_new_entry(struct messaging_context *msg,
2379                                        void *private_data,
2380                                        uint32_t msg_type,
2381                                        struct server_id server_id,
2382                                        DATA_BLOB *data)
2383 {
2384         WINS_RECORD *record;
2385         struct name_record *namerec = NULL;
2386         struct name_record *new_namerec = NULL;
2387         struct nmb_name question;
2388         bool overwrite=False;
2389         struct in_addr our_fake_ip;
2390         int i;
2391
2392         (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
2393         if (buf==NULL) {
2394                 return;
2395         }
2396         
2397         /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2398         record=(WINS_RECORD *)buf;
2399         
2400         make_nmb_name(&question, record->name, record->type);
2401
2402         namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2403
2404         /* record doesn't exist, add it */
2405         if (namerec == NULL) {
2406                 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n", 
2407                           record->name, record->type, inet_ntoa(record->wins_ip)));
2408
2409                 new_namerec=add_name_to_subnet( wins_server_subnet,
2410                                                 record->name,
2411                                                 record->type,
2412                                                 record->nb_flags, 
2413                                                 EXTINCTION_INTERVAL,
2414                                                 REGISTER_NAME,
2415                                                 record->num_ips,
2416                                                 record->ip);
2417
2418                 if (new_namerec!=NULL) {
2419                                 update_wins_owner(new_namerec, record->wins_ip);
2420                                 update_wins_flag(new_namerec, record->wins_flags);
2421                                 new_namerec->data.id=record->id;
2422
2423                                 wins_server_subnet->namelist_changed = True;
2424                         }
2425         }
2426
2427         /* check if we have a conflict */
2428         if (namerec != NULL) {
2429                 /* both records are UNIQUE */
2430                 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2431
2432                         /* the database record is a replica */
2433                         if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2434                                 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2435                                         if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2436                                                 overwrite=True;
2437                                 } else
2438                                         overwrite=True;
2439                         } else {
2440                         /* we are the wins owner of the database record */
2441                                 /* the 2 records have the same IP address */
2442                                 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2443                                         if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2444                                                 get_global_id_and_update(&namerec->data.id, True);
2445                                         else
2446                                                 overwrite=True;
2447                                 
2448                                 } else {
2449                                 /* the 2 records have different IP address */
2450                                         if (namerec->data.wins_flags&WINS_ACTIVE) {
2451                                                 if (record->wins_flags&WINS_TOMBSTONED)
2452                                                         get_global_id_and_update(&namerec->data.id, True);
2453                                                 if (record->wins_flags&WINS_ACTIVE)
2454                                                         /* send conflict challenge to the replica node */
2455                                                         ;
2456                                         } else
2457                                                 overwrite=True;
2458                                 }
2459
2460                         }
2461                 }
2462                 
2463                 /* the replica is a standard group */
2464                 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2465                         /* if the database record is unique and active force a name release */
2466                         if (namerec->data.wins_flags&WINS_UNIQUE)
2467                                 /* send a release name to the unique node */
2468                                 ;
2469                         overwrite=True;
2470                 
2471                 }
2472         
2473                 /* the replica is a special group */
2474                 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2475                         if (namerec->data.wins_flags&WINS_ACTIVE) {
2476                                 for (i=0; i<record->num_ips; i++)
2477                                         if(!find_ip_in_name_record(namerec, record->ip[i]))
2478                                                 add_ip_to_name_record(namerec, record->ip[i]);
2479                         } else {
2480                                 overwrite=True;
2481                         }
2482                 }
2483                 
2484                 /* the replica is a multihomed host */
2485                 
2486                 /* I'm giving up on multi homed. Too much complex to understand */
2487                 
2488                 if (record->wins_flags&WINS_MHOMED) {
2489                         if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2490                                 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2491                                         overwrite=True;
2492                         }
2493                         else {
2494                                 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2495                                         overwrite=True;
2496                                 
2497                                 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2498                                         if (namerec->data.wins_flags&WINS_UNIQUE)
2499                                                 get_global_id_and_update(&namerec->data.id, True);
2500                                 
2501                         }
2502                         
2503                         if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2504                                 if (namerec->data.wins_flags&WINS_UNIQUE ||
2505                                     namerec->data.wins_flags&WINS_MHOMED)
2506                                         if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2507                                                 overwrite=True;
2508                                 
2509                 }
2510
2511                 if (overwrite == False)
2512                         DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n", 
2513                                   record->name, record->type, inet_ntoa(record->wins_ip)));
2514                 else {
2515                         DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n", 
2516                                   record->name, record->type, inet_ntoa(record->wins_ip)));
2517
2518                         /* remove the old record and add a new one */
2519                         remove_name_from_namelist( wins_server_subnet, namerec );
2520                         new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags, 
2521                                                 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2522                         if (new_namerec!=NULL) {
2523                                 update_wins_owner(new_namerec, record->wins_ip);
2524                                 update_wins_flag(new_namerec, record->wins_flags);
2525                                 new_namerec->data.id=record->id;
2526
2527                                 wins_server_subnet->namelist_changed = True;
2528                         }
2529
2530                         wins_server_subnet->namelist_changed = True;
2531                 }
2532
2533         }
2534 }
2535 #endif