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