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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Converted to store WINS data in a tdb. Dec 2005. JRA.
26 #define WINS_LIST "wins.dat"
27 #define WINS_VERSION 1
28 #define WINSDB_VERSION 1
30 /****************************************************************************
31 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
32 name (65 bytes with the last byte being the name type).
33 *****************************************************************************/
35 TDB_CONTEXT *wins_tdb;
37 /****************************************************************************
38 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
39 *****************************************************************************/
41 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
43 struct name_record *namerec = NULL;
46 uint32 death_time, refresh_time;
47 uint32 id_low, id_high;
54 if (data.dptr == NULL || data.dsize == 0) {
58 /* Min size is "wbddddddd" + 1 ip address (4). */
59 if (data.dsize < 2 + 1 + (7*4) + 4) {
63 len = tdb_unpack(data.dptr, data.dsize,
75 namerec = SMB_MALLOC_P(struct name_record);
80 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
81 if (!namerec->data.ip) {
86 namerec->subnet = wins_server_subnet;
87 push_ascii_nstring(namerec->name.name, key.dptr);
88 namerec->name.name_type = key.dptr[sizeof(unstring)];
90 push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
92 /* We're using a byte-by-byte compare, so we must be sure that
93 * unused space doesn't have garbage in it.
96 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
97 namerec->name.name[i] = '\0';
99 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
100 namerec->name.scope[i] = '\0';
103 namerec->data.nb_flags = nb_flags;
104 namerec->data.source = (enum name_source)nr_src;
105 namerec->data.death_time = (time_t)death_time;
106 namerec->data.refresh_time = (time_t)refresh_time;
107 namerec->data.id = id_low;
108 #if defined(HAVE_LONGLONG)
109 namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
111 namerec->data.wins_ip.s_addr = saddr;
112 namerec->data.wins_flags = wins_flags,
113 namerec->data.num_ips = num_ips;
115 for (i = 0; i < num_ips; i++) {
116 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
122 /****************************************************************************
123 Convert a struct name_record to a wins.tdb record. Ignore the scope.
124 *****************************************************************************/
126 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
131 uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
132 #if defined(HAVE_LONGLONG)
133 uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
140 len = (2 + 1 + (7*4)); /* "wbddddddd" */
141 len += (namerec->data.num_ips * 4);
143 data.dptr = SMB_MALLOC(len);
149 len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
150 namerec->data.nb_flags,
151 (unsigned char)namerec->data.source,
152 (uint32)namerec->data.death_time,
153 (uint32)namerec->data.refresh_time,
156 (uint32)namerec->data.wins_ip.s_addr,
157 (uint32)namerec->data.wins_flags,
158 (uint32)namerec->data.num_ips );
160 for (i = 0; i < namerec->data.num_ips; i++) {
161 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
167 /****************************************************************************
168 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
169 *****************************************************************************/
171 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
173 static char keydata[sizeof(unstring) + 1];
176 memset(keydata, '\0', sizeof(keydata));
178 pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
180 keydata[sizeof(unstring)] = nmbname->name_type;
182 key.dsize = sizeof(keydata);
187 /****************************************************************************
188 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
189 on the linked list. We will free this later in XXXX().
190 *****************************************************************************/
192 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
195 struct name_record *nr = NULL;
196 struct name_record *namerec = NULL;
202 key = name_to_key(nmbname);
203 data = tdb_fetch(wins_tdb, key);
205 if (data.dsize == 0) {
209 namerec = wins_record_to_name_record(key, data);
211 /* done with the this */
213 SAFE_FREE( data.dptr );
219 /* Search for this name record on the list. Replace it if found. */
221 for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
222 if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
224 DLIST_REMOVE(wins_server_subnet->namelist, nr);
225 SAFE_FREE(nr->data.ip);
231 DLIST_ADD(wins_server_subnet->namelist, namerec);
235 /****************************************************************************
236 Overwrite or add a given name in the wins.tdb.
237 *****************************************************************************/
239 static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
248 key = name_to_key(&namerec->name);
249 data = name_record_to_wins_record(namerec);
251 if (data.dptr == NULL) {
255 ret = tdb_store(wins_tdb, key, data, tdb_flag);
257 SAFE_FREE(data.dptr);
258 return (ret == 0) ? True : False;
261 /****************************************************************************
262 Overwrite a given name in the wins.tdb.
263 *****************************************************************************/
265 BOOL wins_store_changed_namerec(const struct name_record *namerec)
267 return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
270 /****************************************************************************
271 Primary interface into creating and overwriting records in the wins.tdb.
272 *****************************************************************************/
274 BOOL add_name_to_wins_subnet(const struct name_record *namerec)
276 return store_or_replace_wins_namerec(namerec, TDB_INSERT);
279 /****************************************************************************
280 Delete a given name in the tdb and remove the temporary malloc'ed data struct
282 *****************************************************************************/
284 BOOL remove_name_from_wins_namelist(struct name_record *namerec)
293 key = name_to_key(&namerec->name);
294 ret = tdb_delete(wins_tdb, key);
296 DLIST_REMOVE(wins_server_subnet->namelist, namerec);
297 SAFE_FREE(namerec->data.ip);
299 /* namerec must be freed by the caller */
301 return (ret == 0) ? True : False;
304 /****************************************************************************
305 Dump out the complete namelist.
306 *****************************************************************************/
308 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
310 struct name_record *namerec = NULL;
311 XFILE *fp = (XFILE *)state;
313 if (kbuf.dsize != sizeof(unstring) + 1) {
317 namerec = wins_record_to_name_record(kbuf, dbuf);
322 dump_name_record(namerec, fp);
324 SAFE_FREE(namerec->data.ip);
329 void dump_wins_subnet_namelist(XFILE *fp)
331 tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
334 /****************************************************************************
335 Change the wins owner address in the record.
336 *****************************************************************************/
338 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
340 namerec->data.wins_ip=wins_ip;
343 /****************************************************************************
344 Create the wins flags based on the nb flags and the input value.
345 *****************************************************************************/
347 static void update_wins_flag(struct name_record *namerec, int flags)
349 namerec->data.wins_flags=0x0;
351 /* if it's a group, it can be a normal or a special one */
352 if (namerec->data.nb_flags & NB_GROUP) {
353 if (namerec->name.name_type==0x1C) {
354 namerec->data.wins_flags|=WINS_SGROUP;
356 if (namerec->data.num_ips>1) {
357 namerec->data.wins_flags|=WINS_SGROUP;
359 namerec->data.wins_flags|=WINS_NGROUP;
363 /* can be unique or multi-homed */
364 if (namerec->data.num_ips>1) {
365 namerec->data.wins_flags|=WINS_MHOMED;
367 namerec->data.wins_flags|=WINS_UNIQUE;
371 /* the node type are the same bits */
372 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
374 /* the static bit is elsewhere */
375 if (namerec->data.death_time == PERMANENT_TTL) {
376 namerec->data.wins_flags|=WINS_STATIC;
379 /* and add the given bits */
380 namerec->data.wins_flags|=flags;
382 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
383 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
386 /****************************************************************************
387 Return the general ID value and increase it if requested.
388 *****************************************************************************/
390 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
393 * it's kept as a static here, to prevent people from messing
394 * with the value directly
397 static SMB_BIG_UINT general_id = 1;
399 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
401 *current_id = general_id;
408 /****************************************************************************
409 Possibly call the WINS hook external program when a WINS change is made.
410 Also stores the changed record back in the wins_tdb.
411 *****************************************************************************/
413 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
416 char *cmd = lp_wins_hook();
420 wins_store_changed_namerec(namerec);
426 for (p=namerec->name.name; *p; p++) {
427 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
428 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
433 /* Use the name without the nametype (and scope) appended */
435 namestr = nmb_namestr(&namerec->name);
436 if ((p = strchr(namestr, '<'))) {
441 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
445 namerec->name.name_type,
448 for (i=0;i<namerec->data.num_ips;i++) {
449 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
452 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
453 smbrun(command, NULL);
456 /****************************************************************************
457 Determine if this packet should be allocated to the WINS server.
458 *****************************************************************************/
460 BOOL packet_is_for_wins_server(struct packet_struct *packet)
462 struct nmb_packet *nmb = &packet->packet.nmb;
464 /* Only unicast packets go to a WINS server. */
465 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
466 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
470 /* Check for node status requests. */
471 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
475 switch(nmb->header.opcode) {
477 * A WINS server issues WACKS, not receives them.
479 case NMB_WACK_OPCODE:
480 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
483 * A WINS server only processes registration and
484 * release requests, not responses.
486 case NMB_NAME_REG_OPCODE:
487 case NMB_NAME_MULTIHOMED_REG_OPCODE:
488 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
489 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
490 if(nmb->header.response) {
491 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
496 case NMB_NAME_RELEASE_OPCODE:
497 if(nmb->header.response) {
498 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
504 * Only process unicast name queries with rd = 1.
506 case NMB_NAME_QUERY_OPCODE:
507 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
508 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
517 /****************************************************************************
518 Utility function to decide what ttl to give a register/refresh request.
519 *****************************************************************************/
521 static int get_ttl_from_packet(struct nmb_packet *nmb)
523 int ttl = nmb->additional->ttl;
525 if (ttl < lp_min_wins_ttl()) {
526 ttl = lp_min_wins_ttl();
529 if (ttl > lp_max_wins_ttl()) {
530 ttl = lp_max_wins_ttl();
536 /****************************************************************************
537 Load or create the WINS database.
538 *****************************************************************************/
540 BOOL initialise_wins(void)
542 time_t time_now = time(NULL);
546 if(!lp_we_are_a_wins_server()) {
550 /* Open the wins.tdb. */
551 wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
553 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
558 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
560 add_samba_names_to_subnet(wins_server_subnet);
562 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
563 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
564 WINS_LIST, strerror(errno) ));
568 while (!x_feof(fp)) {
569 pstring name_str, ip_str, ttl_str, nb_flags_str;
570 unsigned int num_ips;
572 struct in_addr *ip_list;
584 /* Read a line from the wins.dat file. Strips whitespace
585 from the beginning and end of the line. */
586 if (!fgets_slash(line,sizeof(pstring),fp))
592 if (strncmp(line,"VERSION ", 8) == 0) {
593 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
594 version != WINS_VERSION) {
595 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
605 * Now we handle multiple IP addresses per name we need
606 * to iterate over the line twice. The first time to
607 * determine how many IP addresses there are, the second
608 * time to actually parse them into the ip_list array.
611 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
612 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
616 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
617 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
622 * Determine the number of IP addresses per line.
626 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
629 if(got_token && strchr(ip_str, '.')) {
633 } while( got_token && was_ip);
636 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
641 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
645 /* Allocate the space for the ip_list. */
646 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
647 DEBUG(0,("initialise_wins: Malloc fail !\n"));
651 /* Reset and re-parse the line. */
653 next_token(&ptr,name_str,NULL,sizeof(name_str));
654 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
655 for(i = 0; i < num_ips; i++) {
656 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
657 ip_list[i] = *interpret_addr2(ip_str);
659 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
662 * Deal with SELF or REGISTER name encoding. Default is REGISTER
663 * for compatibility with old nmbds.
666 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
667 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
672 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
673 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
676 /* Netbios name. # divides the name from the type (hex): netbios#xx */
677 pstrcpy(name,name_str);
679 if((p = strchr(name,'#')) != NULL) {
681 sscanf(p+1,"%x",&type);
684 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
685 sscanf(nb_flags_str,"%x",&nb_flags);
686 sscanf(ttl_str,"%d",&ttl);
688 /* add all entries that have 60 seconds or more to live */
689 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
690 if(ttl != PERMANENT_TTL) {
694 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
695 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
697 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
698 ttl, REGISTER_NAME, num_ips, ip_list );
700 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
701 "%s#%02x ttl = %d first IP %s flags = %2x\n",
702 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
712 /****************************************************************************
713 Send a WINS WACK (Wait ACKnowledgement) response.
714 **************************************************************************/
716 static void send_wins_wack_response(int ttl, struct packet_struct *p)
718 struct nmb_packet *nmb = &p->packet.nmb;
719 unsigned char rdata[2];
721 rdata[0] = rdata[1] = 0;
723 /* Taken from nmblib.c - we need to send back almost
724 identical bytes from the requesting packet header. */
726 rdata[0] = (nmb->header.opcode & 0xF) << 3;
727 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
730 if (nmb->header.nm_flags.trunc) {
733 if (nmb->header.nm_flags.recursion_desired) {
736 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
739 if (nmb->header.nm_flags.bcast) {
743 reply_netbios_packet(p, /* Packet to reply to. */
744 0, /* Result code. */
745 NMB_WAIT_ACK, /* nmbd type code. */
746 NMB_WACK_OPCODE, /* opcode. */
748 (char *)rdata, /* data to send. */
749 2); /* data length. */
752 /****************************************************************************
753 Send a WINS name registration response.
754 **************************************************************************/
756 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
758 struct nmb_packet *nmb = &p->packet.nmb;
761 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
763 reply_netbios_packet(p, /* Packet to reply to. */
764 rcode, /* Result code. */
765 WINS_REG, /* nmbd type code. */
766 NMB_NAME_REG_OPCODE, /* opcode. */
768 rdata, /* data to send. */
769 6); /* data length. */
772 /***********************************************************************
773 Deal with a name refresh request to a WINS server.
774 ************************************************************************/
776 void wins_process_name_refresh_request( struct subnet_record *subrec,
777 struct packet_struct *p )
779 struct nmb_packet *nmb = &p->packet.nmb;
780 struct nmb_name *question = &nmb->question.question_name;
781 BOOL bcast = nmb->header.nm_flags.bcast;
782 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
783 BOOL group = (nb_flags & NB_GROUP) ? True : False;
784 struct name_record *namerec = NULL;
785 int ttl = get_ttl_from_packet(nmb);
786 struct in_addr from_ip;
787 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
789 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
793 * We should only get unicast name refresh packets here.
794 * Anyone trying to refresh broadcast should not be going
795 * to a WINS server. Log an error here.
797 if( DEBUGLVL( 0 ) ) {
798 dbgtext( "wins_process_name_refresh_request: " );
799 dbgtext( "Broadcast name refresh request received " );
800 dbgtext( "for name %s ", nmb_namestr(question) );
801 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
802 dbgtext( "on subnet %s. ", subrec->subnet_name );
803 dbgtext( "Error - Broadcasts should not be sent " );
804 dbgtext( "to a WINS server\n" );
809 if( DEBUGLVL( 3 ) ) {
810 dbgtext( "wins_process_name_refresh_request: " );
811 dbgtext( "Name refresh for name %s IP %s\n",
812 nmb_namestr(question), inet_ntoa(from_ip) );
816 * See if the name already exists.
817 * If not, handle it as a name registration and return.
819 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
822 * If this is a refresh request and the name doesn't exist then
823 * treat it like a registration request. This allows us to recover
824 * from errors (tridge)
826 if(namerec == NULL) {
827 if( DEBUGLVL( 3 ) ) {
828 dbgtext( "wins_process_name_refresh_request: " );
829 dbgtext( "Name refresh for name %s ",
830 nmb_namestr( question ) );
831 dbgtext( "and the name does not exist. Treating " );
832 dbgtext( "as registration.\n" );
834 wins_process_name_registration_request(subrec,p);
839 * if the name is present but not active, simply remove it
840 * and treat the refresh request as a registration & return.
842 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
843 if( DEBUGLVL( 5 ) ) {
844 dbgtext( "wins_process_name_refresh_request: " );
845 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
846 dbgtext( "was not active - removing it.\n" );
848 remove_name_from_namelist( subrec, namerec );
850 wins_process_name_registration_request( subrec, p );
855 * Check that the group bits for the refreshing name and the
856 * name in our database match. If not, refuse the refresh.
857 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
859 if( (namerec != NULL) &&
860 ( (group && !NAME_GROUP(namerec))
861 || (!group && NAME_GROUP(namerec)) ) ) {
862 if( DEBUGLVL( 3 ) ) {
863 dbgtext( "wins_process_name_refresh_request: " );
864 dbgtext( "Name %s ", nmb_namestr(question) );
865 dbgtext( "group bit = %s does not match ",
866 group ? "True" : "False" );
867 dbgtext( "group bit in WINS for this name.\n" );
869 send_wins_name_registration_response(RFS_ERR, 0, p);
874 * For a unique name check that the person refreshing the name is
875 * one of the registered IP addresses. If not - fail the refresh.
876 * Do the same for group names with a type of 0x1c.
877 * Just return success for unique 0x1d refreshes. For normal group
878 * names update the ttl and return success.
880 if( (!group || (group && (question->name_type == 0x1c)))
881 && find_ip_in_name_record(namerec, from_ip) ) {
885 update_name_ttl(namerec, ttl);
888 * if the record is a replica:
889 * we take ownership and update the version ID.
891 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
892 update_wins_owner(namerec, our_fake_ip);
893 get_global_id_and_update(&namerec->data.id, True);
896 send_wins_name_registration_response(0, ttl, p);
897 wins_hook("refresh", namerec, ttl);
899 } else if((group && (question->name_type == 0x1c))) {
901 * Added by crh for bug #1079.
902 * Fix from Bert Driehuis
904 if( DEBUGLVL( 3 ) ) {
905 dbgtext( "wins_process_name_refresh_request: " );
906 dbgtext( "Name refresh for name %s, ",
907 nmb_namestr(question) );
908 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
909 dbgtext( "is not yet associated with " );
910 dbgtext( "that name. Treating as registration.\n" );
912 wins_process_name_registration_request(subrec,p);
916 * Normal groups are all registered with an IP address of
917 * 255.255.255.255 so we can't search for the IP address.
919 update_name_ttl(namerec, ttl);
920 wins_hook("refresh", namerec, ttl);
921 send_wins_name_registration_response(0, ttl, p);
923 } else if(!group && (question->name_type == 0x1d)) {
925 * Special name type - just pretend the refresh succeeded.
927 send_wins_name_registration_response(0, ttl, p);
933 if( DEBUGLVL( 3 ) ) {
934 dbgtext( "wins_process_name_refresh_request: " );
935 dbgtext( "Name refresh for name %s with IP %s ",
936 nmb_namestr(question), inet_ntoa(from_ip) );
937 dbgtext( "and is IP is not known to the name.\n" );
939 send_wins_name_registration_response(RFS_ERR, 0, p);
944 /***********************************************************************
945 Deal with a name registration request query success to a client that
948 We have a locked pointer to the original packet stashed away in the
949 userdata pointer. The success here is actually a failure as it means
950 the client we queried wants to keep the name, so we must return
951 a registration failure to the original requestor.
952 ************************************************************************/
954 static void wins_register_query_success(struct subnet_record *subrec,
955 struct userdata_struct *userdata,
956 struct nmb_name *question_name,
958 struct res_rec *answers)
960 struct packet_struct *orig_reg_packet;
962 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
964 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
965 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
967 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
969 orig_reg_packet->locked = False;
970 free_packet(orig_reg_packet);
973 /***********************************************************************
974 Deal with a name registration request query failure to a client that
977 We have a locked pointer to the original packet stashed away in the
978 userdata pointer. The failure here is actually a success as it means
979 the client we queried didn't want to keep the name, so we can remove
980 the old name record and then successfully add the new name.
981 ************************************************************************/
983 static void wins_register_query_fail(struct subnet_record *subrec,
984 struct response_record *rrec,
985 struct nmb_name *question_name,
988 struct userdata_struct *userdata = rrec->userdata;
989 struct packet_struct *orig_reg_packet;
990 struct name_record *namerec = NULL;
992 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
995 * We want to just add the name, as we now know the original owner
996 * didn't want it. But we can't just do that as an arbitary
997 * amount of time may have taken place between the name query
998 * request and this timeout/error response. So we check that
999 * the name still exists and is in the same state - if so
1000 * we remove it and call wins_process_name_registration_request()
1001 * as we know it will do the right thing now.
1004 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1006 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1007 ip_equal(rrec->packet->ip, *namerec->data.ip)) {
1008 remove_name_from_namelist( subrec, namerec);
1012 if(namerec == NULL) {
1013 wins_process_name_registration_request(subrec, orig_reg_packet);
1015 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1016 "querying for name %s in order to replace it and this reply.\n",
1017 nmb_namestr(question_name) ));
1020 orig_reg_packet->locked = False;
1021 free_packet(orig_reg_packet);
1024 /***********************************************************************
1025 Deal with a name registration request to a WINS server.
1027 Use the following pseudocode :
1032 +--------name exists
1035 | +--- existing name is group
1038 | | +--- add name (return).
1041 | +--- exiting name is unique
1044 | +--- query existing owner (return).
1047 +--------name doesn't exist
1050 +--- add name (return).
1055 +--------name exists
1058 | +--- existing name is group
1061 | | +--- fail add (return).
1064 | +--- exiting name is unique
1067 | +--- query existing owner (return).
1070 +--------name doesn't exist
1073 +--- add name (return).
1075 As can be seen from the above, the two cases may be collapsed onto each
1076 other with the exception of the case where the name already exists and
1077 is a group name. This case we handle with an if statement.
1079 ************************************************************************/
1081 void wins_process_name_registration_request(struct subnet_record *subrec,
1082 struct packet_struct *p)
1085 struct nmb_packet *nmb = &p->packet.nmb;
1086 struct nmb_name *question = &nmb->question.question_name;
1087 BOOL bcast = nmb->header.nm_flags.bcast;
1088 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1089 int ttl = get_ttl_from_packet(nmb);
1090 struct name_record *namerec = NULL;
1091 struct in_addr from_ip;
1092 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1093 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1095 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1099 * We should only get unicast name registration packets here.
1100 * Anyone trying to register broadcast should not be going to a WINS
1101 * server. Log an error here.
1104 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1105 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1106 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1110 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1111 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1114 * See if the name already exists.
1117 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1120 * if the record exists but NOT in active state,
1123 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1124 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1125 not active - removing it.\n", nmb_namestr(question) ));
1126 remove_name_from_namelist( subrec, namerec );
1131 * Deal with the case where the name found was a dns entry.
1132 * Remove it as we now have a NetBIOS client registering the
1136 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1137 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1138 a dns lookup - removing it.\n", nmb_namestr(question) ));
1139 remove_name_from_namelist( subrec, namerec );
1144 * Reject if the name exists and is not a REGISTER_NAME.
1145 * (ie. Don't allow any static names to be overwritten.
1148 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1149 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1150 to register name %s. Name already exists in WINS with source type %d.\n",
1151 nmb_namestr(question), namerec->data.source ));
1152 send_wins_name_registration_response(RFS_ERR, 0, p);
1157 * Special policy decisions based on MS documentation.
1158 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1159 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1163 * A group name is always added as the local broadcast address, except
1164 * for group names ending in 0x1c.
1165 * Group names with type 0x1c are registered with individual IP addresses.
1168 if(registering_group_name && (question->name_type != 0x1c)) {
1169 from_ip = *interpret_addr2("255.255.255.255");
1173 * Ignore all attempts to register a unique 0x1d name, although return success.
1176 if(!registering_group_name && (question->name_type == 0x1d)) {
1177 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1178 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1179 send_wins_name_registration_response(0, ttl, p);
1184 * Next two cases are the 'if statement' mentioned above.
1187 if((namerec != NULL) && NAME_GROUP(namerec)) {
1188 if(registering_group_name) {
1190 * If we are adding a group name, the name exists and is also a group entry just add this
1191 * IP address to it and update the ttl.
1194 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1195 inet_ntoa(from_ip), nmb_namestr(question) ));
1198 * Check the ip address is not already in the group.
1201 if(!find_ip_in_name_record(namerec, from_ip)) {
1202 add_ip_to_name_record(namerec, from_ip);
1203 /* we need to update the record for replication */
1204 get_global_id_and_update(&namerec->data.id, True);
1207 * if the record is a replica, we must change
1208 * the wins owner to us to make the replication updates
1209 * it on the other wins servers.
1210 * And when the partner will receive this record,
1211 * it will update its own record.
1214 update_wins_owner(namerec, our_fake_ip);
1216 update_name_ttl(namerec, ttl);
1217 wins_hook("refresh", namerec, ttl);
1218 send_wins_name_registration_response(0, ttl, p);
1223 * If we are adding a unique name, the name exists in the WINS db
1224 * and is a group name then reject the registration.
1226 * explanation: groups have a higher priority than unique names.
1229 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1230 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1231 send_wins_name_registration_response(RFS_ERR, 0, p);
1237 * From here on down we know that if the name exists in the WINS db it is
1238 * a unique name, not a group name.
1242 * If the name exists and is one of our names then check the
1243 * registering IP address. If it's not one of ours then automatically
1244 * reject without doing the query - we know we will reject it.
1247 if ( namerec != NULL ) {
1248 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1249 if( is_myname(name) ) {
1250 if(!ismyip(from_ip)) {
1251 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1252 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1253 send_wins_name_registration_response(RFS_ERR, 0, p);
1257 * It's one of our names and one of our IP's - update the ttl.
1259 update_name_ttl(namerec, ttl);
1260 wins_hook("refresh", namerec, ttl);
1261 send_wins_name_registration_response(0, ttl, p);
1270 * If the name exists and it is a unique registration and the registering IP
1271 * is the same as the (single) already registered IP then just update the ttl.
1273 * But not if the record is an active replica. IF it's a replica, it means it can be
1274 * the same client which has moved and not yet expired. So we don't update
1275 * the ttl in this case and go beyond to do a WACK and query the old client
1278 if( !registering_group_name
1279 && (namerec != NULL)
1280 && (namerec->data.num_ips == 1)
1281 && ip_equal( namerec->data.ip[0], from_ip )
1282 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
1283 update_name_ttl( namerec, ttl );
1284 wins_hook("refresh", namerec, ttl);
1285 send_wins_name_registration_response( 0, ttl, p );
1290 * Finally if the name exists do a query to the registering machine
1291 * to see if they still claim to have the name.
1294 if( namerec != NULL ) {
1295 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1296 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1299 * First send a WACK to the registering machine.
1302 send_wins_wack_response(60, p);
1305 * When the reply comes back we need the original packet.
1306 * Lock this so it won't be freed and then put it into
1307 * the userdata structure.
1312 userdata = (struct userdata_struct *)ud;
1314 userdata->copy_fn = NULL;
1315 userdata->free_fn = NULL;
1316 userdata->userdata_len = sizeof(struct packet_struct *);
1317 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1320 * Use the new call to send a query directly to an IP address.
1321 * This sends the query directly to the IP address, and ensures
1322 * the recursion desired flag is not set (you were right Luke :-).
1323 * This function should *only* be called from the WINS server
1327 pull_ascii_nstring(name, sizeof(name), question->name);
1328 query_name_from_wins_server( *namerec->data.ip,
1330 question->name_type,
1331 wins_register_query_success,
1332 wins_register_query_fail,
1338 * Name did not exist - add it.
1341 pull_ascii_nstring(name, sizeof(name), question->name);
1342 add_name_to_subnet( subrec, name, question->name_type,
1343 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1345 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1346 get_global_id_and_update(&namerec->data.id, True);
1347 update_wins_owner(namerec, our_fake_ip);
1348 update_wins_flag(namerec, WINS_ACTIVE);
1349 wins_hook("add", namerec, ttl);
1352 send_wins_name_registration_response(0, ttl, p);
1355 /***********************************************************************
1356 Deal with a mutihomed name query success to the machine that
1357 requested the multihomed name registration.
1359 We have a locked pointer to the original packet stashed away in the
1361 ************************************************************************/
1363 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1364 struct userdata_struct *userdata,
1365 struct nmb_name *question_name,
1367 struct res_rec *answers)
1369 struct packet_struct *orig_reg_packet;
1370 struct nmb_packet *nmb;
1371 struct name_record *namerec = NULL;
1372 struct in_addr from_ip;
1374 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1376 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1378 nmb = &orig_reg_packet->packet.nmb;
1380 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1381 ttl = get_ttl_from_packet(nmb);
1384 * We want to just add the new IP, as we now know the requesting
1385 * machine claims to own it. But we can't just do that as an arbitary
1386 * amount of time may have taken place between the name query
1387 * request and this response. So we check that
1388 * the name still exists and is in the same state - if so
1389 * we just add the extra IP and update the ttl.
1392 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1394 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1395 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1396 a subsequent IP address.\n", nmb_namestr(question_name) ));
1397 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1399 orig_reg_packet->locked = False;
1400 free_packet(orig_reg_packet);
1405 if(!find_ip_in_name_record(namerec, from_ip)) {
1406 add_ip_to_name_record(namerec, from_ip);
1409 get_global_id_and_update(&namerec->data.id, True);
1410 update_wins_owner(namerec, our_fake_ip);
1411 update_wins_flag(namerec, WINS_ACTIVE);
1412 update_name_ttl(namerec, ttl);
1413 wins_hook("add", namerec, ttl);
1414 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1416 orig_reg_packet->locked = False;
1417 free_packet(orig_reg_packet);
1420 /***********************************************************************
1421 Deal with a name registration request query failure to a client that
1424 We have a locked pointer to the original packet stashed away in the
1426 ************************************************************************/
1428 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1429 struct response_record *rrec,
1430 struct nmb_name *question_name,
1433 struct userdata_struct *userdata = rrec->userdata;
1434 struct packet_struct *orig_reg_packet;
1436 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1438 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1439 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1440 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1442 orig_reg_packet->locked = False;
1443 free_packet(orig_reg_packet);
1447 /***********************************************************************
1448 Deal with a multihomed name registration request to a WINS server.
1449 These cannot be group name registrations.
1450 ***********************************************************************/
1452 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1453 struct packet_struct *p)
1455 struct nmb_packet *nmb = &p->packet.nmb;
1456 struct nmb_name *question = &nmb->question.question_name;
1457 BOOL bcast = nmb->header.nm_flags.bcast;
1458 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1459 int ttl = get_ttl_from_packet(nmb);
1460 struct name_record *namerec = NULL;
1461 struct in_addr from_ip;
1462 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1463 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1466 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1470 * We should only get unicast name registration packets here.
1471 * Anyone trying to register broadcast should not be going to a WINS
1472 * server. Log an error here.
1475 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1476 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1477 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1482 * Only unique names should be registered multihomed.
1486 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1487 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1488 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1492 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1493 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1496 * Deal with policy regarding 0x1d names.
1499 if(question->name_type == 0x1d) {
1500 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1501 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1502 send_wins_name_registration_response(0, ttl, p);
1507 * See if the name already exists.
1510 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1513 * if the record exists but NOT in active state,
1517 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1518 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1519 remove_name_from_namelist(subrec, namerec);
1524 * Deal with the case where the name found was a dns entry.
1525 * Remove it as we now have a NetBIOS client registering the
1529 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1530 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1531 - removing it.\n", nmb_namestr(question) ));
1532 remove_name_from_namelist( subrec, namerec);
1537 * Reject if the name exists and is not a REGISTER_NAME.
1538 * (ie. Don't allow any static names to be overwritten.
1541 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1542 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1543 to register name %s. Name already exists in WINS with source type %d.\n",
1544 nmb_namestr(question), namerec->data.source ));
1545 send_wins_name_registration_response(RFS_ERR, 0, p);
1550 * Reject if the name exists and is a GROUP name and is active.
1553 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1554 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1555 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1556 send_wins_name_registration_response(RFS_ERR, 0, p);
1561 * From here on down we know that if the name exists in the WINS db it is
1562 * a unique name, not a group name.
1566 * If the name exists and is one of our names then check the
1567 * registering IP address. If it's not one of ours then automatically
1568 * reject without doing the query - we know we will reject it.
1571 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1572 if(!ismyip(from_ip)) {
1573 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1574 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1575 send_wins_name_registration_response(RFS_ERR, 0, p);
1579 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1580 * update the ttl. Update the version ID to force replication.
1582 update_name_ttl(namerec, ttl);
1584 if(!find_ip_in_name_record(namerec, from_ip)) {
1585 get_global_id_and_update(&namerec->data.id, True);
1586 update_wins_owner(namerec, our_fake_ip);
1587 update_wins_flag(namerec, WINS_ACTIVE);
1589 add_ip_to_name_record(namerec, from_ip);
1592 wins_hook("refresh", namerec, ttl);
1593 send_wins_name_registration_response(0, ttl, p);
1599 * If the name exists and is active, check if the IP address is already registered
1600 * to that name. If so then update the ttl and reply success.
1603 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1604 update_name_ttl(namerec, ttl);
1607 * If it's a replica, we need to become the wins owner
1608 * to force the replication
1610 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1611 get_global_id_and_update(&namerec->data.id, True);
1612 update_wins_owner(namerec, our_fake_ip);
1613 update_wins_flag(namerec, WINS_ACTIVE);
1616 wins_hook("refresh", namerec, ttl);
1617 send_wins_name_registration_response(0, ttl, p);
1622 * If the name exists do a query to the owner
1623 * to see if they still want the name.
1626 if(namerec != NULL) {
1627 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1628 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1631 * First send a WACK to the registering machine.
1634 send_wins_wack_response(60, p);
1637 * When the reply comes back we need the original packet.
1638 * Lock this so it won't be freed and then put it into
1639 * the userdata structure.
1644 userdata = (struct userdata_struct *)ud;
1646 userdata->copy_fn = NULL;
1647 userdata->free_fn = NULL;
1648 userdata->userdata_len = sizeof(struct packet_struct *);
1649 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1652 * Use the new call to send a query directly to an IP address.
1653 * This sends the query directly to the IP address, and ensures
1654 * the recursion desired flag is not set (you were right Luke :-).
1655 * This function should *only* be called from the WINS server
1658 * Note that this packet is sent to the current owner of the name,
1659 * not the person who sent the packet
1662 pull_ascii_nstring( qname, sizeof(qname), question->name);
1663 query_name_from_wins_server( namerec->data.ip[0],
1665 question->name_type,
1666 wins_multihomed_register_query_success,
1667 wins_multihomed_register_query_fail,
1674 * Name did not exist - add it.
1677 pull_ascii_nstring( qname, sizeof(qname), question->name);
1678 add_name_to_subnet( subrec, qname, question->name_type,
1679 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1681 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1682 get_global_id_and_update(&namerec->data.id, True);
1683 update_wins_owner(namerec, our_fake_ip);
1684 update_wins_flag(namerec, WINS_ACTIVE);
1685 wins_hook("add", namerec, ttl);
1688 send_wins_name_registration_response(0, ttl, p);
1691 /***********************************************************************
1692 Fetch all *<1b> names from the WINS db and store on the namelist.
1693 ***********************************************************************/
1695 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1697 struct name_record *namerec = NULL;
1699 if (kbuf.dsize != sizeof(unstring) + 1) {
1703 /* Filter out all non-1b names. */
1704 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1708 namerec = wins_record_to_name_record(kbuf, dbuf);
1713 DLIST_ADD(wins_server_subnet->namelist, namerec);
1717 void fetch_all_active_wins_1b_names(void)
1719 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1722 /***********************************************************************
1723 Deal with the special name query for *<1b>.
1724 ***********************************************************************/
1726 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1727 struct packet_struct *p)
1729 struct name_record *namerec = NULL;
1734 * Go through all the ACTIVE names in the WINS db looking for those
1735 * ending in <1b>. Use this to calculate the number of IP
1736 * addresses we need to return.
1741 fetch_all_active_wins_1b_names();
1743 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1744 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1745 num_ips += namerec->data.num_ips;
1751 * There are no 0x1b names registered. Return name query fail.
1753 send_wins_name_query_response(NAM_ERR, p, NULL);
1757 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1758 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1763 * Go through all the names again in the WINS db looking for those
1764 * ending in <1b>. Add their IP addresses into the list we will
1769 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1770 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1772 for(i = 0; i < namerec->data.num_ips; i++) {
1773 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1774 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1781 * Send back the reply containing the IP list.
1784 reply_netbios_packet(p, /* Packet to reply to. */
1785 0, /* Result code. */
1786 WINS_QUERY, /* nmbd type code. */
1787 NMB_NAME_QUERY_OPCODE, /* opcode. */
1788 lp_min_wins_ttl(), /* ttl. */
1789 prdata, /* data to send. */
1790 num_ips*6); /* data length. */
1795 /****************************************************************************
1796 Send a WINS name query response.
1797 **************************************************************************/
1799 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1800 struct name_record *namerec)
1803 char *prdata = rdata;
1804 int reply_data_len = 0;
1808 memset(rdata,'\0',6);
1811 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1813 /* Copy all known ip addresses into the return data. */
1814 /* Optimise for the common case of one IP address so we don't need a malloc. */
1816 if( namerec->data.num_ips == 1 ) {
1819 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1820 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1825 for(i = 0; i < namerec->data.num_ips; i++) {
1826 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1827 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1830 sort_query_replies(prdata, i, p->ip);
1831 reply_data_len = namerec->data.num_ips * 6;
1834 reply_netbios_packet(p, /* Packet to reply to. */
1835 rcode, /* Result code. */
1836 WINS_QUERY, /* nmbd type code. */
1837 NMB_NAME_QUERY_OPCODE, /* opcode. */
1839 prdata, /* data to send. */
1840 reply_data_len); /* data length. */
1842 if(prdata != rdata) {
1847 /***********************************************************************
1848 Deal with a name query.
1849 ***********************************************************************/
1851 void wins_process_name_query_request(struct subnet_record *subrec,
1852 struct packet_struct *p)
1854 struct nmb_packet *nmb = &p->packet.nmb;
1855 struct nmb_name *question = &nmb->question.question_name;
1856 struct name_record *namerec = NULL;
1859 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1860 nmb_namestr(question), inet_ntoa(p->ip) ));
1863 * Special name code. If the queried name is *<1b> then search
1864 * the entire WINS database and return a list of all the IP addresses
1865 * registered to any <1b> name. This is to allow domain master browsers
1866 * to discover other domains that may not have a presence on their subnet.
1869 pull_ascii_nstring(qname, sizeof(qname), question->name);
1870 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1871 process_wins_dmb_query_request( subrec, p);
1875 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1877 if(namerec != NULL) {
1879 * If the name is not anymore in active state then reply not found.
1880 * it's fair even if we keep it in the cache for days.
1882 if (!WINS_STATE_ACTIVE(namerec)) {
1883 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1884 nmb_namestr(question) ));
1885 send_wins_name_query_response(NAM_ERR, p, namerec);
1890 * If it's a DNSFAIL_NAME then reply name not found.
1893 if( namerec->data.source == DNSFAIL_NAME ) {
1894 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1895 nmb_namestr(question) ));
1896 send_wins_name_query_response(NAM_ERR, p, namerec);
1901 * If the name has expired then reply name not found.
1904 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1905 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1906 nmb_namestr(question) ));
1907 send_wins_name_query_response(NAM_ERR, p, namerec);
1911 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1912 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1914 send_wins_name_query_response(0, p, namerec);
1919 * Name not found in WINS - try a dns query if it's a 0x20 name.
1922 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1923 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1924 nmb_namestr(question) ));
1926 queue_dns_query(p, question);
1931 * Name not found - return error.
1934 send_wins_name_query_response(NAM_ERR, p, NULL);
1937 /****************************************************************************
1938 Send a WINS name release response.
1939 **************************************************************************/
1941 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1943 struct nmb_packet *nmb = &p->packet.nmb;
1946 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1948 reply_netbios_packet(p, /* Packet to reply to. */
1949 rcode, /* Result code. */
1950 NMB_REL, /* nmbd type code. */
1951 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1953 rdata, /* data to send. */
1954 6); /* data length. */
1957 /***********************************************************************
1958 Deal with a name release.
1959 ***********************************************************************/
1961 void wins_process_name_release_request(struct subnet_record *subrec,
1962 struct packet_struct *p)
1964 struct nmb_packet *nmb = &p->packet.nmb;
1965 struct nmb_name *question = &nmb->question.question_name;
1966 BOOL bcast = nmb->header.nm_flags.bcast;
1967 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1968 struct name_record *namerec = NULL;
1969 struct in_addr from_ip;
1970 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1972 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1976 * We should only get unicast name registration packets here.
1977 * Anyone trying to register broadcast should not be going to a WINS
1978 * server. Log an error here.
1981 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1982 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1983 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1987 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1988 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1991 * Deal with policy regarding 0x1d names.
1994 if(!releasing_group_name && (question->name_type == 0x1d)) {
1995 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1996 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1997 send_wins_name_release_response(0, p);
2002 * See if the name already exists.
2005 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2007 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2008 send_wins_name_release_response(NAM_ERR, p);
2013 * Check that the sending machine has permission to release this name.
2014 * If it's a group name not ending in 0x1c then just say yes and let
2015 * the group time out.
2018 if(releasing_group_name && (question->name_type != 0x1c)) {
2019 send_wins_name_release_response(0, p);
2024 * Check that the releasing node is on the list of IP addresses
2025 * for this name. Disallow the release if not.
2028 if(!find_ip_in_name_record(namerec, from_ip)) {
2029 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2030 release name %s as IP %s is not one of the known IP's for this name.\n",
2031 nmb_namestr(question), inet_ntoa(from_ip) ));
2032 send_wins_name_release_response(NAM_ERR, p);
2037 * Check if the record is active. IF it's already released
2038 * or tombstoned, refuse the release.
2041 if (!WINS_STATE_ACTIVE(namerec)) {
2042 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2043 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2044 send_wins_name_release_response(NAM_ERR, p);
2049 * Check if the record is a 0x1c group
2050 * and has more then one ip
2051 * remove only this address.
2054 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2055 remove_ip_from_name_record(namerec, from_ip);
2056 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2057 inet_ntoa(from_ip),nmb_namestr(question)));
2058 wins_hook("delete", namerec, 0);
2059 send_wins_name_release_response(0, p);
2064 * Send a release response.
2065 * Flag the name as released and update the ttl
2068 namerec->data.wins_flags |= WINS_RELEASED;
2069 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2071 wins_hook("delete", namerec, 0);
2072 send_wins_name_release_response(0, p);
2075 /*******************************************************************
2076 WINS time dependent processing.
2077 ******************************************************************/
2079 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2081 time_t t = *(time_t *)state;
2082 BOOL store_record = False;
2083 struct name_record *namerec = NULL;
2084 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2086 if (kbuf.dsize != sizeof(unstring) + 1) {
2090 namerec = wins_record_to_name_record(kbuf, dbuf);
2095 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2096 if( namerec->data.source == SELF_NAME ) {
2097 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2098 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2099 namerec->data.death_time += 300;
2100 store_record = True;
2102 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2103 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2104 nmb_namestr(&namerec->name)));
2105 remove_name_from_wins_namelist(namerec );
2109 /* handle records, samba is the wins owner */
2110 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2111 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
2113 namerec->data.wins_flags&=~WINS_STATE_MASK;
2114 namerec->data.wins_flags|=WINS_RELEASED;
2115 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2116 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2117 nmb_namestr(&namerec->name)));
2118 store_record = True;
2121 namerec->data.wins_flags&=~WINS_STATE_MASK;
2122 namerec->data.wins_flags|=WINS_TOMBSTONED;
2123 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2124 get_global_id_and_update(&namerec->data.id, True);
2125 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2126 nmb_namestr(&namerec->name)));
2127 store_record = True;
2129 case WINS_TOMBSTONED:
2130 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2131 nmb_namestr(&namerec->name)));
2132 remove_name_from_wins_namelist(namerec );
2136 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
2138 /* that's not as MS says it should be */
2139 namerec->data.wins_flags&=~WINS_STATE_MASK;
2140 namerec->data.wins_flags|=WINS_TOMBSTONED;
2141 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2142 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2143 nmb_namestr(&namerec->name)));
2144 store_record = True;
2146 case WINS_TOMBSTONED:
2147 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2148 nmb_namestr(&namerec->name)));
2149 remove_name_from_wins_namelist(namerec );
2152 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2153 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2162 wins_store_changed_namerec(namerec);
2165 SAFE_FREE(namerec->data.ip);
2171 /*******************************************************************
2172 Time dependent wins processing.
2173 ******************************************************************/
2175 void initiate_wins_processing(time_t t)
2177 static time_t lasttime = 0;
2178 struct name_record *nr = NULL;
2179 struct name_record *nrnext = NULL;
2184 if (t - lasttime < 20) {
2188 if(!lp_we_are_a_wins_server()) {
2193 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2196 /* Delete all temporary name records on the wins subnet linked list. */
2197 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
2199 DLIST_REMOVE(wins_server_subnet->namelist, nr);
2200 SAFE_FREE(nr->data.ip);
2204 wins_write_database(t, True);
2209 /*******************************************************************
2210 Write out one record.
2211 ******************************************************************/
2213 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2218 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2220 if( namerec->data.death_time != PERMANENT_TTL ) {
2223 tm = localtime(&namerec->data.death_time);
2225 nl = strrchr( ts, '\n' );
2229 DEBUGADD(4,("TTL = %s ", ts ));
2231 DEBUGADD(4,("TTL = PERMANENT "));
2234 for (i = 0; i < namerec->data.num_ips; i++) {
2235 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2237 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2239 if( namerec->data.source == REGISTER_NAME ) {
2241 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2242 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2243 (int)namerec->data.death_time);
2245 for (i = 0; i < namerec->data.num_ips; i++)
2246 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2247 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2251 /*******************************************************************
2252 Write out the current WINS database.
2253 ******************************************************************/
2255 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2257 struct name_record *namerec = NULL;
2258 XFILE *fp = (XFILE *)state;
2260 if (kbuf.dsize != sizeof(unstring) + 1) {
2264 namerec = wins_record_to_name_record(kbuf, dbuf);
2269 wins_write_name_record(namerec, fp);
2271 SAFE_FREE(namerec->data.ip);
2277 void wins_write_database(time_t t, BOOL background)
2279 static time_t last_write_time = 0;
2280 pstring fname, fnamenew;
2285 if (!last_write_time) {
2286 last_write_time = t;
2288 if (t - last_write_time < 120) {
2294 if(!lp_we_are_a_wins_server()) {
2298 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2304 if (tdb_reopen(wins_tdb)) {
2305 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2311 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
2312 all_string_sub(fname,"//", "/", 0);
2313 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
2315 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2316 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2323 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2325 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2327 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2330 chmod(fnamenew,0644);
2332 rename(fnamenew,fname);
2339 Until winsrepl is done.
2340 /****************************************************************************
2341 Process a internal Samba message receiving a wins record.
2342 ***************************************************************************/
2344 void nmbd_wins_new_entry(int msg_type, struct process_id src,
2345 void *buf, size_t len)
2347 WINS_RECORD *record;
2348 struct name_record *namerec = NULL;
2349 struct name_record *new_namerec = NULL;
2350 struct nmb_name question;
2351 BOOL overwrite=False;
2352 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2359 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2360 record=(WINS_RECORD *)buf;
2362 make_nmb_name(&question, record->name, record->type);
2364 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2366 /* record doesn't exist, add it */
2367 if (namerec == NULL) {
2368 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2369 record->name, record->type, inet_ntoa(record->wins_ip)));
2371 new_namerec=add_name_to_subnet( wins_server_subnet,
2375 EXTINCTION_INTERVAL,
2380 if (new_namerec!=NULL) {
2381 update_wins_owner(new_namerec, record->wins_ip);
2382 update_wins_flag(new_namerec, record->wins_flags);
2383 new_namerec->data.id=record->id;
2385 wins_server_subnet->namelist_changed = True;
2389 /* check if we have a conflict */
2390 if (namerec != NULL) {
2391 /* both records are UNIQUE */
2392 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2394 /* the database record is a replica */
2395 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2396 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2397 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
2402 /* we are the wins owner of the database record */
2403 /* the 2 records have the same IP address */
2404 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
2405 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2406 get_global_id_and_update(&namerec->data.id, True);
2411 /* the 2 records have different IP address */
2412 if (namerec->data.wins_flags&WINS_ACTIVE) {
2413 if (record->wins_flags&WINS_TOMBSTONED)
2414 get_global_id_and_update(&namerec->data.id, True);
2415 if (record->wins_flags&WINS_ACTIVE)
2416 /* send conflict challenge to the replica node */
2425 /* the replica is a standard group */
2426 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2427 /* if the database record is unique and active force a name release */
2428 if (namerec->data.wins_flags&WINS_UNIQUE)
2429 /* send a release name to the unique node */
2435 /* the replica is a special group */
2436 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2437 if (namerec->data.wins_flags&WINS_ACTIVE) {
2438 for (i=0; i<record->num_ips; i++)
2439 if(!find_ip_in_name_record(namerec, record->ip[i]))
2440 add_ip_to_name_record(namerec, record->ip[i]);
2446 /* the replica is a multihomed host */
2448 /* I'm giving up on multi homed. Too much complex to understand */
2450 if (record->wins_flags&WINS_MHOMED) {
2451 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2452 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2456 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2459 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
2460 if (namerec->data.wins_flags&WINS_UNIQUE)
2461 get_global_id_and_update(&namerec->data.id, True);
2465 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2466 if (namerec->data.wins_flags&WINS_UNIQUE ||
2467 namerec->data.wins_flags&WINS_MHOMED)
2468 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2473 if (overwrite == False)
2474 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2475 record->name, record->type, inet_ntoa(record->wins_ip)));
2477 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2478 record->name, record->type, inet_ntoa(record->wins_ip)));
2480 /* remove the old record and add a new one */
2481 remove_name_from_namelist( wins_server_subnet, namerec );
2482 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2483 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2484 if (new_namerec!=NULL) {
2485 update_wins_owner(new_namerec, record->wins_ip);
2486 update_wins_flag(new_namerec, record->wins_flags);
2487 new_namerec->data.id=record->id;
2489 wins_server_subnet->namelist_changed = True;
2492 wins_server_subnet->namelist_changed = True;