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