s3:smb2_server: remove unused 'sconn' from smbd_smb2_send_break_state
[Samba.git] / source3 / nmbd / nmbd_winsserver.c
blobe09d1a01764afecb3552641377ada3308ab3ba8a
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 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;
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 id_low = (namerec->data.id & 0xFFFFFFFF);
171 uint32 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 *)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)namerec->data.death_time,
188 (uint32)namerec->data.refresh_time,
189 id_low,
190 id_high,
191 (uint32)namerec->data.wins_ip.s_addr,
192 (uint32)namerec->data.wins_flags,
193 (uint32)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 *)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_compat(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 XFILE *fp = (XFILE *)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(XFILE *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 char *command = NULL;
458 char *cmd = lp_wins_hook(talloc_tos());
459 char *p, *namestr;
460 int i;
461 TALLOC_CTX *ctx = talloc_tos();
463 wins_store_changed_namerec(namerec);
465 if (!cmd || !*cmd) {
466 return;
469 for (p=namerec->name.name; *p; p++) {
470 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
471 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
472 return;
476 /* Use the name without the nametype (and scope) appended */
478 namestr = nmb_namestr(&namerec->name);
479 if ((p = strchr(namestr, '<'))) {
480 *p = 0;
483 command = talloc_asprintf(ctx,
484 "%s %s %s %02x %d",
485 cmd,
486 operation,
487 namestr,
488 namerec->name.name_type,
489 ttl);
490 if (!command) {
491 return;
494 for (i=0;i<namerec->data.num_ips;i++) {
495 command = talloc_asprintf_append(command,
496 " %s",
497 inet_ntoa(namerec->data.ip[i]));
498 if (!command) {
499 return;
503 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
504 smbrun(command, NULL);
505 TALLOC_FREE(command);
508 /****************************************************************************
509 Determine if this packet should be allocated to the WINS server.
510 *****************************************************************************/
512 bool packet_is_for_wins_server(struct packet_struct *packet)
514 struct nmb_packet *nmb = &packet->packet.nmb;
516 /* Only unicast packets go to a WINS server. */
517 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
518 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
519 return False;
522 /* Check for node status requests. */
523 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
524 return False;
527 switch(nmb->header.opcode) {
529 * A WINS server issues WACKS, not receives them.
531 case NMB_WACK_OPCODE:
532 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
533 return False;
535 * A WINS server only processes registration and
536 * release requests, not responses.
538 case NMB_NAME_REG_OPCODE:
539 case NMB_NAME_MULTIHOMED_REG_OPCODE:
540 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
541 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
542 if(nmb->header.response) {
543 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
544 return False;
546 break;
548 case NMB_NAME_RELEASE_OPCODE:
549 if(nmb->header.response) {
550 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
551 return False;
553 break;
556 * Only process unicast name queries with rd = 1.
558 case NMB_NAME_QUERY_OPCODE:
559 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
560 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
561 return False;
563 break;
566 return True;
569 /****************************************************************************
570 Utility function to decide what ttl to give a register/refresh request.
571 *****************************************************************************/
573 static int get_ttl_from_packet(struct nmb_packet *nmb)
575 int ttl = nmb->additional->ttl;
577 if (ttl < lp_min_wins_ttl()) {
578 ttl = lp_min_wins_ttl();
581 if (ttl > lp_max_wins_ttl()) {
582 ttl = lp_max_wins_ttl();
585 return ttl;
588 /****************************************************************************
589 Load or create the WINS database.
590 *****************************************************************************/
592 bool initialise_wins(void)
594 time_t time_now = time(NULL);
595 XFILE *fp;
596 char line[1024];
598 if(!lp_we_are_a_wins_server()) {
599 return True;
602 /* Open the wins.tdb. */
603 wins_tdb = tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
604 O_CREAT|O_RDWR, 0600);
605 if (!wins_tdb) {
606 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
607 strerror(errno) ));
608 return False;
611 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
613 add_samba_names_to_subnet(wins_server_subnet);
615 if((fp = x_fopen(state_path(WINS_LIST),O_RDONLY,0)) == NULL) {
616 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
617 WINS_LIST, strerror(errno) ));
618 return True;
621 while (!x_feof(fp)) {
622 char *name_str = NULL;
623 char *ip_str = NULL;
624 char *ttl_str = NULL, *nb_flags_str = NULL;
625 unsigned int num_ips;
626 char *name = NULL;
627 struct in_addr *ip_list = NULL;
628 int type = 0;
629 int nb_flags;
630 int ttl;
631 const char *ptr;
632 char *p = NULL;
633 bool got_token;
634 bool was_ip;
635 int i;
636 unsigned int hash;
637 int version;
638 TALLOC_CTX *frame = NULL;
640 /* Read a line from the wins.dat file. Strips whitespace
641 from the beginning and end of the line. */
642 if (!fgets_slash(line,sizeof(line),fp)) {
643 continue;
646 if (*line == '#') {
647 continue;
650 if (strncmp(line,"VERSION ", 8) == 0) {
651 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
652 version != WINS_VERSION) {
653 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
654 x_fclose(fp);
655 return True;
657 continue;
660 ptr = line;
663 * Now we handle multiple IP addresses per name we need
664 * to iterate over the line twice. The first time to
665 * determine how many IP addresses there are, the second
666 * time to actually parse them into the ip_list array.
669 frame = talloc_stackframe();
670 if (!next_token_talloc(frame,&ptr,&name_str,NULL)) {
671 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
672 TALLOC_FREE(frame);
673 continue;
676 if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) {
677 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
678 TALLOC_FREE(frame);
679 continue;
683 * Determine the number of IP addresses per line.
685 num_ips = 0;
686 do {
687 got_token = next_token_talloc(frame,&ptr,&ip_str,NULL);
688 was_ip = False;
690 if(got_token && strchr(ip_str, '.')) {
691 num_ips++;
692 was_ip = True;
694 } while(got_token && was_ip);
696 if(num_ips == 0) {
697 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
698 TALLOC_FREE(frame);
699 continue;
702 if(!got_token) {
703 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
704 TALLOC_FREE(frame);
705 continue;
708 /* Allocate the space for the ip_list. */
709 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
710 DEBUG(0,("initialise_wins: Malloc fail !\n"));
711 x_fclose(fp);
712 TALLOC_FREE(frame);
713 return False;
716 /* Reset and re-parse the line. */
717 ptr = line;
718 next_token_talloc(frame,&ptr,&name_str,NULL);
719 next_token_talloc(frame,&ptr,&ttl_str,NULL);
720 for(i = 0; i < num_ips; i++) {
721 next_token_talloc(frame,&ptr, &ip_str, NULL);
722 ip_list[i] = interpret_addr2(ip_str);
724 next_token_talloc(frame,&ptr,&nb_flags_str,NULL);
727 * Deal with SELF or REGISTER name encoding. Default is REGISTER
728 * for compatibility with old nmbds.
731 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
732 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
733 SAFE_FREE(ip_list);
734 TALLOC_FREE(frame);
735 continue;
738 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
739 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
742 /* Netbios name. # divides the name from the type (hex): netbios#xx */
743 name = name_str;
745 if((p = strchr(name,'#')) != NULL) {
746 *p = 0;
747 sscanf(p+1,"%x",&type);
750 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
751 sscanf(nb_flags_str,"%x",&nb_flags);
752 sscanf(ttl_str,"%d",&ttl);
754 /* add all entries that have 60 seconds or more to live */
755 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
756 if(ttl != PERMANENT_TTL) {
757 ttl -= time_now;
760 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
761 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
763 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
764 ttl, REGISTER_NAME, num_ips, ip_list );
765 } else {
766 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
767 "%s#%02x ttl = %d first IP %s flags = %2x\n",
768 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
771 TALLOC_FREE(frame);
772 SAFE_FREE(ip_list);
775 x_fclose(fp);
776 return True;
779 /****************************************************************************
780 Send a WINS WACK (Wait ACKnowledgement) response.
781 **************************************************************************/
783 static void send_wins_wack_response(int ttl, struct packet_struct *p)
785 struct nmb_packet *nmb = &p->packet.nmb;
786 unsigned char rdata[2];
788 rdata[0] = rdata[1] = 0;
790 /* Taken from nmblib.c - we need to send back almost
791 identical bytes from the requesting packet header. */
793 rdata[0] = (nmb->header.opcode & 0xF) << 3;
794 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
795 rdata[0] |= 0x4;
797 if (nmb->header.nm_flags.trunc) {
798 rdata[0] |= 0x2;
800 if (nmb->header.nm_flags.recursion_desired) {
801 rdata[0] |= 0x1;
803 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
804 rdata[1] |= 0x80;
806 if (nmb->header.nm_flags.bcast) {
807 rdata[1] |= 0x10;
810 reply_netbios_packet(p, /* Packet to reply to. */
811 0, /* Result code. */
812 NMB_WAIT_ACK, /* nmbd type code. */
813 NMB_WACK_OPCODE, /* opcode. */
814 ttl, /* ttl. */
815 (char *)rdata, /* data to send. */
816 2); /* data length. */
819 /****************************************************************************
820 Send a WINS name registration response.
821 **************************************************************************/
823 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
825 struct nmb_packet *nmb = &p->packet.nmb;
826 char rdata[6];
828 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
830 reply_netbios_packet(p, /* Packet to reply to. */
831 rcode, /* Result code. */
832 WINS_REG, /* nmbd type code. */
833 NMB_NAME_REG_OPCODE, /* opcode. */
834 ttl, /* ttl. */
835 rdata, /* data to send. */
836 6); /* data length. */
839 /***********************************************************************
840 Deal with a name refresh request to a WINS server.
841 ************************************************************************/
843 void wins_process_name_refresh_request( struct subnet_record *subrec,
844 struct packet_struct *p )
846 struct nmb_packet *nmb = &p->packet.nmb;
847 struct nmb_name *question = &nmb->question.question_name;
848 bool bcast = nmb->header.nm_flags.bcast;
849 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
850 bool group = (nb_flags & NB_GROUP) ? True : False;
851 struct name_record *namerec = NULL;
852 int ttl = get_ttl_from_packet(nmb);
853 struct in_addr from_ip;
854 struct in_addr our_fake_ip;
856 our_fake_ip = interpret_addr2("0.0.0.0");
857 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
859 if(bcast) {
861 * We should only get unicast name refresh packets here.
862 * Anyone trying to refresh broadcast should not be going
863 * to a WINS server. Log an error here.
865 if( DEBUGLVL( 0 ) ) {
866 dbgtext( "wins_process_name_refresh_request: " );
867 dbgtext( "Broadcast name refresh request received " );
868 dbgtext( "for name %s ", nmb_namestr(question) );
869 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
870 dbgtext( "on subnet %s. ", subrec->subnet_name );
871 dbgtext( "Error - Broadcasts should not be sent " );
872 dbgtext( "to a WINS server\n" );
874 return;
877 if( DEBUGLVL( 3 ) ) {
878 dbgtext( "wins_process_name_refresh_request: " );
879 dbgtext( "Name refresh for name %s IP %s\n",
880 nmb_namestr(question), inet_ntoa(from_ip) );
884 * See if the name already exists.
885 * If not, handle it as a name registration and return.
887 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
890 * If this is a refresh request and the name doesn't exist then
891 * treat it like a registration request. This allows us to recover
892 * from errors (tridge)
894 if(namerec == NULL) {
895 if( DEBUGLVL( 3 ) ) {
896 dbgtext( "wins_process_name_refresh_request: " );
897 dbgtext( "Name refresh for name %s ",
898 nmb_namestr( question ) );
899 dbgtext( "and the name does not exist. Treating " );
900 dbgtext( "as registration.\n" );
902 wins_process_name_registration_request(subrec,p);
903 return;
907 * if the name is present but not active, simply remove it
908 * and treat the refresh request as a registration & return.
910 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
911 if( DEBUGLVL( 5 ) ) {
912 dbgtext( "wins_process_name_refresh_request: " );
913 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
914 dbgtext( "was not active - removing it.\n" );
916 remove_name_from_namelist( subrec, namerec );
917 namerec = NULL;
918 wins_process_name_registration_request( subrec, p );
919 return;
923 * Check that the group bits for the refreshing name and the
924 * name in our database match. If not, refuse the refresh.
925 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
927 if( (namerec != NULL) &&
928 ( (group && !NAME_GROUP(namerec))
929 || (!group && NAME_GROUP(namerec)) ) ) {
930 if( DEBUGLVL( 3 ) ) {
931 dbgtext( "wins_process_name_refresh_request: " );
932 dbgtext( "Name %s ", nmb_namestr(question) );
933 dbgtext( "group bit = %s does not match ",
934 group ? "True" : "False" );
935 dbgtext( "group bit in WINS for this name.\n" );
937 send_wins_name_registration_response(RFS_ERR, 0, p);
938 return;
942 * For a unique name check that the person refreshing the name is
943 * one of the registered IP addresses. If not - fail the refresh.
944 * Do the same for group names with a type of 0x1c.
945 * Just return success for unique 0x1d refreshes. For normal group
946 * names update the ttl and return success.
948 if( (!group || (group && (question->name_type == 0x1c)))
949 && find_ip_in_name_record(namerec, from_ip) ) {
951 * Update the ttl.
953 update_name_ttl(namerec, ttl);
956 * if the record is a replica:
957 * we take ownership and update the version ID.
959 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
960 update_wins_owner(namerec, our_fake_ip);
961 get_global_id_and_update(&namerec->data.id, True);
964 send_wins_name_registration_response(0, ttl, p);
965 wins_hook("refresh", namerec, ttl);
966 return;
967 } else if((group && (question->name_type == 0x1c))) {
969 * Added by crh for bug #1079.
970 * Fix from Bert Driehuis
972 if( DEBUGLVL( 3 ) ) {
973 dbgtext( "wins_process_name_refresh_request: " );
974 dbgtext( "Name refresh for name %s, ",
975 nmb_namestr(question) );
976 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
977 dbgtext( "is not yet associated with " );
978 dbgtext( "that name. Treating as registration.\n" );
980 wins_process_name_registration_request(subrec,p);
981 return;
982 } else if(group) {
984 * Normal groups are all registered with an IP address of
985 * 255.255.255.255 so we can't search for the IP address.
987 update_name_ttl(namerec, ttl);
988 wins_hook("refresh", namerec, ttl);
989 send_wins_name_registration_response(0, ttl, p);
990 return;
991 } else if(!group && (question->name_type == 0x1d)) {
993 * Special name type - just pretend the refresh succeeded.
995 send_wins_name_registration_response(0, ttl, p);
996 return;
997 } else {
999 * Fail the refresh.
1001 if( DEBUGLVL( 3 ) ) {
1002 dbgtext( "wins_process_name_refresh_request: " );
1003 dbgtext( "Name refresh for name %s with IP %s ",
1004 nmb_namestr(question), inet_ntoa(from_ip) );
1005 dbgtext( "and is IP is not known to the name.\n" );
1007 send_wins_name_registration_response(RFS_ERR, 0, p);
1008 return;
1012 /***********************************************************************
1013 Deal with a name registration request query success to a client that
1014 owned the name.
1016 We have a locked pointer to the original packet stashed away in the
1017 userdata pointer. The success here is actually a failure as it means
1018 the client we queried wants to keep the name, so we must return
1019 a registration failure to the original requestor.
1020 ************************************************************************/
1022 static void wins_register_query_success(struct subnet_record *subrec,
1023 struct userdata_struct *userdata,
1024 struct nmb_name *question_name,
1025 struct in_addr ip,
1026 struct res_rec *answers)
1028 struct packet_struct *orig_reg_packet;
1030 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1032 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1033 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
1035 send_wins_name_registration_response(ACT_ERR, 0, orig_reg_packet);
1037 orig_reg_packet->locked = False;
1038 free_packet(orig_reg_packet);
1041 /***********************************************************************
1042 Deal with a name registration request query failure to a client that
1043 owned the name.
1045 We have a locked pointer to the original packet stashed away in the
1046 userdata pointer. The failure here is actually a success as it means
1047 the client we queried didn't want to keep the name, so we can remove
1048 the old name record and then successfully add the new name.
1049 ************************************************************************/
1051 static void wins_register_query_fail(struct subnet_record *subrec,
1052 struct response_record *rrec,
1053 struct nmb_name *question_name,
1054 int rcode)
1056 struct userdata_struct *userdata = rrec->userdata;
1057 struct packet_struct *orig_reg_packet;
1058 struct name_record *namerec = NULL;
1060 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1063 * We want to just add the name, as we now know the original owner
1064 * didn't want it. But we can't just do that as an arbitary
1065 * amount of time may have taken place between the name query
1066 * request and this timeout/error response. So we check that
1067 * the name still exists and is in the same state - if so
1068 * we remove it and call wins_process_name_registration_request()
1069 * as we know it will do the right thing now.
1072 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1074 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1075 ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1076 remove_name_from_namelist( subrec, namerec);
1077 namerec = NULL;
1080 if(namerec == NULL) {
1081 wins_process_name_registration_request(subrec, orig_reg_packet);
1082 } else {
1083 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1084 "querying for name %s in order to replace it and this reply.\n",
1085 nmb_namestr(question_name) ));
1088 orig_reg_packet->locked = False;
1089 free_packet(orig_reg_packet);
1092 /***********************************************************************
1093 Deal with a name registration request to a WINS server.
1095 Use the following pseudocode :
1097 registering_group
1100 +--------name exists
1103 | +--- existing name is group
1104 | | |
1105 | | |
1106 | | +--- add name (return).
1109 | +--- exiting name is unique
1112 | +--- query existing owner (return).
1115 +--------name doesn't exist
1118 +--- add name (return).
1120 registering_unique
1123 +--------name exists
1126 | +--- existing name is group
1127 | | |
1128 | | |
1129 | | +--- fail add (return).
1130 | |
1132 | +--- exiting name is unique
1135 | +--- query existing owner (return).
1138 +--------name doesn't exist
1141 +--- add name (return).
1143 As can be seen from the above, the two cases may be collapsed onto each
1144 other with the exception of the case where the name already exists and
1145 is a group name. This case we handle with an if statement.
1147 ************************************************************************/
1149 void wins_process_name_registration_request(struct subnet_record *subrec,
1150 struct packet_struct *p)
1152 unstring name;
1153 struct nmb_packet *nmb = &p->packet.nmb;
1154 struct nmb_name *question = &nmb->question.question_name;
1155 bool bcast = nmb->header.nm_flags.bcast;
1156 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1157 int ttl = get_ttl_from_packet(nmb);
1158 struct name_record *namerec = NULL;
1159 struct in_addr from_ip;
1160 bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1161 struct in_addr our_fake_ip;
1163 our_fake_ip = interpret_addr2("0.0.0.0");
1164 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1166 if(bcast) {
1168 * We should only get unicast name registration packets here.
1169 * Anyone trying to register broadcast should not be going to a WINS
1170 * server. Log an error here.
1173 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1174 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1175 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1176 return;
1179 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1180 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1183 * See if the name already exists.
1186 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1189 * if the record exists but NOT in active state,
1190 * consider it dead.
1192 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1193 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1194 not active - removing it.\n", nmb_namestr(question) ));
1195 remove_name_from_namelist( subrec, namerec );
1196 namerec = NULL;
1200 * Deal with the case where the name found was a dns entry.
1201 * Remove it as we now have a NetBIOS client registering the
1202 * name.
1205 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1206 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1207 a dns lookup - removing it.\n", nmb_namestr(question) ));
1208 remove_name_from_namelist( subrec, namerec );
1209 namerec = NULL;
1213 * Reject if the name exists and is not a REGISTER_NAME.
1214 * (ie. Don't allow any static names to be overwritten.
1217 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1218 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1219 to register name %s. Name already exists in WINS with source type %d.\n",
1220 nmb_namestr(question), namerec->data.source ));
1221 send_wins_name_registration_response(RFS_ERR, 0, p);
1222 return;
1226 * Special policy decisions based on MS documentation.
1227 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1228 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1232 * A group name is always added as the local broadcast address, except
1233 * for group names ending in 0x1c.
1234 * Group names with type 0x1c are registered with individual IP addresses.
1237 if(registering_group_name && (question->name_type != 0x1c)) {
1238 from_ip = interpret_addr2("255.255.255.255");
1242 * Ignore all attempts to register a unique 0x1d name, although return success.
1245 if(!registering_group_name && (question->name_type == 0x1d)) {
1246 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1247 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1248 send_wins_name_registration_response(0, ttl, p);
1249 return;
1253 * Next two cases are the 'if statement' mentioned above.
1256 if((namerec != NULL) && NAME_GROUP(namerec)) {
1257 if(registering_group_name) {
1259 * If we are adding a group name, the name exists and is also a group entry just add this
1260 * IP address to it and update the ttl.
1263 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1264 inet_ntoa(from_ip), nmb_namestr(question) ));
1267 * Check the ip address is not already in the group.
1270 if(!find_ip_in_name_record(namerec, from_ip)) {
1272 * Need to emulate the behaviour of Windows, as
1273 * described in:
1274 * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1275 * (is there an MS reference for this
1276 * somewhere?) because if the 1c list gets over
1277 * 86 entries, the reply packet is too big
1278 * (rdata>576 bytes) so no reply is sent.
1280 * Keep only the "latest" 25 records, while
1281 * ensuring that the PDC (0x1b) is never removed
1282 * We do this by removing the first entry that
1283 * isn't the 1b entry for the same name,
1284 * on the grounds that insertion is at the end
1285 * of the list, so the oldest entries are at
1286 * the start.
1289 while(namerec->data.num_ips>=25) {
1290 struct name_record *name1brec = NULL;
1292 /* We only do this for 1c types. */
1293 if (namerec->name.name_type != 0x1c) {
1294 break;
1296 DEBUG(3,("wins_process_name_registration_request: "
1297 "More than 25 IPs already in "
1298 "the list. Looking for a 1b "
1299 "record\n"));
1301 /* Ensure we have all the active 1b
1302 * names on the list. */
1303 wins_delete_all_1b_in_memory_records();
1304 fetch_all_active_wins_1b_names();
1306 /* Per the above, find the 1b record,
1307 and then remove the first IP that isn't the same */
1308 for(name1brec = subrec->namelist;
1309 name1brec;
1310 name1brec = name1brec->next ) {
1311 if( WINS_STATE_ACTIVE(name1brec) &&
1312 name1brec->name.name_type == 0x1b) {
1313 DEBUG(3,("wins_process_name_registration_request: "
1314 "Found the #1b record "
1315 "with ip %s\n",
1316 inet_ntoa(name1brec->data.ip[0])));
1317 break;
1320 if(!name1brec) {
1321 DEBUG(3,("wins_process_name_registration_request: "
1322 "Didn't find a #1b name record. "
1323 "Removing the first available "
1324 "entry %s\n",
1325 inet_ntoa(namerec->data.ip[0])));
1326 remove_ip_from_name_record(namerec, namerec->data.ip[0]);
1327 wins_hook("delete", namerec, 0);
1328 } else {
1329 int i;
1330 for(i=0; i<namerec->data.num_ips; i++) {
1331 /* The name1brec should only have
1332 * the single IP address in it,
1333 * so we only check against the first one*/
1334 if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) {
1335 /* The i'th entry isn't the 1b address; delete it */
1336 DEBUG(3,("wins_process_name_registration_request: "
1337 "Entry at %d is not the #1b address. "
1338 "About to remove it\n",
1339 i));
1340 remove_ip_from_name_record(namerec, namerec->data.ip[i]);
1341 wins_hook("delete", namerec, 0);
1342 break;
1347 /* The list is guaranteed to be < 25 entries now
1348 * - safe to add a new one */
1349 add_ip_to_name_record(namerec, from_ip);
1350 /* we need to update the record for replication */
1351 get_global_id_and_update(&namerec->data.id, True);
1354 * if the record is a replica, we must change
1355 * the wins owner to us to make the replication updates
1356 * it on the other wins servers.
1357 * And when the partner will receive this record,
1358 * it will update its own record.
1361 update_wins_owner(namerec, our_fake_ip);
1363 update_name_ttl(namerec, ttl);
1364 wins_hook("refresh", namerec, ttl);
1365 send_wins_name_registration_response(0, ttl, p);
1366 return;
1367 } else {
1370 * If we are adding a unique name, the name exists in the WINS db
1371 * and is a group name then reject the registration.
1373 * explanation: groups have a higher priority than unique names.
1376 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1377 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1378 send_wins_name_registration_response(RFS_ERR, 0, p);
1379 return;
1384 * From here on down we know that if the name exists in the WINS db it is
1385 * a unique name, not a group name.
1389 * If the name exists and is one of our names then check the
1390 * registering IP address. If it's not one of ours then automatically
1391 * reject without doing the query - we know we will reject it.
1394 if ( namerec != NULL ) {
1395 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1396 if( is_myname(name) ) {
1397 if(!ismyip_v4(from_ip)) {
1398 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1399 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1400 send_wins_name_registration_response(RFS_ERR, 0, p);
1401 return;
1402 } else {
1404 * It's one of our names and one of our IP's - update the ttl.
1406 update_name_ttl(namerec, ttl);
1407 wins_hook("refresh", namerec, ttl);
1408 send_wins_name_registration_response(0, ttl, p);
1409 return;
1412 } else {
1413 name[0] = '\0';
1417 * If the name exists and it is a unique registration and the registering IP
1418 * is the same as the (single) already registered IP then just update the ttl.
1420 * But not if the record is an active replica. IF it's a replica, it means it can be
1421 * the same client which has moved and not yet expired. So we don't update
1422 * the ttl in this case and go beyond to do a WACK and query the old client
1425 if( !registering_group_name
1426 && (namerec != NULL)
1427 && (namerec->data.num_ips == 1)
1428 && ip_equal_v4( namerec->data.ip[0], from_ip )
1429 && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1430 update_name_ttl( namerec, ttl );
1431 wins_hook("refresh", namerec, ttl);
1432 send_wins_name_registration_response( 0, ttl, p );
1433 return;
1437 * Finally if the name exists do a query to the registering machine
1438 * to see if they still claim to have the name.
1441 if( namerec != NULL ) {
1442 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1443 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1446 * First send a WACK to the registering machine.
1449 send_wins_wack_response(60, p);
1452 * When the reply comes back we need the original packet.
1453 * Lock this so it won't be freed and then put it into
1454 * the userdata structure.
1457 p->locked = True;
1459 userdata = (struct userdata_struct *)ud;
1461 userdata->copy_fn = NULL;
1462 userdata->free_fn = NULL;
1463 userdata->userdata_len = sizeof(struct packet_struct *);
1464 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1467 * Use the new call to send a query directly to an IP address.
1468 * This sends the query directly to the IP address, and ensures
1469 * the recursion desired flag is not set (you were right Luke :-).
1470 * This function should *only* be called from the WINS server
1471 * code. JRA.
1474 pull_ascii_nstring(name, sizeof(name), question->name);
1475 query_name_from_wins_server( *namerec->data.ip,
1476 name,
1477 question->name_type,
1478 wins_register_query_success,
1479 wins_register_query_fail,
1480 userdata );
1481 return;
1485 * Name did not exist - add it.
1488 pull_ascii_nstring(name, sizeof(name), question->name);
1489 add_name_to_subnet( subrec, name, question->name_type,
1490 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1492 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1493 get_global_id_and_update(&namerec->data.id, True);
1494 update_wins_owner(namerec, our_fake_ip);
1495 update_wins_flag(namerec, WINS_ACTIVE);
1496 wins_hook("add", namerec, ttl);
1499 send_wins_name_registration_response(0, ttl, p);
1502 /***********************************************************************
1503 Deal with a mutihomed name query success to the machine that
1504 requested the multihomed name registration.
1506 We have a locked pointer to the original packet stashed away in the
1507 userdata pointer.
1508 ************************************************************************/
1510 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1511 struct userdata_struct *userdata,
1512 struct nmb_name *question_name,
1513 struct in_addr ip,
1514 struct res_rec *answers)
1516 struct packet_struct *orig_reg_packet;
1517 struct nmb_packet *nmb;
1518 struct name_record *namerec = NULL;
1519 struct in_addr from_ip;
1520 int ttl;
1521 struct in_addr our_fake_ip;
1523 our_fake_ip = interpret_addr2("0.0.0.0");
1524 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1526 nmb = &orig_reg_packet->packet.nmb;
1528 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1529 ttl = get_ttl_from_packet(nmb);
1532 * We want to just add the new IP, as we now know the requesting
1533 * machine claims to own it. But we can't just do that as an arbitary
1534 * amount of time may have taken place between the name query
1535 * request and this response. So we check that
1536 * the name still exists and is in the same state - if so
1537 * we just add the extra IP and update the ttl.
1540 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1542 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1543 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1544 a subsequent IP address.\n", nmb_namestr(question_name) ));
1545 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1547 orig_reg_packet->locked = False;
1548 free_packet(orig_reg_packet);
1550 return;
1553 if(!find_ip_in_name_record(namerec, from_ip)) {
1554 add_ip_to_name_record(namerec, from_ip);
1557 get_global_id_and_update(&namerec->data.id, True);
1558 update_wins_owner(namerec, our_fake_ip);
1559 update_wins_flag(namerec, WINS_ACTIVE);
1560 update_name_ttl(namerec, ttl);
1561 wins_hook("add", namerec, ttl);
1562 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1564 orig_reg_packet->locked = False;
1565 free_packet(orig_reg_packet);
1568 /***********************************************************************
1569 Deal with a name registration request query failure to a client that
1570 owned the name.
1572 We have a locked pointer to the original packet stashed away in the
1573 userdata pointer.
1574 ************************************************************************/
1576 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1577 struct response_record *rrec,
1578 struct nmb_name *question_name,
1579 int rcode)
1581 struct userdata_struct *userdata = rrec->userdata;
1582 struct packet_struct *orig_reg_packet;
1584 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1586 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1587 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1588 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1590 orig_reg_packet->locked = False;
1591 free_packet(orig_reg_packet);
1592 return;
1595 /***********************************************************************
1596 Deal with a multihomed name registration request to a WINS server.
1597 These cannot be group name registrations.
1598 ***********************************************************************/
1600 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1601 struct packet_struct *p)
1603 struct nmb_packet *nmb = &p->packet.nmb;
1604 struct nmb_name *question = &nmb->question.question_name;
1605 bool bcast = nmb->header.nm_flags.bcast;
1606 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1607 int ttl = get_ttl_from_packet(nmb);
1608 struct name_record *namerec = NULL;
1609 struct in_addr from_ip;
1610 bool group = (nb_flags & NB_GROUP) ? True : False;
1611 struct in_addr our_fake_ip;
1612 unstring qname;
1614 our_fake_ip = interpret_addr2("0.0.0.0");
1615 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1617 if(bcast) {
1619 * We should only get unicast name registration packets here.
1620 * Anyone trying to register broadcast should not be going to a WINS
1621 * server. Log an error here.
1624 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1625 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1626 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1627 return;
1631 * Only unique names should be registered multihomed.
1634 if(group) {
1635 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1636 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1637 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1638 return;
1641 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1642 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1645 * Deal with policy regarding 0x1d names.
1648 if(question->name_type == 0x1d) {
1649 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1650 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1651 send_wins_name_registration_response(0, ttl, p);
1652 return;
1656 * See if the name already exists.
1659 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1662 * if the record exists but NOT in active state,
1663 * consider it dead.
1666 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1667 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1668 remove_name_from_namelist(subrec, namerec);
1669 namerec = NULL;
1673 * Deal with the case where the name found was a dns entry.
1674 * Remove it as we now have a NetBIOS client registering the
1675 * name.
1678 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1679 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1680 - removing it.\n", nmb_namestr(question) ));
1681 remove_name_from_namelist( subrec, namerec);
1682 namerec = NULL;
1686 * Reject if the name exists and is not a REGISTER_NAME.
1687 * (ie. Don't allow any static names to be overwritten.
1690 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1691 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1692 to register name %s. Name already exists in WINS with source type %d.\n",
1693 nmb_namestr(question), namerec->data.source ));
1694 send_wins_name_registration_response(RFS_ERR, 0, p);
1695 return;
1699 * Reject if the name exists and is a GROUP name and is active.
1702 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1703 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1704 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1705 send_wins_name_registration_response(RFS_ERR, 0, p);
1706 return;
1710 * From here on down we know that if the name exists in the WINS db it is
1711 * a unique name, not a group name.
1715 * If the name exists and is one of our names then check the
1716 * registering IP address. If it's not one of ours then automatically
1717 * reject without doing the query - we know we will reject it.
1720 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1721 if(!ismyip_v4(from_ip)) {
1722 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1723 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1724 send_wins_name_registration_response(RFS_ERR, 0, p);
1725 return;
1726 } else {
1728 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1729 * update the ttl. Update the version ID to force replication.
1731 update_name_ttl(namerec, ttl);
1733 if(!find_ip_in_name_record(namerec, from_ip)) {
1734 get_global_id_and_update(&namerec->data.id, True);
1735 update_wins_owner(namerec, our_fake_ip);
1736 update_wins_flag(namerec, WINS_ACTIVE);
1738 add_ip_to_name_record(namerec, from_ip);
1741 wins_hook("refresh", namerec, ttl);
1742 send_wins_name_registration_response(0, ttl, p);
1743 return;
1748 * If the name exists and is active, check if the IP address is already registered
1749 * to that name. If so then update the ttl and reply success.
1752 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1753 update_name_ttl(namerec, ttl);
1756 * If it's a replica, we need to become the wins owner
1757 * to force the replication
1759 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1760 get_global_id_and_update(&namerec->data.id, True);
1761 update_wins_owner(namerec, our_fake_ip);
1762 update_wins_flag(namerec, WINS_ACTIVE);
1765 wins_hook("refresh", namerec, ttl);
1766 send_wins_name_registration_response(0, ttl, p);
1767 return;
1771 * If the name exists do a query to the owner
1772 * to see if they still want the name.
1775 if(namerec != NULL) {
1776 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1777 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1780 * First send a WACK to the registering machine.
1783 send_wins_wack_response(60, p);
1786 * When the reply comes back we need the original packet.
1787 * Lock this so it won't be freed and then put it into
1788 * the userdata structure.
1791 p->locked = True;
1793 userdata = (struct userdata_struct *)ud;
1795 userdata->copy_fn = NULL;
1796 userdata->free_fn = NULL;
1797 userdata->userdata_len = sizeof(struct packet_struct *);
1798 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1801 * Use the new call to send a query directly to an IP address.
1802 * This sends the query directly to the IP address, and ensures
1803 * the recursion desired flag is not set (you were right Luke :-).
1804 * This function should *only* be called from the WINS server
1805 * code. JRA.
1807 * Note that this packet is sent to the current owner of the name,
1808 * not the person who sent the packet
1811 pull_ascii_nstring( qname, sizeof(qname), question->name);
1812 query_name_from_wins_server( namerec->data.ip[0],
1813 qname,
1814 question->name_type,
1815 wins_multihomed_register_query_success,
1816 wins_multihomed_register_query_fail,
1817 userdata );
1819 return;
1823 * Name did not exist - add it.
1826 pull_ascii_nstring( qname, sizeof(qname), question->name);
1827 add_name_to_subnet( subrec, qname, question->name_type,
1828 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1830 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1831 get_global_id_and_update(&namerec->data.id, True);
1832 update_wins_owner(namerec, our_fake_ip);
1833 update_wins_flag(namerec, WINS_ACTIVE);
1834 wins_hook("add", namerec, ttl);
1837 send_wins_name_registration_response(0, ttl, p);
1840 /***********************************************************************
1841 Fetch all *<1b> names from the WINS db and store on the namelist.
1842 ***********************************************************************/
1844 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1846 struct name_record *namerec = NULL;
1848 if (kbuf.dsize != sizeof(unstring) + 1) {
1849 return 0;
1852 /* Filter out all non-1b names. */
1853 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1854 return 0;
1857 namerec = wins_record_to_name_record(kbuf, dbuf);
1858 if (!namerec) {
1859 return 0;
1862 DLIST_ADD(wins_server_subnet->namelist, namerec);
1863 return 0;
1866 void fetch_all_active_wins_1b_names(void)
1868 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1871 /***********************************************************************
1872 Deal with the special name query for *<1b>.
1873 ***********************************************************************/
1875 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1876 struct packet_struct *p)
1878 struct name_record *namerec = NULL;
1879 char *prdata;
1880 int num_ips;
1883 * Go through all the ACTIVE names in the WINS db looking for those
1884 * ending in <1b>. Use this to calculate the number of IP
1885 * addresses we need to return.
1888 num_ips = 0;
1890 /* First, clear the in memory list - we're going to re-populate
1891 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1893 wins_delete_all_tmp_in_memory_records();
1895 fetch_all_active_wins_1b_names();
1897 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1898 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1899 num_ips += namerec->data.num_ips;
1903 if(num_ips == 0) {
1905 * There are no 0x1b names registered. Return name query fail.
1907 send_wins_name_query_response(NAM_ERR, p, NULL);
1908 return;
1911 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1912 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1913 return;
1917 * Go through all the names again in the WINS db looking for those
1918 * ending in <1b>. Add their IP addresses into the list we will
1919 * return.
1922 num_ips = 0;
1923 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1924 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1925 int i;
1926 for(i = 0; i < namerec->data.num_ips; i++) {
1927 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1928 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1929 num_ips++;
1935 * Send back the reply containing the IP list.
1938 reply_netbios_packet(p, /* Packet to reply to. */
1939 0, /* Result code. */
1940 WINS_QUERY, /* nmbd type code. */
1941 NMB_NAME_QUERY_OPCODE, /* opcode. */
1942 lp_min_wins_ttl(), /* ttl. */
1943 prdata, /* data to send. */
1944 num_ips*6); /* data length. */
1946 SAFE_FREE(prdata);
1949 /****************************************************************************
1950 Send a WINS name query response.
1951 **************************************************************************/
1953 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1954 struct name_record *namerec)
1956 char rdata[6];
1957 char *prdata = rdata;
1958 int reply_data_len = 0;
1959 int ttl = 0;
1960 int i;
1962 memset(rdata,'\0',6);
1964 if(rcode == 0) {
1966 int ip_count;
1968 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1970 /* The netbios reply packet data section is limited to 576 bytes. In theory
1971 * this should give us space for 96 addresses, but in practice, 86 appears
1972 * to be the max (don't know why). If we send any more than that,
1973 * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
1974 * overflow. Keep the count to 85 and it will be ok */
1975 ip_count=namerec->data.num_ips;
1976 if(ip_count>85) {
1977 ip_count=85;
1980 /* Copy all known ip addresses into the return data. */
1981 /* Optimise for the common case of one IP address so we don't need a malloc. */
1983 if( ip_count == 1 ) {
1984 prdata = rdata;
1985 } else {
1986 if((prdata = (char *)SMB_MALLOC( ip_count * 6 )) == NULL) {
1987 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1988 return;
1992 for(i = 0; i < ip_count; i++) {
1993 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1994 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1997 sort_query_replies(prdata, i, p->ip);
1998 reply_data_len = ip_count * 6;
2001 reply_netbios_packet(p, /* Packet to reply to. */
2002 rcode, /* Result code. */
2003 WINS_QUERY, /* nmbd type code. */
2004 NMB_NAME_QUERY_OPCODE, /* opcode. */
2005 ttl, /* ttl. */
2006 prdata, /* data to send. */
2007 reply_data_len); /* data length. */
2009 if(prdata != rdata) {
2010 SAFE_FREE(prdata);
2014 /***********************************************************************
2015 Deal with a name query.
2016 ***********************************************************************/
2018 void wins_process_name_query_request(struct subnet_record *subrec,
2019 struct packet_struct *p)
2021 struct nmb_packet *nmb = &p->packet.nmb;
2022 struct nmb_name *question = &nmb->question.question_name;
2023 struct name_record *namerec = NULL;
2024 unstring qname;
2026 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
2027 nmb_namestr(question), inet_ntoa(p->ip) ));
2030 * Special name code. If the queried name is *<1b> then search
2031 * the entire WINS database and return a list of all the IP addresses
2032 * registered to any <1b> name. This is to allow domain master browsers
2033 * to discover other domains that may not have a presence on their subnet.
2036 pull_ascii_nstring(qname, sizeof(qname), question->name);
2037 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
2038 process_wins_dmb_query_request( subrec, p);
2039 return;
2042 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2044 if(namerec != NULL) {
2046 * If the name is not anymore in active state then reply not found.
2047 * it's fair even if we keep it in the cache for days.
2049 if (!WINS_STATE_ACTIVE(namerec)) {
2050 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2051 nmb_namestr(question) ));
2052 send_wins_name_query_response(NAM_ERR, p, namerec);
2053 return;
2057 * If it's a DNSFAIL_NAME then reply name not found.
2060 if( namerec->data.source == DNSFAIL_NAME ) {
2061 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2062 nmb_namestr(question) ));
2063 send_wins_name_query_response(NAM_ERR, p, namerec);
2064 return;
2068 * If the name has expired then reply name not found.
2071 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
2072 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2073 nmb_namestr(question) ));
2074 send_wins_name_query_response(NAM_ERR, p, namerec);
2075 return;
2078 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2079 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
2081 send_wins_name_query_response(0, p, namerec);
2082 return;
2086 * Name not found in WINS - try a dns query if it's a 0x20 name.
2089 if(lp_wins_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
2090 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2091 nmb_namestr(question) ));
2093 queue_dns_query(p, question);
2094 return;
2098 * Name not found - return error.
2101 send_wins_name_query_response(NAM_ERR, p, NULL);
2104 /****************************************************************************
2105 Send a WINS name release response.
2106 **************************************************************************/
2108 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
2110 struct nmb_packet *nmb = &p->packet.nmb;
2111 char rdata[6];
2113 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
2115 reply_netbios_packet(p, /* Packet to reply to. */
2116 rcode, /* Result code. */
2117 NMB_REL, /* nmbd type code. */
2118 NMB_NAME_RELEASE_OPCODE, /* opcode. */
2119 0, /* ttl. */
2120 rdata, /* data to send. */
2121 6); /* data length. */
2124 /***********************************************************************
2125 Deal with a name release.
2126 ***********************************************************************/
2128 void wins_process_name_release_request(struct subnet_record *subrec,
2129 struct packet_struct *p)
2131 struct nmb_packet *nmb = &p->packet.nmb;
2132 struct nmb_name *question = &nmb->question.question_name;
2133 bool bcast = nmb->header.nm_flags.bcast;
2134 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
2135 struct name_record *namerec = NULL;
2136 struct in_addr from_ip;
2137 bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;
2139 putip((char *)&from_ip,&nmb->additional->rdata[2]);
2141 if(bcast) {
2143 * We should only get unicast name registration packets here.
2144 * Anyone trying to register broadcast should not be going to a WINS
2145 * server. Log an error here.
2148 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2149 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2150 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2151 return;
2154 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2155 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2158 * Deal with policy regarding 0x1d names.
2161 if(!releasing_group_name && (question->name_type == 0x1d)) {
2162 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2163 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2164 send_wins_name_release_response(0, p);
2165 return;
2169 * See if the name already exists.
2172 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2174 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2175 send_wins_name_release_response(NAM_ERR, p);
2176 return;
2180 * Check that the sending machine has permission to release this name.
2181 * If it's a group name not ending in 0x1c then just say yes and let
2182 * the group time out.
2185 if(releasing_group_name && (question->name_type != 0x1c)) {
2186 send_wins_name_release_response(0, p);
2187 return;
2191 * Check that the releasing node is on the list of IP addresses
2192 * for this name. Disallow the release if not.
2195 if(!find_ip_in_name_record(namerec, from_ip)) {
2196 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2197 release name %s as IP %s is not one of the known IP's for this name.\n",
2198 nmb_namestr(question), inet_ntoa(from_ip) ));
2199 send_wins_name_release_response(NAM_ERR, p);
2200 return;
2204 * Check if the record is active. IF it's already released
2205 * or tombstoned, refuse the release.
2208 if (!WINS_STATE_ACTIVE(namerec)) {
2209 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2210 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2211 send_wins_name_release_response(NAM_ERR, p);
2212 return;
2216 * Check if the record is a 0x1c group
2217 * and has more then one ip
2218 * remove only this address.
2221 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2222 remove_ip_from_name_record(namerec, from_ip);
2223 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2224 inet_ntoa(from_ip),nmb_namestr(question)));
2225 wins_hook("delete", namerec, 0);
2226 send_wins_name_release_response(0, p);
2227 return;
2231 * Send a release response.
2232 * Flag the name as released and update the ttl
2235 namerec->data.wins_flags |= WINS_RELEASED;
2236 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2238 wins_hook("delete", namerec, 0);
2239 send_wins_name_release_response(0, p);
2242 /*******************************************************************
2243 WINS time dependent processing.
2244 ******************************************************************/
2246 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2248 time_t t = *(time_t *)state;
2249 bool store_record = False;
2250 struct name_record *namerec = NULL;
2251 struct in_addr our_fake_ip;
2253 our_fake_ip = interpret_addr2("0.0.0.0");
2254 if (kbuf.dsize != sizeof(unstring) + 1) {
2255 return 0;
2258 namerec = wins_record_to_name_record(kbuf, dbuf);
2259 if (!namerec) {
2260 return 0;
2263 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2264 if( namerec->data.source == SELF_NAME ) {
2265 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2266 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2267 namerec->data.death_time += 300;
2268 store_record = True;
2269 goto done;
2270 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2271 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2272 nmb_namestr(&namerec->name)));
2273 remove_name_from_wins_namelist(namerec );
2274 goto done;
2277 /* handle records, samba is the wins owner */
2278 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2279 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2280 case WINS_ACTIVE:
2281 namerec->data.wins_flags&=~WINS_STATE_MASK;
2282 namerec->data.wins_flags|=WINS_RELEASED;
2283 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2284 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2285 nmb_namestr(&namerec->name)));
2286 store_record = True;
2287 goto done;
2288 case WINS_RELEASED:
2289 namerec->data.wins_flags&=~WINS_STATE_MASK;
2290 namerec->data.wins_flags|=WINS_TOMBSTONED;
2291 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2292 get_global_id_and_update(&namerec->data.id, True);
2293 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2294 nmb_namestr(&namerec->name)));
2295 store_record = True;
2296 goto done;
2297 case WINS_TOMBSTONED:
2298 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2299 nmb_namestr(&namerec->name)));
2300 remove_name_from_wins_namelist(namerec );
2301 goto done;
2303 } else {
2304 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2305 case WINS_ACTIVE:
2306 /* that's not as MS says it should be */
2307 namerec->data.wins_flags&=~WINS_STATE_MASK;
2308 namerec->data.wins_flags|=WINS_TOMBSTONED;
2309 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2310 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2311 nmb_namestr(&namerec->name)));
2312 store_record = True;
2313 goto done;
2314 case WINS_TOMBSTONED:
2315 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2316 nmb_namestr(&namerec->name)));
2317 remove_name_from_wins_namelist(namerec );
2318 goto done;
2319 case WINS_RELEASED:
2320 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2321 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2322 goto done;
2327 done:
2329 if (store_record) {
2330 wins_store_changed_namerec(namerec);
2333 SAFE_FREE(namerec->data.ip);
2334 SAFE_FREE(namerec);
2336 return 0;
2339 /*******************************************************************
2340 Time dependent wins processing.
2341 ******************************************************************/
2343 void initiate_wins_processing(time_t t)
2345 static time_t lasttime = 0;
2347 if (!lasttime) {
2348 lasttime = t;
2350 if (t - lasttime < 20) {
2351 return;
2354 if(!lp_we_are_a_wins_server()) {
2355 lasttime = t;
2356 return;
2359 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2361 wins_delete_all_tmp_in_memory_records();
2363 wins_write_database(t, True);
2365 lasttime = t;
2368 /*******************************************************************
2369 Write out one record.
2370 ******************************************************************/
2372 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2374 int i;
2375 struct tm *tm;
2377 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2379 if( namerec->data.death_time != PERMANENT_TTL ) {
2380 char *ts, *nl;
2382 tm = localtime(&namerec->data.death_time);
2383 if (!tm) {
2384 return;
2386 ts = asctime(tm);
2387 if (!ts) {
2388 return;
2390 nl = strrchr( ts, '\n' );
2391 if( NULL != nl ) {
2392 *nl = '\0';
2394 DEBUGADD(4,("TTL = %s ", ts ));
2395 } else {
2396 DEBUGADD(4,("TTL = PERMANENT "));
2399 for (i = 0; i < namerec->data.num_ips; i++) {
2400 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2402 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2404 if( namerec->data.source == REGISTER_NAME ) {
2405 unstring name;
2406 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2407 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2408 (int)namerec->data.death_time);
2410 for (i = 0; i < namerec->data.num_ips; i++)
2411 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2412 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2416 /*******************************************************************
2417 Write out the current WINS database.
2418 ******************************************************************/
2420 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2422 struct name_record *namerec = NULL;
2423 XFILE *fp = (XFILE *)state;
2425 if (kbuf.dsize != sizeof(unstring) + 1) {
2426 return 0;
2429 namerec = wins_record_to_name_record(kbuf, dbuf);
2430 if (!namerec) {
2431 return 0;
2434 wins_write_name_record(namerec, fp);
2436 SAFE_FREE(namerec->data.ip);
2437 SAFE_FREE(namerec);
2438 return 0;
2442 void wins_write_database(time_t t, bool background)
2444 static time_t last_write_time = 0;
2445 char *fname = NULL;
2446 char *fnamenew = NULL;
2448 XFILE *fp;
2450 if (background) {
2451 if (!last_write_time) {
2452 last_write_time = t;
2454 if (t - last_write_time < 120) {
2455 return;
2460 if(!lp_we_are_a_wins_server()) {
2461 return;
2464 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2465 if (background) {
2466 CatchChild();
2467 if (fork()) {
2468 return;
2470 if (tdb_reopen(wins_tdb)) {
2471 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2472 strerror(errno)));
2473 _exit(0);
2474 return;
2478 if (!(fname = state_path(WINS_LIST))) {
2479 goto err_exit;
2481 /* This is safe as the 0 length means "don't expand". */
2482 all_string_sub(fname,"//", "/", 0);
2484 if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)getpid()) < 0) {
2485 goto err_exit;
2488 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2489 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2490 goto err_exit;
2493 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2495 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2497 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2499 x_fclose(fp);
2500 chmod(fnamenew,0644);
2501 unlink(fname);
2502 rename(fnamenew,fname);
2504 err_exit:
2506 SAFE_FREE(fnamenew);
2507 TALLOC_FREE(fname);
2509 if (background) {
2510 _exit(0);
2514 #if 0
2515 Until winsrepl is done.
2516 /****************************************************************************
2517 Process a internal Samba message receiving a wins record.
2518 ***************************************************************************/
2520 void nmbd_wins_new_entry(struct messaging_context *msg,
2521 void *private_data,
2522 uint32_t msg_type,
2523 struct server_id server_id,
2524 DATA_BLOB *data)
2526 WINS_RECORD *record;
2527 struct name_record *namerec = NULL;
2528 struct name_record *new_namerec = NULL;
2529 struct nmb_name question;
2530 bool overwrite=False;
2531 struct in_addr our_fake_ip;
2532 int i;
2534 our_fake_ip = interpret_addr2("0.0.0.0");
2535 if (buf==NULL) {
2536 return;
2539 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2540 record=(WINS_RECORD *)buf;
2542 make_nmb_name(&question, record->name, record->type);
2544 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2546 /* record doesn't exist, add it */
2547 if (namerec == NULL) {
2548 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2549 record->name, record->type, inet_ntoa(record->wins_ip)));
2551 new_namerec=add_name_to_subnet( wins_server_subnet,
2552 record->name,
2553 record->type,
2554 record->nb_flags,
2555 EXTINCTION_INTERVAL,
2556 REGISTER_NAME,
2557 record->num_ips,
2558 record->ip);
2560 if (new_namerec!=NULL) {
2561 update_wins_owner(new_namerec, record->wins_ip);
2562 update_wins_flag(new_namerec, record->wins_flags);
2563 new_namerec->data.id=record->id;
2565 wins_server_subnet->namelist_changed = True;
2569 /* check if we have a conflict */
2570 if (namerec != NULL) {
2571 /* both records are UNIQUE */
2572 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2574 /* the database record is a replica */
2575 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2576 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2577 if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2578 overwrite=True;
2579 } else
2580 overwrite=True;
2581 } else {
2582 /* we are the wins owner of the database record */
2583 /* the 2 records have the same IP address */
2584 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2585 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2586 get_global_id_and_update(&namerec->data.id, True);
2587 else
2588 overwrite=True;
2590 } else {
2591 /* the 2 records have different IP address */
2592 if (namerec->data.wins_flags&WINS_ACTIVE) {
2593 if (record->wins_flags&WINS_TOMBSTONED)
2594 get_global_id_and_update(&namerec->data.id, True);
2595 if (record->wins_flags&WINS_ACTIVE)
2596 /* send conflict challenge to the replica node */
2598 } else
2599 overwrite=True;
2605 /* the replica is a standard group */
2606 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2607 /* if the database record is unique and active force a name release */
2608 if (namerec->data.wins_flags&WINS_UNIQUE)
2609 /* send a release name to the unique node */
2611 overwrite=True;
2615 /* the replica is a special group */
2616 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2617 if (namerec->data.wins_flags&WINS_ACTIVE) {
2618 for (i=0; i<record->num_ips; i++)
2619 if(!find_ip_in_name_record(namerec, record->ip[i]))
2620 add_ip_to_name_record(namerec, record->ip[i]);
2621 } else {
2622 overwrite=True;
2626 /* the replica is a multihomed host */
2628 /* I'm giving up on multi homed. Too much complex to understand */
2630 if (record->wins_flags&WINS_MHOMED) {
2631 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2632 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2633 overwrite=True;
2635 else {
2636 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2637 overwrite=True;
2639 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2640 if (namerec->data.wins_flags&WINS_UNIQUE)
2641 get_global_id_and_update(&namerec->data.id, True);
2645 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2646 if (namerec->data.wins_flags&WINS_UNIQUE ||
2647 namerec->data.wins_flags&WINS_MHOMED)
2648 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2649 overwrite=True;
2653 if (overwrite == False)
2654 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2655 record->name, record->type, inet_ntoa(record->wins_ip)));
2656 else {
2657 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2658 record->name, record->type, inet_ntoa(record->wins_ip)));
2660 /* remove the old record and add a new one */
2661 remove_name_from_namelist( wins_server_subnet, namerec );
2662 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2663 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2664 if (new_namerec!=NULL) {
2665 update_wins_owner(new_namerec, record->wins_ip);
2666 update_wins_flag(new_namerec, record->wins_flags);
2667 new_namerec->data.id=record->id;
2669 wins_server_subnet->namelist_changed = True;
2672 wins_server_subnet->namelist_changed = True;
2677 #endif