source: branches/samba-3.0/source/nmbd/nmbd_winsserver.c

Last change on this file was 73, checked in by Paul Smedley, 18 years ago

Close file handle before rename() - fixes Ticket #30

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