talloc: release 2.4.2
[Samba.git] / source3 / nmbd / nmbd_winsserver.c
blobecae447619591772e740ac7c00e58751db5c96b7
1 /*
2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2005
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.
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.
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/>.
20 Converted to store WINS data in a tdb. Dec 2005. JRA.
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "nmbd/nmbd.h"
26 #include "util_tdb.h"
28 #define WINS_LIST "wins.dat"
29 #define WINS_VERSION 1
30 #define WINSDB_VERSION 1
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 *****************************************************************************/
37 TDB_CONTEXT *wins_tdb;
39 /****************************************************************************
40 Delete all the temporary name records on the in-memory linked list.
41 *****************************************************************************/
43 static void wins_delete_all_tmp_in_memory_records(void)
45 struct name_record *nr = NULL;
46 struct name_record *nrnext = NULL;
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);
57 /****************************************************************************
58 Delete all the temporary 1b name records on the in-memory linked list.
59 *****************************************************************************/
61 static void wins_delete_all_1b_in_memory_records(void)
63 struct name_record *nr = NULL;
64 struct name_record *nrnext = NULL;
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);
77 /****************************************************************************
78 Convert a wins.tdb record to a struct name_record. Add in our lp_netbios_scope().
79 *****************************************************************************/
81 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
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;
94 if (data.dptr == NULL || data.dsize == 0) {
95 return NULL;
98 /* Min size is "wbddddddd" + 1 ip address (4). */
99 if (data.dsize < 2 + 1 + (7*4) + 4) {
100 return NULL;
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 );
115 namerec = SMB_MALLOC_P(struct name_record);
116 if (!namerec) {
117 return NULL;
119 ZERO_STRUCTP(namerec);
121 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
122 if (!namerec->data.ip) {
123 SAFE_FREE(namerec);
124 return NULL;
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);
133 /* We're using a byte-by-byte compare, so we must be sure that
134 * unused space doesn't have garbage in it.
137 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
138 namerec->name.name[i] = '\0';
140 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
141 namerec->name.scope[i] = '\0';
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;
154 for (i = 0; i < num_ips; i++) {
155 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
158 return namerec;
161 /****************************************************************************
162 Convert a struct name_record to a wins.tdb record. Ignore the scope.
163 *****************************************************************************/
165 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
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;
173 ZERO_STRUCT(data);
175 len = (2 + 1 + (7*4)); /* "wbddddddd" */
176 len += (namerec->data.num_ips * 4);
178 data.dptr = (uint8_t *)SMB_MALLOC(len);
179 if (!data.dptr) {
180 return data;
182 data.dsize = len;
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 );
195 for (i = 0; i < namerec->data.num_ips; i++) {
196 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
199 return data;
202 /****************************************************************************
203 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
204 *****************************************************************************/
206 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
208 static char keydata[sizeof(unstring) + 1];
209 TDB_DATA key;
211 memset(keydata, '\0', sizeof(keydata));
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);
219 return key;
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 *****************************************************************************/
227 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only)
229 TDB_DATA data, key;
230 struct name_record *nr = NULL;
231 struct name_record *namerec = NULL;
233 if (!wins_tdb) {
234 return NULL;
237 key = name_to_key(nmbname);
238 data = tdb_fetch(wins_tdb, key);
240 if (data.dsize == 0) {
241 return NULL;
244 namerec = wins_record_to_name_record(key, data);
246 /* done with the this */
248 SAFE_FREE( data.dptr );
250 if (!namerec) {
251 return NULL;
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;
262 /* Search for this name record on the list. Replace it if found. */
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;
274 DLIST_ADD(wins_server_subnet->namelist, namerec);
275 return namerec;
278 /****************************************************************************
279 Overwrite or add a given name in the wins.tdb.
280 *****************************************************************************/
282 static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
284 TDB_DATA key, data;
285 int ret;
287 if (!wins_tdb) {
288 return False;
291 key = name_to_key(&namerec->name);
292 data = name_record_to_wins_record(namerec);
294 if (data.dptr == NULL) {
295 return False;
298 ret = tdb_store(wins_tdb, key, data, tdb_flag);
300 SAFE_FREE(data.dptr);
301 return (ret == 0) ? True : False;
304 /****************************************************************************
305 Overwrite a given name in the wins.tdb.
306 *****************************************************************************/
308 bool wins_store_changed_namerec(const struct name_record *namerec)
310 return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
313 /****************************************************************************
314 Primary interface into creating and overwriting records in the wins.tdb.
315 *****************************************************************************/
317 bool add_name_to_wins_subnet(const struct name_record *namerec)
319 return store_or_replace_wins_namerec(namerec, TDB_INSERT);
322 /****************************************************************************
323 Delete a given name in the tdb and remove the temporary malloc'ed data struct
324 on the linked list.
325 *****************************************************************************/
327 bool remove_name_from_wins_namelist(struct name_record *namerec)
329 TDB_DATA key;
330 int ret;
332 if (!wins_tdb) {
333 return False;
336 key = name_to_key(&namerec->name);
337 ret = tdb_delete(wins_tdb, key);
339 DLIST_REMOVE(wins_server_subnet->namelist, namerec);
341 /* namerec must be freed by the caller */
343 return (ret == 0) ? True : False;
346 /****************************************************************************
347 Dump out the complete namelist.
348 *****************************************************************************/
350 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
352 struct name_record *namerec = NULL;
353 FILE *fp = (FILE *)state;
355 if (kbuf.dsize != sizeof(unstring) + 1) {
356 return 0;
359 namerec = wins_record_to_name_record(kbuf, dbuf);
360 if (!namerec) {
361 return 0;
364 dump_name_record(namerec, fp);
366 SAFE_FREE(namerec->data.ip);
367 SAFE_FREE(namerec);
368 return 0;
371 void dump_wins_subnet_namelist(FILE *fp)
373 tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
376 /****************************************************************************
377 Change the wins owner address in the record.
378 *****************************************************************************/
380 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
382 namerec->data.wins_ip=wins_ip;
385 /****************************************************************************
386 Create the wins flags based on the nb flags and the input value.
387 *****************************************************************************/
389 static void update_wins_flag(struct name_record *namerec, int flags)
391 namerec->data.wins_flags=0x0;
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;
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;
413 /* the node type are the same bits */
414 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
416 /* the static bit is elsewhere */
417 if (namerec->data.death_time == PERMANENT_TTL) {
418 namerec->data.wins_flags|=WINS_STATIC;
421 /* and add the given bits */
422 namerec->data.wins_flags|=flags;
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));
428 /****************************************************************************
429 Return the general ID value and increase it if requested.
430 *****************************************************************************/
432 static void get_global_id_and_update(uint64_t *current_id, bool update)
435 * it's kept as a static here, to prevent people from messing
436 * with the value directly
439 static uint64_t general_id = 1;
441 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
443 *current_id = general_id;
445 if (update) {
446 general_id++;
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 *****************************************************************************/
455 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
457 const struct loadparm_substitution *lp_sub =
458 loadparm_s3_global_substitution();
459 char *command = NULL;
460 char *cmd = lp_wins_hook(talloc_tos(), lp_sub);
461 char *p, *namestr;
462 int i;
463 TALLOC_CTX *ctx = talloc_tos();
465 wins_store_changed_namerec(namerec);
467 if (!cmd || !*cmd) {
468 return;
471 for (p=namerec->name.name; *p; p++) {
472 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
473 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
474 return;
478 /* Use the name without the nametype (and scope) appended */
480 namestr = nmb_namestr(&namerec->name);
481 if ((p = strchr(namestr, '<'))) {
482 *p = 0;
485 command = talloc_asprintf(ctx,
486 "%s %s %s %02x %d",
487 cmd,
488 operation,
489 namestr,
490 namerec->name.name_type,
491 ttl);
492 if (!command) {
493 return;
496 for (i=0;i<namerec->data.num_ips;i++) {
497 command = talloc_asprintf_append(command,
498 " %s",
499 inet_ntoa(namerec->data.ip[i]));
500 if (!command) {
501 return;
505 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
506 smbrun(command, NULL, NULL);
507 TALLOC_FREE(command);
510 /****************************************************************************
511 Determine if this packet should be allocated to the WINS server.
512 *****************************************************************************/
514 bool packet_is_for_wins_server(struct packet_struct *packet)
516 struct nmb_packet *nmb = &packet->packet.nmb;
518 /* Only unicast packets go to a WINS server. */
519 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
520 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
521 return False;
524 /* Check for node status requests. */
525 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
526 return False;
529 switch(nmb->header.opcode) {
531 * A WINS server issues WACKS, not receives them.
533 case NMB_WACK_OPCODE:
534 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
535 return False;
537 * A WINS server only processes registration and
538 * release requests, not responses.
540 case NMB_NAME_REG_OPCODE:
541 case NMB_NAME_MULTIHOMED_REG_OPCODE:
542 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
543 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
544 if(nmb->header.response) {
545 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
546 return False;
548 break;
550 case NMB_NAME_RELEASE_OPCODE:
551 if(nmb->header.response) {
552 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
553 return False;
555 break;
558 * Only process unicast name queries with rd = 1.
560 case NMB_NAME_QUERY_OPCODE:
561 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
562 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
563 return False;
565 break;
568 return True;
571 /****************************************************************************
572 Utility function to decide what ttl to give a register/refresh request.
573 *****************************************************************************/
575 static int get_ttl_from_packet(struct nmb_packet *nmb)
577 int ttl = nmb->additional->ttl;
579 if (ttl < lp_min_wins_ttl()) {
580 ttl = lp_min_wins_ttl();
583 if (ttl > lp_max_wins_ttl()) {
584 ttl = lp_max_wins_ttl();
587 return ttl;
590 /****************************************************************************
591 Load or create the WINS database.
592 *****************************************************************************/
594 bool initialise_wins(void)
596 time_t time_now = time(NULL);
597 FILE *fp;
598 char line[1024];
599 char *db_path;
600 char *list_path;
602 if(!lp_we_are_a_wins_server()) {
603 return True;
606 db_path = state_path(talloc_tos(), "wins.tdb");
607 if (db_path == NULL) {
608 return false;
611 /* Open the wins.tdb. */
612 wins_tdb = tdb_open_log(db_path, 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
613 O_CREAT|O_RDWR, 0600);
614 TALLOC_FREE(db_path);
615 if (!wins_tdb) {
616 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
617 strerror(errno) ));
618 return False;
621 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
623 add_samba_names_to_subnet(wins_server_subnet);
625 list_path = state_path(talloc_tos(), WINS_LIST);
626 if (list_path == NULL) {
627 tdb_close(wins_tdb);
628 return false;
631 fp = fopen(list_path, "r");
632 TALLOC_FREE(list_path);
633 if (fp == NULL) {
634 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
635 WINS_LIST, strerror(errno) ));
636 return True;
639 while (!feof(fp)) {
640 char *name_str = NULL;
641 char *ip_str = NULL;
642 char *ttl_str = NULL, *nb_flags_str = NULL;
643 unsigned int num_ips;
644 char *name = NULL;
645 struct in_addr *ip_list = NULL;
646 int type = 0;
647 int nb_flags;
648 int ttl;
649 const char *ptr;
650 char *p = NULL;
651 bool got_token;
652 bool was_ip;
653 int i;
654 unsigned int hash;
655 int version;
656 TALLOC_CTX *frame = NULL;
658 /* Read a line from the wins.dat file. Strips whitespace
659 from the beginning and end of the line. */
660 if (!fgets_slash(NULL, line, sizeof(line), fp)) {
661 continue;
664 if (*line == '#') {
665 continue;
668 if (strncmp(line,"VERSION ", 8) == 0) {
669 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
670 version != WINS_VERSION) {
671 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
672 fclose(fp);
673 return True;
675 continue;
678 ptr = line;
681 * Now we handle multiple IP addresses per name we need
682 * to iterate over the line twice. The first time to
683 * determine how many IP addresses there are, the second
684 * time to actually parse them into the ip_list array.
687 frame = talloc_stackframe();
688 if (!next_token_talloc(frame,&ptr,&name_str,NULL)) {
689 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
690 TALLOC_FREE(frame);
691 continue;
694 if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) {
695 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
696 TALLOC_FREE(frame);
697 continue;
701 * Determine the number of IP addresses per line.
703 num_ips = 0;
704 do {
705 got_token = next_token_talloc(frame,&ptr,&ip_str,NULL);
706 was_ip = False;
708 if(got_token && strchr(ip_str, '.')) {
709 num_ips++;
710 was_ip = True;
712 } while(got_token && was_ip);
714 if(num_ips == 0) {
715 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
716 TALLOC_FREE(frame);
717 continue;
720 if(!got_token) {
721 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
722 TALLOC_FREE(frame);
723 continue;
726 /* Allocate the space for the ip_list. */
727 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
728 DEBUG(0,("initialise_wins: Malloc fail !\n"));
729 fclose(fp);
730 TALLOC_FREE(frame);
731 return False;
734 /* Reset and re-parse the line. */
735 ptr = line;
736 next_token_talloc(frame,&ptr,&name_str,NULL);
737 next_token_talloc(frame,&ptr,&ttl_str,NULL);
738 for(i = 0; i < num_ips; i++) {
739 next_token_talloc(frame,&ptr, &ip_str, NULL);
740 ip_list[i] = interpret_addr2(ip_str);
742 next_token_talloc(frame,&ptr,&nb_flags_str,NULL);
745 * Deal with SELF or REGISTER name encoding. Default is REGISTER
746 * for compatibility with old nmbds.
749 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
750 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
751 SAFE_FREE(ip_list);
752 TALLOC_FREE(frame);
753 continue;
756 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
757 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
760 /* Netbios name. # divides the name from the type (hex): netbios#xx */
761 name = name_str;
763 if((p = strchr(name,'#')) != NULL) {
764 *p = 0;
765 sscanf(p+1,"%x",&type);
768 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
769 sscanf(nb_flags_str,"%x",&nb_flags);
770 sscanf(ttl_str,"%d",&ttl);
772 /* add all entries that have 60 seconds or more to live */
773 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
774 if(ttl != PERMANENT_TTL) {
775 ttl -= time_now;
778 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
779 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
781 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
782 ttl, REGISTER_NAME, num_ips, ip_list );
783 } else {
784 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
785 "%s#%02x ttl = %d first IP %s flags = %2x\n",
786 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
789 TALLOC_FREE(frame);
790 SAFE_FREE(ip_list);
793 fclose(fp);
794 return True;
797 /****************************************************************************
798 Send a WINS WACK (Wait ACKnowledgement) response.
799 **************************************************************************/
801 static void send_wins_wack_response(int ttl, struct packet_struct *p)
803 struct nmb_packet *nmb = &p->packet.nmb;
804 unsigned char rdata[2];
806 rdata[0] = rdata[1] = 0;
808 /* Taken from nmblib.c - we need to send back almost
809 identical bytes from the requesting packet header. */
811 rdata[0] = (nmb->header.opcode & 0xF) << 3;
812 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
813 rdata[0] |= 0x4;
815 if (nmb->header.nm_flags.trunc) {
816 rdata[0] |= 0x2;
818 if (nmb->header.nm_flags.recursion_desired) {
819 rdata[0] |= 0x1;
821 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
822 rdata[1] |= 0x80;
824 if (nmb->header.nm_flags.bcast) {
825 rdata[1] |= 0x10;
828 reply_netbios_packet(p, /* Packet to reply to. */
829 0, /* Result code. */
830 NMB_WAIT_ACK, /* nmbd type code. */
831 NMB_WACK_OPCODE, /* opcode. */
832 ttl, /* ttl. */
833 (char *)rdata, /* data to send. */
834 2); /* data length. */
837 /****************************************************************************
838 Send a WINS name registration response.
839 **************************************************************************/
841 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
843 struct nmb_packet *nmb = &p->packet.nmb;
844 char rdata[6];
846 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
848 reply_netbios_packet(p, /* Packet to reply to. */
849 rcode, /* Result code. */
850 WINS_REG, /* nmbd type code. */
851 NMB_NAME_REG_OPCODE, /* opcode. */
852 ttl, /* ttl. */
853 rdata, /* data to send. */
854 6); /* data length. */
857 /***********************************************************************
858 Deal with a name refresh request to a WINS server.
859 ************************************************************************/
861 void wins_process_name_refresh_request( struct subnet_record *subrec,
862 struct packet_struct *p )
864 struct nmb_packet *nmb = &p->packet.nmb;
865 struct nmb_name *question = &nmb->question.question_name;
866 bool bcast = nmb->header.nm_flags.bcast;
867 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
868 bool group = (nb_flags & NB_GROUP) ? True : False;
869 struct name_record *namerec = NULL;
870 int ttl = get_ttl_from_packet(nmb);
871 struct in_addr from_ip;
872 struct in_addr our_fake_ip;
874 our_fake_ip = interpret_addr2("0.0.0.0");
875 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
877 if(bcast) {
879 * We should only get unicast name refresh packets here.
880 * Anyone trying to refresh broadcast should not be going
881 * to a WINS server. Log an error here.
883 if( DEBUGLVL( 0 ) ) {
884 dbgtext( "wins_process_name_refresh_request: " );
885 dbgtext( "Broadcast name refresh request received " );
886 dbgtext( "for name %s ", nmb_namestr(question) );
887 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
888 dbgtext( "on subnet %s. ", subrec->subnet_name );
889 dbgtext( "Error - Broadcasts should not be sent " );
890 dbgtext( "to a WINS server\n" );
892 return;
895 if( DEBUGLVL( 3 ) ) {
896 dbgtext( "wins_process_name_refresh_request: " );
897 dbgtext( "Name refresh for name %s IP %s\n",
898 nmb_namestr(question), inet_ntoa(from_ip) );
902 * See if the name already exists.
903 * If not, handle it as a name registration and return.
905 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
908 * If this is a refresh request and the name doesn't exist then
909 * treat it like a registration request. This allows us to recover
910 * from errors (tridge)
912 if(namerec == NULL) {
913 if( DEBUGLVL( 3 ) ) {
914 dbgtext( "wins_process_name_refresh_request: " );
915 dbgtext( "Name refresh for name %s ",
916 nmb_namestr( question ) );
917 dbgtext( "and the name does not exist. Treating " );
918 dbgtext( "as registration.\n" );
920 wins_process_name_registration_request(subrec,p);
921 return;
925 * if the name is present but not active, simply remove it
926 * and treat the refresh request as a registration & return.
928 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
929 if( DEBUGLVL( 5 ) ) {
930 dbgtext( "wins_process_name_refresh_request: " );
931 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
932 dbgtext( "was not active - removing it.\n" );
934 remove_name_from_namelist( subrec, namerec );
935 namerec = NULL;
936 wins_process_name_registration_request( subrec, p );
937 return;
941 * Check that the group bits for the refreshing name and the
942 * name in our database match. If not, refuse the refresh.
943 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
945 if( (namerec != NULL) &&
946 ( (group && !NAME_GROUP(namerec))
947 || (!group && NAME_GROUP(namerec)) ) ) {
948 if( DEBUGLVL( 3 ) ) {
949 dbgtext( "wins_process_name_refresh_request: " );
950 dbgtext( "Name %s ", nmb_namestr(question) );
951 dbgtext( "group bit = %s does not match ",
952 group ? "True" : "False" );
953 dbgtext( "group bit in WINS for this name.\n" );
955 send_wins_name_registration_response(RFS_ERR, 0, p);
956 return;
960 * For a unique name check that the person refreshing the name is
961 * one of the registered IP addresses. If not - fail the refresh.
962 * Do the same for group names with a type of 0x1c.
963 * Just return success for unique 0x1d refreshes. For normal group
964 * names update the ttl and return success.
966 if( (!group || (group && (question->name_type == 0x1c)))
967 && find_ip_in_name_record(namerec, from_ip) ) {
969 * Update the ttl.
971 update_name_ttl(namerec, ttl);
974 * if the record is a replica:
975 * we take ownership and update the version ID.
977 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
978 update_wins_owner(namerec, our_fake_ip);
979 get_global_id_and_update(&namerec->data.id, True);
982 send_wins_name_registration_response(0, ttl, p);
983 wins_hook("refresh", namerec, ttl);
984 return;
985 } else if((group && (question->name_type == 0x1c))) {
987 * Added by crh for bug #1079.
988 * Fix from Bert Driehuis
990 if( DEBUGLVL( 3 ) ) {
991 dbgtext( "wins_process_name_refresh_request: " );
992 dbgtext( "Name refresh for name %s, ",
993 nmb_namestr(question) );
994 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
995 dbgtext( "is not yet associated with " );
996 dbgtext( "that name. Treating as registration.\n" );
998 wins_process_name_registration_request(subrec,p);
999 return;
1000 } else if(group) {
1002 * Normal groups are all registered with an IP address of
1003 * 255.255.255.255 so we can't search for the IP address.
1005 update_name_ttl(namerec, ttl);
1006 wins_hook("refresh", namerec, ttl);
1007 send_wins_name_registration_response(0, ttl, p);
1008 return;
1009 } else if(!group && (question->name_type == 0x1d)) {
1011 * Special name type - just pretend the refresh succeeded.
1013 send_wins_name_registration_response(0, ttl, p);
1014 return;
1015 } else {
1017 * Fail the refresh.
1019 if( DEBUGLVL( 3 ) ) {
1020 dbgtext( "wins_process_name_refresh_request: " );
1021 dbgtext( "Name refresh for name %s with IP %s ",
1022 nmb_namestr(question), inet_ntoa(from_ip) );
1023 dbgtext( "and is IP is not known to the name.\n" );
1025 send_wins_name_registration_response(RFS_ERR, 0, p);
1026 return;
1030 /***********************************************************************
1031 Deal with a name registration request query success to a client that
1032 owned the name.
1034 We have a locked pointer to the original packet stashed away in the
1035 userdata pointer. The success here is actually a failure as it means
1036 the client we queried wants to keep the name, so we must return
1037 a registration failure to the original requester.
1038 ************************************************************************/
1040 static void wins_register_query_success(struct subnet_record *subrec,
1041 struct userdata_struct *userdata,
1042 struct nmb_name *question_name,
1043 struct in_addr ip,
1044 struct res_rec *answers)
1046 struct packet_struct *orig_reg_packet;
1048 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1050 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1051 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
1053 send_wins_name_registration_response(ACT_ERR, 0, orig_reg_packet);
1055 orig_reg_packet->locked = False;
1056 free_packet(orig_reg_packet);
1059 /***********************************************************************
1060 Deal with a name registration request query failure to a client that
1061 owned the name.
1063 We have a locked pointer to the original packet stashed away in the
1064 userdata pointer. The failure here is actually a success as it means
1065 the client we queried didn't want to keep the name, so we can remove
1066 the old name record and then successfully add the new name.
1067 ************************************************************************/
1069 static void wins_register_query_fail(struct subnet_record *subrec,
1070 struct response_record *rrec,
1071 struct nmb_name *question_name,
1072 int rcode)
1074 struct userdata_struct *userdata = rrec->userdata;
1075 struct packet_struct *orig_reg_packet;
1076 struct name_record *namerec = NULL;
1078 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1081 * We want to just add the name, as we now know the original owner
1082 * didn't want it. But we can't just do that as an arbitrary
1083 * amount of time may have taken place between the name query
1084 * request and this timeout/error response. So we check that
1085 * the name still exists and is in the same state - if so
1086 * we remove it and call wins_process_name_registration_request()
1087 * as we know it will do the right thing now.
1090 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1092 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1093 ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1094 remove_name_from_namelist( subrec, namerec);
1095 namerec = NULL;
1098 if(namerec == NULL) {
1099 wins_process_name_registration_request(subrec, orig_reg_packet);
1100 } else {
1101 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1102 "querying for name %s in order to replace it and this reply.\n",
1103 nmb_namestr(question_name) ));
1106 orig_reg_packet->locked = False;
1107 free_packet(orig_reg_packet);
1110 /***********************************************************************
1111 Deal with a name registration request to a WINS server.
1113 Use the following pseudocode :
1115 registering_group
1118 +--------name exists
1121 | +--- existing name is group
1122 | | |
1123 | | |
1124 | | +--- add name (return).
1127 | +--- exiting name is unique
1130 | +--- query existing owner (return).
1133 +--------name doesn't exist
1136 +--- add name (return).
1138 registering_unique
1141 +--------name exists
1144 | +--- existing name is group
1145 | | |
1146 | | |
1147 | | +--- fail add (return).
1148 | |
1150 | +--- exiting name is unique
1153 | +--- query existing owner (return).
1156 +--------name doesn't exist
1159 +--- add name (return).
1161 As can be seen from the above, the two cases may be collapsed onto each
1162 other with the exception of the case where the name already exists and
1163 is a group name. This case we handle with an if statement.
1165 ************************************************************************/
1167 void wins_process_name_registration_request(struct subnet_record *subrec,
1168 struct packet_struct *p)
1170 unstring name;
1171 struct nmb_packet *nmb = &p->packet.nmb;
1172 struct nmb_name *question = &nmb->question.question_name;
1173 bool bcast = nmb->header.nm_flags.bcast;
1174 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
1175 int ttl = get_ttl_from_packet(nmb);
1176 struct name_record *namerec = NULL;
1177 struct in_addr from_ip;
1178 bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1179 struct in_addr our_fake_ip;
1181 our_fake_ip = interpret_addr2("0.0.0.0");
1182 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1184 if(bcast) {
1186 * We should only get unicast name registration packets here.
1187 * Anyone trying to register broadcast should not be going to a WINS
1188 * server. Log an error here.
1191 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1192 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1193 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1194 return;
1197 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1198 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1201 * See if the name already exists.
1204 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1207 * if the record exists but NOT in active state,
1208 * consider it dead.
1210 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1211 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1212 not active - removing it.\n", nmb_namestr(question) ));
1213 remove_name_from_namelist( subrec, namerec );
1214 namerec = NULL;
1218 * Deal with the case where the name found was a dns entry.
1219 * Remove it as we now have a NetBIOS client registering the
1220 * name.
1223 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1224 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1225 a dns lookup - removing it.\n", nmb_namestr(question) ));
1226 remove_name_from_namelist( subrec, namerec );
1227 namerec = NULL;
1231 * Reject if the name exists and is not a REGISTER_NAME.
1232 * (ie. Don't allow any static names to be overwritten.
1235 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1236 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1237 to register name %s. Name already exists in WINS with source type %d.\n",
1238 nmb_namestr(question), namerec->data.source ));
1239 send_wins_name_registration_response(RFS_ERR, 0, p);
1240 return;
1244 * Special policy decisions based on MS documentation.
1245 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1246 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1250 * A group name is always added as the local broadcast address, except
1251 * for group names ending in 0x1c.
1252 * Group names with type 0x1c are registered with individual IP addresses.
1255 if(registering_group_name && (question->name_type != 0x1c)) {
1256 from_ip = interpret_addr2("255.255.255.255");
1260 * Ignore all attempts to register a unique 0x1d name, although return success.
1263 if(!registering_group_name && (question->name_type == 0x1d)) {
1264 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1265 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1266 send_wins_name_registration_response(0, ttl, p);
1267 return;
1271 * Next two cases are the 'if statement' mentioned above.
1274 if((namerec != NULL) && NAME_GROUP(namerec)) {
1275 if(registering_group_name) {
1277 * If we are adding a group name, the name exists and is also a group entry just add this
1278 * IP address to it and update the ttl.
1281 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1282 inet_ntoa(from_ip), nmb_namestr(question) ));
1285 * Check the ip address is not already in the group.
1288 if(!find_ip_in_name_record(namerec, from_ip)) {
1290 * Need to emulate the behaviour of Windows, as
1291 * described in:
1292 * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1293 * (is there an MS reference for this
1294 * somewhere?) because if the 1c list gets over
1295 * 86 entries, the reply packet is too big
1296 * (rdata>576 bytes) so no reply is sent.
1298 * Keep only the "latest" 25 records, while
1299 * ensuring that the PDC (0x1b) is never removed
1300 * We do this by removing the first entry that
1301 * isn't the 1b entry for the same name,
1302 * on the grounds that insertion is at the end
1303 * of the list, so the oldest entries are at
1304 * the start.
1307 while(namerec->data.num_ips>=25) {
1308 struct name_record *name1brec = NULL;
1310 /* We only do this for 1c types. */
1311 if (namerec->name.name_type != 0x1c) {
1312 break;
1314 DEBUG(3,("wins_process_name_registration_request: "
1315 "More than 25 IPs already in "
1316 "the list. Looking for a 1b "
1317 "record\n"));
1319 /* Ensure we have all the active 1b
1320 * names on the list. */
1321 wins_delete_all_1b_in_memory_records();
1322 fetch_all_active_wins_1b_names();
1324 /* Per the above, find the 1b record,
1325 and then remove the first IP that isn't the same */
1326 for(name1brec = subrec->namelist;
1327 name1brec;
1328 name1brec = name1brec->next ) {
1329 if( WINS_STATE_ACTIVE(name1brec) &&
1330 name1brec->name.name_type == 0x1b) {
1331 DEBUG(3,("wins_process_name_registration_request: "
1332 "Found the #1b record "
1333 "with ip %s\n",
1334 inet_ntoa(name1brec->data.ip[0])));
1335 break;
1338 if(!name1brec) {
1339 DEBUG(3,("wins_process_name_registration_request: "
1340 "Didn't find a #1b name record. "
1341 "Removing the first available "
1342 "entry %s\n",
1343 inet_ntoa(namerec->data.ip[0])));
1344 remove_ip_from_name_record(namerec, namerec->data.ip[0]);
1345 wins_hook("delete", namerec, 0);
1346 } else {
1347 int i;
1348 for(i=0; i<namerec->data.num_ips; i++) {
1349 /* The name1brec should only have
1350 * the single IP address in it,
1351 * so we only check against the first one*/
1352 if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) {
1353 /* The i'th entry isn't the 1b address; delete it */
1354 DEBUG(3,("wins_process_name_registration_request: "
1355 "Entry at %d is not the #1b address. "
1356 "About to remove it\n",
1357 i));
1358 remove_ip_from_name_record(namerec, namerec->data.ip[i]);
1359 wins_hook("delete", namerec, 0);
1360 break;
1365 /* The list is guaranteed to be < 25 entries now
1366 * - safe to add a new one */
1367 add_ip_to_name_record(namerec, from_ip);
1368 /* we need to update the record for replication */
1369 get_global_id_and_update(&namerec->data.id, True);
1372 * if the record is a replica, we must change
1373 * the wins owner to us to make the replication updates
1374 * it on the other wins servers.
1375 * And when the partner will receive this record,
1376 * it will update its own record.
1379 update_wins_owner(namerec, our_fake_ip);
1381 update_name_ttl(namerec, ttl);
1382 wins_hook("refresh", namerec, ttl);
1383 send_wins_name_registration_response(0, ttl, p);
1384 return;
1385 } else {
1388 * If we are adding a unique name, the name exists in the WINS db
1389 * and is a group name then reject the registration.
1391 * explanation: groups have a higher priority than unique names.
1394 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1395 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1396 send_wins_name_registration_response(RFS_ERR, 0, p);
1397 return;
1402 * From here on down we know that if the name exists in the WINS db it is
1403 * a unique name, not a group name.
1407 * If the name exists and is one of our names then check the
1408 * registering IP address. If it's not one of ours then automatically
1409 * reject without doing the query - we know we will reject it.
1412 if ( namerec != NULL ) {
1413 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1414 if( is_myname(name) ) {
1415 if(!ismyip_v4(from_ip)) {
1416 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1417 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1418 send_wins_name_registration_response(RFS_ERR, 0, p);
1419 return;
1420 } else {
1422 * It's one of our names and one of our IP's - update the ttl.
1424 update_name_ttl(namerec, ttl);
1425 wins_hook("refresh", namerec, ttl);
1426 send_wins_name_registration_response(0, ttl, p);
1427 return;
1430 } else {
1431 name[0] = '\0';
1435 * If the name exists and it is a unique registration and the registering IP
1436 * is the same as the (single) already registered IP then just update the ttl.
1438 * But not if the record is an active replica. IF it's a replica, it means it can be
1439 * the same client which has moved and not yet expired. So we don't update
1440 * the ttl in this case and go beyond to do a WACK and query the old client
1443 if( !registering_group_name
1444 && (namerec != NULL)
1445 && (namerec->data.num_ips == 1)
1446 && ip_equal_v4( namerec->data.ip[0], from_ip )
1447 && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1448 update_name_ttl( namerec, ttl );
1449 wins_hook("refresh", namerec, ttl);
1450 send_wins_name_registration_response( 0, ttl, p );
1451 return;
1455 * Finally if the name exists do a query to the registering machine
1456 * to see if they still claim to have the name.
1459 if( namerec != NULL ) {
1460 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1461 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1464 * First send a WACK to the registering machine.
1467 send_wins_wack_response(60, p);
1470 * When the reply comes back we need the original packet.
1471 * Lock this so it won't be freed and then put it into
1472 * the userdata structure.
1475 p->locked = True;
1477 userdata = (struct userdata_struct *)ud;
1479 userdata->copy_fn = NULL;
1480 userdata->free_fn = NULL;
1481 userdata->userdata_len = sizeof(struct packet_struct *);
1482 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1485 * Use the new call to send a query directly to an IP address.
1486 * This sends the query directly to the IP address, and ensures
1487 * the recursion desired flag is not set (you were right Luke :-).
1488 * This function should *only* be called from the WINS server
1489 * code. JRA.
1492 pull_ascii_nstring(name, sizeof(name), question->name);
1493 query_name_from_wins_server( *namerec->data.ip,
1494 name,
1495 question->name_type,
1496 wins_register_query_success,
1497 wins_register_query_fail,
1498 userdata );
1499 return;
1503 * Name did not exist - add it.
1506 pull_ascii_nstring(name, sizeof(name), question->name);
1507 add_name_to_subnet( subrec, name, question->name_type,
1508 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1510 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1511 get_global_id_and_update(&namerec->data.id, True);
1512 update_wins_owner(namerec, our_fake_ip);
1513 update_wins_flag(namerec, WINS_ACTIVE);
1514 wins_hook("add", namerec, ttl);
1517 send_wins_name_registration_response(0, ttl, p);
1520 /***********************************************************************
1521 Deal with a mutihomed name query success to the machine that
1522 requested the multihomed name registration.
1524 We have a locked pointer to the original packet stashed away in the
1525 userdata pointer.
1526 ************************************************************************/
1528 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1529 struct userdata_struct *userdata,
1530 struct nmb_name *question_name,
1531 struct in_addr ip,
1532 struct res_rec *answers)
1534 struct packet_struct *orig_reg_packet;
1535 struct nmb_packet *nmb;
1536 struct name_record *namerec = NULL;
1537 struct in_addr from_ip;
1538 int ttl;
1539 struct in_addr our_fake_ip;
1541 our_fake_ip = interpret_addr2("0.0.0.0");
1542 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1544 nmb = &orig_reg_packet->packet.nmb;
1546 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1547 ttl = get_ttl_from_packet(nmb);
1550 * We want to just add the new IP, as we now know the requesting
1551 * machine claims to own it. But we can't just do that as an arbitrary
1552 * amount of time may have taken place between the name query
1553 * request and this response. So we check that
1554 * the name still exists and is in the same state - if so
1555 * we just add the extra IP and update the ttl.
1558 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1560 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1561 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1562 a subsequent IP address.\n", nmb_namestr(question_name) ));
1563 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1565 orig_reg_packet->locked = False;
1566 free_packet(orig_reg_packet);
1568 return;
1571 if(!find_ip_in_name_record(namerec, from_ip)) {
1572 add_ip_to_name_record(namerec, from_ip);
1575 get_global_id_and_update(&namerec->data.id, True);
1576 update_wins_owner(namerec, our_fake_ip);
1577 update_wins_flag(namerec, WINS_ACTIVE);
1578 update_name_ttl(namerec, ttl);
1579 wins_hook("add", namerec, ttl);
1580 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1582 orig_reg_packet->locked = False;
1583 free_packet(orig_reg_packet);
1586 /***********************************************************************
1587 Deal with a name registration request query failure to a client that
1588 owned the name.
1590 We have a locked pointer to the original packet stashed away in the
1591 userdata pointer.
1592 ************************************************************************/
1594 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1595 struct response_record *rrec,
1596 struct nmb_name *question_name,
1597 int rcode)
1599 struct userdata_struct *userdata = rrec->userdata;
1600 struct packet_struct *orig_reg_packet;
1602 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1604 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1605 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1606 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1608 orig_reg_packet->locked = False;
1609 free_packet(orig_reg_packet);
1610 return;
1613 /***********************************************************************
1614 Deal with a multihomed name registration request to a WINS server.
1615 These cannot be group name registrations.
1616 ***********************************************************************/
1618 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1619 struct packet_struct *p)
1621 struct nmb_packet *nmb = &p->packet.nmb;
1622 struct nmb_name *question = &nmb->question.question_name;
1623 bool bcast = nmb->header.nm_flags.bcast;
1624 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
1625 int ttl = get_ttl_from_packet(nmb);
1626 struct name_record *namerec = NULL;
1627 struct in_addr from_ip;
1628 bool group = (nb_flags & NB_GROUP) ? True : False;
1629 struct in_addr our_fake_ip;
1630 unstring qname;
1632 our_fake_ip = interpret_addr2("0.0.0.0");
1633 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1635 if(bcast) {
1637 * We should only get unicast name registration packets here.
1638 * Anyone trying to register broadcast should not be going to a WINS
1639 * server. Log an error here.
1642 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1643 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1644 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1645 return;
1649 * Only unique names should be registered multihomed.
1652 if(group) {
1653 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1654 received for name %s from IP %s on subnet %s. Error - group names should not be multihomed.\n",
1655 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1656 return;
1659 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1660 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1663 * Deal with policy regarding 0x1d names.
1666 if(question->name_type == 0x1d) {
1667 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1668 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1669 send_wins_name_registration_response(0, ttl, p);
1670 return;
1674 * See if the name already exists.
1677 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1680 * if the record exists but NOT in active state,
1681 * consider it dead.
1684 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1685 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1686 remove_name_from_namelist(subrec, namerec);
1687 namerec = NULL;
1691 * Deal with the case where the name found was a dns entry.
1692 * Remove it as we now have a NetBIOS client registering the
1693 * name.
1696 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1697 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1698 - removing it.\n", nmb_namestr(question) ));
1699 remove_name_from_namelist( subrec, namerec);
1700 namerec = NULL;
1704 * Reject if the name exists and is not a REGISTER_NAME.
1705 * (ie. Don't allow any static names to be overwritten.
1708 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1709 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1710 to register name %s. Name already exists in WINS with source type %d.\n",
1711 nmb_namestr(question), namerec->data.source ));
1712 send_wins_name_registration_response(RFS_ERR, 0, p);
1713 return;
1717 * Reject if the name exists and is a GROUP name and is active.
1720 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1721 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1722 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1723 send_wins_name_registration_response(RFS_ERR, 0, p);
1724 return;
1728 * From here on down we know that if the name exists in the WINS db it is
1729 * a unique name, not a group name.
1733 * If the name exists and is one of our names then check the
1734 * registering IP address. If it's not one of ours then automatically
1735 * reject without doing the query - we know we will reject it.
1738 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1739 if(!ismyip_v4(from_ip)) {
1740 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1741 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1742 send_wins_name_registration_response(RFS_ERR, 0, p);
1743 return;
1744 } else {
1746 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1747 * update the ttl. Update the version ID to force replication.
1749 update_name_ttl(namerec, ttl);
1751 if(!find_ip_in_name_record(namerec, from_ip)) {
1752 get_global_id_and_update(&namerec->data.id, True);
1753 update_wins_owner(namerec, our_fake_ip);
1754 update_wins_flag(namerec, WINS_ACTIVE);
1756 add_ip_to_name_record(namerec, from_ip);
1759 wins_hook("refresh", namerec, ttl);
1760 send_wins_name_registration_response(0, ttl, p);
1761 return;
1766 * If the name exists and is active, check if the IP address is already registered
1767 * to that name. If so then update the ttl and reply success.
1770 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1771 update_name_ttl(namerec, ttl);
1774 * If it's a replica, we need to become the wins owner
1775 * to force the replication
1777 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1778 get_global_id_and_update(&namerec->data.id, True);
1779 update_wins_owner(namerec, our_fake_ip);
1780 update_wins_flag(namerec, WINS_ACTIVE);
1783 wins_hook("refresh", namerec, ttl);
1784 send_wins_name_registration_response(0, ttl, p);
1785 return;
1789 * If the name exists do a query to the owner
1790 * to see if they still want the name.
1793 if(namerec != NULL) {
1794 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1795 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1798 * First send a WACK to the registering machine.
1801 send_wins_wack_response(60, p);
1804 * When the reply comes back we need the original packet.
1805 * Lock this so it won't be freed and then put it into
1806 * the userdata structure.
1809 p->locked = True;
1811 userdata = (struct userdata_struct *)ud;
1813 userdata->copy_fn = NULL;
1814 userdata->free_fn = NULL;
1815 userdata->userdata_len = sizeof(struct packet_struct *);
1816 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1819 * Use the new call to send a query directly to an IP address.
1820 * This sends the query directly to the IP address, and ensures
1821 * the recursion desired flag is not set (you were right Luke :-).
1822 * This function should *only* be called from the WINS server
1823 * code. JRA.
1825 * Note that this packet is sent to the current owner of the name,
1826 * not the person who sent the packet
1829 pull_ascii_nstring( qname, sizeof(qname), question->name);
1830 query_name_from_wins_server( namerec->data.ip[0],
1831 qname,
1832 question->name_type,
1833 wins_multihomed_register_query_success,
1834 wins_multihomed_register_query_fail,
1835 userdata );
1837 return;
1841 * Name did not exist - add it.
1844 pull_ascii_nstring( qname, sizeof(qname), question->name);
1845 add_name_to_subnet( subrec, qname, question->name_type,
1846 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1848 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1849 get_global_id_and_update(&namerec->data.id, True);
1850 update_wins_owner(namerec, our_fake_ip);
1851 update_wins_flag(namerec, WINS_ACTIVE);
1852 wins_hook("add", namerec, ttl);
1855 send_wins_name_registration_response(0, ttl, p);
1858 /***********************************************************************
1859 Fetch all *<1b> names from the WINS db and store on the namelist.
1860 ***********************************************************************/
1862 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1864 struct name_record *namerec = NULL;
1866 if (kbuf.dsize != sizeof(unstring) + 1) {
1867 return 0;
1870 /* Filter out all non-1b names. */
1871 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1872 return 0;
1875 namerec = wins_record_to_name_record(kbuf, dbuf);
1876 if (!namerec) {
1877 return 0;
1880 DLIST_ADD(wins_server_subnet->namelist, namerec);
1881 return 0;
1884 void fetch_all_active_wins_1b_names(void)
1886 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1889 /***********************************************************************
1890 Deal with the special name query for *<1b>.
1891 ***********************************************************************/
1893 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1894 struct packet_struct *p)
1896 struct name_record *namerec = NULL;
1897 char *prdata;
1898 int num_ips;
1901 * Go through all the ACTIVE names in the WINS db looking for those
1902 * ending in <1b>. Use this to calculate the number of IP
1903 * addresses we need to return.
1906 num_ips = 0;
1908 /* First, clear the in memory list - we're going to re-populate
1909 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1911 wins_delete_all_tmp_in_memory_records();
1913 fetch_all_active_wins_1b_names();
1915 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1916 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1917 num_ips += namerec->data.num_ips;
1921 if(num_ips == 0) {
1923 * There are no 0x1b names registered. Return name query fail.
1925 send_wins_name_query_response(NAM_ERR, p, NULL);
1926 return;
1929 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1930 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1931 return;
1935 * Go through all the names again in the WINS db looking for those
1936 * ending in <1b>. Add their IP addresses into the list we will
1937 * return.
1940 num_ips = 0;
1941 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1942 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1943 int i;
1944 for(i = 0; i < namerec->data.num_ips; i++) {
1945 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1946 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1947 num_ips++;
1953 * Send back the reply containing the IP list.
1956 reply_netbios_packet(p, /* Packet to reply to. */
1957 0, /* Result code. */
1958 WINS_QUERY, /* nmbd type code. */
1959 NMB_NAME_QUERY_OPCODE, /* opcode. */
1960 lp_min_wins_ttl(), /* ttl. */
1961 prdata, /* data to send. */
1962 num_ips*6); /* data length. */
1964 SAFE_FREE(prdata);
1967 /****************************************************************************
1968 Send a WINS name query response.
1969 **************************************************************************/
1971 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1972 struct name_record *namerec)
1974 char rdata[6];
1975 char *prdata = rdata;
1976 int reply_data_len = 0;
1977 int ttl = 0;
1978 int i;
1980 memset(rdata,'\0',6);
1982 if(rcode == 0) {
1984 int ip_count;
1986 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1988 /* The netbios reply packet data section is limited to 576 bytes. In theory
1989 * this should give us space for 96 addresses, but in practice, 86 appears
1990 * to be the max (don't know why). If we send any more than that,
1991 * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
1992 * overflow. Keep the count to 85 and it will be ok */
1993 ip_count=namerec->data.num_ips;
1994 if(ip_count>85) {
1995 ip_count=85;
1998 /* Copy all known ip addresses into the return data. */
1999 /* Optimise for the common case of one IP address so we don't need a malloc. */
2001 if( ip_count == 1 ) {
2002 prdata = rdata;
2003 } else {
2004 if((prdata = (char *)SMB_MALLOC( ip_count * 6 )) == NULL) {
2005 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
2006 return;
2010 for(i = 0; i < ip_count; i++) {
2011 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
2012 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
2015 sort_query_replies(prdata, i, p->ip);
2016 reply_data_len = ip_count * 6;
2019 reply_netbios_packet(p, /* Packet to reply to. */
2020 rcode, /* Result code. */
2021 WINS_QUERY, /* nmbd type code. */
2022 NMB_NAME_QUERY_OPCODE, /* opcode. */
2023 ttl, /* ttl. */
2024 prdata, /* data to send. */
2025 reply_data_len); /* data length. */
2027 if(prdata != rdata) {
2028 SAFE_FREE(prdata);
2032 /***********************************************************************
2033 Deal with a name query.
2034 ***********************************************************************/
2036 void wins_process_name_query_request(struct subnet_record *subrec,
2037 struct packet_struct *p)
2039 struct nmb_packet *nmb = &p->packet.nmb;
2040 struct nmb_name *question = &nmb->question.question_name;
2041 struct name_record *namerec = NULL;
2042 unstring qname;
2044 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
2045 nmb_namestr(question), inet_ntoa(p->ip) ));
2048 * Special name code. If the queried name is *<1b> then search
2049 * the entire WINS database and return a list of all the IP addresses
2050 * registered to any <1b> name. This is to allow domain master browsers
2051 * to discover other domains that may not have a presence on their subnet.
2054 pull_ascii_nstring(qname, sizeof(qname), question->name);
2055 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
2056 process_wins_dmb_query_request( subrec, p);
2057 return;
2060 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2062 if(namerec != NULL) {
2064 * If the name is not anymore in active state then reply not found.
2065 * it's fair even if we keep it in the cache for days.
2067 if (!WINS_STATE_ACTIVE(namerec)) {
2068 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2069 nmb_namestr(question) ));
2070 send_wins_name_query_response(NAM_ERR, p, namerec);
2071 return;
2075 * If it's a DNSFAIL_NAME then reply name not found.
2078 if( namerec->data.source == DNSFAIL_NAME ) {
2079 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2080 nmb_namestr(question) ));
2081 send_wins_name_query_response(NAM_ERR, p, namerec);
2082 return;
2086 * If the name has expired then reply name not found.
2089 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
2090 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2091 nmb_namestr(question) ));
2092 send_wins_name_query_response(NAM_ERR, p, namerec);
2093 return;
2096 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2097 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
2099 send_wins_name_query_response(0, p, namerec);
2100 return;
2104 * Name not found in WINS - try a dns query if it's a 0x20 name.
2107 if(lp_wins_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
2108 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2109 nmb_namestr(question) ));
2111 queue_dns_query(p, question);
2112 return;
2116 * Name not found - return error.
2119 send_wins_name_query_response(NAM_ERR, p, NULL);
2122 /****************************************************************************
2123 Send a WINS name release response.
2124 **************************************************************************/
2126 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
2128 struct nmb_packet *nmb = &p->packet.nmb;
2129 char rdata[6];
2131 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
2133 reply_netbios_packet(p, /* Packet to reply to. */
2134 rcode, /* Result code. */
2135 NMB_REL, /* nmbd type code. */
2136 NMB_NAME_RELEASE_OPCODE, /* opcode. */
2137 0, /* ttl. */
2138 rdata, /* data to send. */
2139 6); /* data length. */
2142 /***********************************************************************
2143 Deal with a name release.
2144 ***********************************************************************/
2146 void wins_process_name_release_request(struct subnet_record *subrec,
2147 struct packet_struct *p)
2149 struct nmb_packet *nmb = &p->packet.nmb;
2150 struct nmb_name *question = &nmb->question.question_name;
2151 bool bcast = nmb->header.nm_flags.bcast;
2152 uint16_t nb_flags = get_nb_flags(nmb->additional->rdata);
2153 struct name_record *namerec = NULL;
2154 struct in_addr from_ip;
2155 bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;
2157 putip((char *)&from_ip,&nmb->additional->rdata[2]);
2159 if(bcast) {
2161 * We should only get unicast name registration packets here.
2162 * Anyone trying to register broadcast should not be going to a WINS
2163 * server. Log an error here.
2166 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2167 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2168 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2169 return;
2172 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2173 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2176 * Deal with policy regarding 0x1d names.
2179 if(!releasing_group_name && (question->name_type == 0x1d)) {
2180 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2181 to release name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
2182 send_wins_name_release_response(0, p);
2183 return;
2187 * See if the name already exists.
2190 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2192 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2193 send_wins_name_release_response(NAM_ERR, p);
2194 return;
2198 * Check that the sending machine has permission to release this name.
2199 * If it's a group name not ending in 0x1c then just say yes and let
2200 * the group time out.
2203 if(releasing_group_name && (question->name_type != 0x1c)) {
2204 send_wins_name_release_response(0, p);
2205 return;
2209 * Check that the releasing node is on the list of IP addresses
2210 * for this name. Disallow the release if not.
2213 if(!find_ip_in_name_record(namerec, from_ip)) {
2214 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2215 release name %s as IP %s is not one of the known IP's for this name.\n",
2216 nmb_namestr(question), inet_ntoa(from_ip) ));
2217 send_wins_name_release_response(NAM_ERR, p);
2218 return;
2222 * Check if the record is active. IF it's already released
2223 * or tombstoned, refuse the release.
2226 if (!WINS_STATE_ACTIVE(namerec)) {
2227 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2228 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2229 send_wins_name_release_response(NAM_ERR, p);
2230 return;
2234 * Check if the record is a 0x1c group
2235 * and has more then one ip
2236 * remove only this address.
2239 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2240 remove_ip_from_name_record(namerec, from_ip);
2241 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2242 inet_ntoa(from_ip),nmb_namestr(question)));
2243 wins_hook("delete", namerec, 0);
2244 send_wins_name_release_response(0, p);
2245 return;
2249 * Send a release response.
2250 * Flag the name as released and update the ttl
2253 namerec->data.wins_flags |= WINS_RELEASED;
2254 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2256 wins_hook("delete", namerec, 0);
2257 send_wins_name_release_response(0, p);
2260 /*******************************************************************
2261 WINS time dependent processing.
2262 ******************************************************************/
2264 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2266 time_t t = *(time_t *)state;
2267 bool store_record = False;
2268 struct name_record *namerec = NULL;
2269 struct in_addr our_fake_ip;
2271 our_fake_ip = interpret_addr2("0.0.0.0");
2272 if (kbuf.dsize != sizeof(unstring) + 1) {
2273 return 0;
2276 namerec = wins_record_to_name_record(kbuf, dbuf);
2277 if (!namerec) {
2278 return 0;
2281 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2282 if( namerec->data.source == SELF_NAME ) {
2283 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2284 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2285 namerec->data.death_time += 300;
2286 store_record = True;
2287 goto done;
2288 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2289 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2290 nmb_namestr(&namerec->name)));
2291 remove_name_from_wins_namelist(namerec );
2292 goto done;
2295 /* handle records, samba is the wins owner */
2296 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2297 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2298 case WINS_ACTIVE:
2299 namerec->data.wins_flags&=~WINS_STATE_MASK;
2300 namerec->data.wins_flags|=WINS_RELEASED;
2301 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2302 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2303 nmb_namestr(&namerec->name)));
2304 store_record = True;
2305 goto done;
2306 case WINS_RELEASED:
2307 namerec->data.wins_flags&=~WINS_STATE_MASK;
2308 namerec->data.wins_flags|=WINS_TOMBSTONED;
2309 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2310 get_global_id_and_update(&namerec->data.id, True);
2311 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2312 nmb_namestr(&namerec->name)));
2313 store_record = True;
2314 goto done;
2315 case WINS_TOMBSTONED:
2316 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2317 nmb_namestr(&namerec->name)));
2318 remove_name_from_wins_namelist(namerec );
2319 goto done;
2321 } else {
2322 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2323 case WINS_ACTIVE:
2324 /* that's not as MS says it should be */
2325 namerec->data.wins_flags&=~WINS_STATE_MASK;
2326 namerec->data.wins_flags|=WINS_TOMBSTONED;
2327 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2328 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2329 nmb_namestr(&namerec->name)));
2330 store_record = True;
2331 goto done;
2332 case WINS_TOMBSTONED:
2333 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2334 nmb_namestr(&namerec->name)));
2335 remove_name_from_wins_namelist(namerec );
2336 goto done;
2337 case WINS_RELEASED:
2338 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2339 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2340 goto done;
2345 done:
2347 if (store_record) {
2348 wins_store_changed_namerec(namerec);
2351 SAFE_FREE(namerec->data.ip);
2352 SAFE_FREE(namerec);
2354 return 0;
2357 /*******************************************************************
2358 Time dependent wins processing.
2359 ******************************************************************/
2361 void initiate_wins_processing(time_t t)
2363 static time_t lasttime = 0;
2365 if (!lasttime) {
2366 lasttime = t;
2368 if (t - lasttime < 20) {
2369 return;
2372 if(!lp_we_are_a_wins_server()) {
2373 lasttime = t;
2374 return;
2377 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2379 wins_delete_all_tmp_in_memory_records();
2381 wins_write_database(t, True);
2383 lasttime = t;
2386 /*******************************************************************
2387 Write out one record.
2388 ******************************************************************/
2390 void wins_write_name_record(struct name_record *namerec, FILE *fp)
2392 int i;
2393 struct tm *tm;
2395 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2397 if( namerec->data.death_time != PERMANENT_TTL ) {
2398 char *ts, *nl;
2400 tm = localtime(&namerec->data.death_time);
2401 if (!tm) {
2402 return;
2404 ts = asctime(tm);
2405 if (!ts) {
2406 return;
2408 nl = strrchr( ts, '\n' );
2409 if( NULL != nl ) {
2410 *nl = '\0';
2412 DEBUGADD(4,("TTL = %s ", ts ));
2413 } else {
2414 DEBUGADD(4,("TTL = PERMANENT "));
2417 for (i = 0; i < namerec->data.num_ips; i++) {
2418 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2420 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2422 if( namerec->data.source == REGISTER_NAME ) {
2423 unstring name;
2424 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2425 fprintf(fp, "\"%s#%02x\" %d ", name,
2426 namerec->name.name_type, /* Ignore scope. */
2427 (int)namerec->data.death_time);
2429 for (i = 0; i < namerec->data.num_ips; i++)
2430 fprintf(fp, "%s ", inet_ntoa(namerec->data.ip[i]));
2431 fprintf(fp, "%2xR\n", namerec->data.nb_flags);
2435 /*******************************************************************
2436 Write out the current WINS database.
2437 ******************************************************************/
2439 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2441 struct name_record *namerec = NULL;
2442 FILE *fp = (FILE *)state;
2444 if (kbuf.dsize != sizeof(unstring) + 1) {
2445 return 0;
2448 namerec = wins_record_to_name_record(kbuf, dbuf);
2449 if (!namerec) {
2450 return 0;
2453 wins_write_name_record(namerec, fp);
2455 SAFE_FREE(namerec->data.ip);
2456 SAFE_FREE(namerec);
2457 return 0;
2461 void wins_write_database(time_t t, bool background)
2463 static time_t last_write_time = 0;
2464 char *fname = NULL;
2465 char *fnamenew = NULL;
2467 int fd;
2468 FILE *fp;
2470 if (background) {
2471 if (!last_write_time) {
2472 last_write_time = t;
2474 if (t - last_write_time < 120) {
2475 return;
2480 if(!lp_we_are_a_wins_server()) {
2481 return;
2484 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2485 if (background) {
2486 CatchChild();
2487 if (fork()) {
2488 return;
2490 if (tdb_reopen(wins_tdb)) {
2491 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2492 strerror(errno)));
2493 _exit(0);
2494 return;
2498 if (!(fname = state_path(talloc_tos(), WINS_LIST))) {
2499 goto err_exit;
2501 /* This is safe as the 0 length means "don't expand". */
2502 all_string_sub(fname,"//", "/", 0);
2504 if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)getpid()) < 0) {
2505 goto err_exit;
2508 fd = open(fnamenew, O_WRONLY|O_CREAT, 0644);
2509 if (fd == -1) {
2510 DBG_ERR("Can't open %s: %s\n", fnamenew, strerror(errno));
2511 goto err_exit;
2514 fp = fdopen(fd, "w");
2515 if (fp == NULL) {
2516 DBG_ERR("fdopen failed: %s\n", strerror(errno));
2517 close(fd);
2518 goto err_exit;
2520 fd = -1;
2522 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2524 fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2526 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2528 fclose(fp);
2529 chmod(fnamenew,0644);
2530 unlink(fname);
2531 rename(fnamenew,fname);
2533 err_exit:
2535 SAFE_FREE(fnamenew);
2536 TALLOC_FREE(fname);
2538 if (background) {
2539 _exit(0);
2543 #if 0
2544 Until winsrepl is done.
2545 /****************************************************************************
2546 Process a internal Samba message receiving a wins record.
2547 ***************************************************************************/
2549 void nmbd_wins_new_entry(struct messaging_context *msg,
2550 void *private_data,
2551 uint32_t msg_type,
2552 struct server_id server_id,
2553 DATA_BLOB *data)
2555 WINS_RECORD *record;
2556 struct name_record *namerec = NULL;
2557 struct name_record *new_namerec = NULL;
2558 struct nmb_name question;
2559 bool overwrite=False;
2560 struct in_addr our_fake_ip;
2561 int i;
2563 our_fake_ip = interpret_addr2("0.0.0.0");
2564 if (buf==NULL) {
2565 return;
2568 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2569 record=(WINS_RECORD *)buf;
2571 make_nmb_name(&question, record->name, record->type);
2573 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2575 /* record doesn't exist, add it */
2576 if (namerec == NULL) {
2577 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2578 record->name, record->type, inet_ntoa(record->wins_ip)));
2580 new_namerec=add_name_to_subnet( wins_server_subnet,
2581 record->name,
2582 record->type,
2583 record->nb_flags,
2584 EXTINCTION_INTERVAL,
2585 REGISTER_NAME,
2586 record->num_ips,
2587 record->ip);
2589 if (new_namerec!=NULL) {
2590 update_wins_owner(new_namerec, record->wins_ip);
2591 update_wins_flag(new_namerec, record->wins_flags);
2592 new_namerec->data.id=record->id;
2594 wins_server_subnet->namelist_changed = True;
2598 /* check if we have a conflict */
2599 if (namerec != NULL) {
2600 /* both records are UNIQUE */
2601 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2603 /* the database record is a replica */
2604 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2605 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2606 if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2607 overwrite=True;
2608 } else
2609 overwrite=True;
2610 } else {
2611 /* we are the wins owner of the database record */
2612 /* the 2 records have the same IP address */
2613 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2614 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2615 get_global_id_and_update(&namerec->data.id, True);
2616 else
2617 overwrite=True;
2619 } else {
2620 /* the 2 records have different IP address */
2621 if (namerec->data.wins_flags&WINS_ACTIVE) {
2622 if (record->wins_flags&WINS_TOMBSTONED)
2623 get_global_id_and_update(&namerec->data.id, True);
2624 if (record->wins_flags&WINS_ACTIVE)
2625 /* send conflict challenge to the replica node */
2627 } else
2628 overwrite=True;
2634 /* the replica is a standard group */
2635 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2636 /* if the database record is unique and active force a name release */
2637 if (namerec->data.wins_flags&WINS_UNIQUE)
2638 /* send a release name to the unique node */
2640 overwrite=True;
2644 /* the replica is a special group */
2645 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2646 if (namerec->data.wins_flags&WINS_ACTIVE) {
2647 for (i=0; i<record->num_ips; i++)
2648 if(!find_ip_in_name_record(namerec, record->ip[i]))
2649 add_ip_to_name_record(namerec, record->ip[i]);
2650 } else {
2651 overwrite=True;
2655 /* the replica is a multihomed host */
2657 /* I'm giving up on multi homed. Too much complex to understand */
2659 if (record->wins_flags&WINS_MHOMED) {
2660 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2661 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2662 overwrite=True;
2664 else {
2665 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2666 overwrite=True;
2668 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2669 if (namerec->data.wins_flags&WINS_UNIQUE)
2670 get_global_id_and_update(&namerec->data.id, True);
2674 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2675 if (namerec->data.wins_flags&WINS_UNIQUE ||
2676 namerec->data.wins_flags&WINS_MHOMED)
2677 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2678 overwrite=True;
2682 if (overwrite == False)
2683 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2684 record->name, record->type, inet_ntoa(record->wins_ip)));
2685 else {
2686 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2687 record->name, record->type, inet_ntoa(record->wins_ip)));
2689 /* remove the old record and add a new one */
2690 remove_name_from_namelist( wins_server_subnet, namerec );
2691 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2692 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2693 if (new_namerec!=NULL) {
2694 update_wins_owner(new_namerec, record->wins_ip);
2695 update_wins_flag(new_namerec, record->wins_flags);
2696 new_namerec->data.id=record->id;
2698 wins_server_subnet->namelist_changed = True;
2701 wins_server_subnet->namelist_changed = True;
2706 #endif