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