source: vendor/current/source3/nmbd/nmbd_winsserver.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

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