source: trunk/server/source3/nmbd/nmbd_winsserver.c@ 898

Last change on this file since 898 was 751, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.9

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