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