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