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);
1253 if( is_myname(name) ) {
1254 if(!ismyip(from_ip)) {
1255 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1256 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1257 send_wins_name_registration_response(RFS_ERR, 0, p);
1261 * It's one of our names and one of our IP's - update the ttl.
1263 update_name_ttl(namerec, ttl);
1264 wins_hook("refresh", namerec, ttl);
1265 send_wins_name_registration_response(0, ttl, p);
1271 * If the name exists and it is a unique registration and the registering IP
1272 * is the same as the (single) already registered IP then just update the ttl.
1274 * But not if the record is an active replica. IF it's a replica, it means it can be
1275 * the same client which has moved and not yet expired. So we don't update
1276 * the ttl in this case and go beyond to do a WACK and query the old client
1279 if( !registering_group_name
1280 && (namerec != NULL)
1281 && (namerec->data.num_ips == 1)
1282 && ip_equal( namerec->data.ip[0], from_ip )
1283 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
1284 update_name_ttl( namerec, ttl );
1285 wins_hook("refresh", namerec, ttl);
1286 send_wins_name_registration_response( 0, ttl, p );
1291 * Finally if the name exists do a query to the registering machine
1292 * to see if they still claim to have the name.
1295 if( namerec != NULL ) {
1296 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1297 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1300 * First send a WACK to the registering machine.
1303 send_wins_wack_response(60, p);
1306 * When the reply comes back we need the original packet.
1307 * Lock this so it won't be freed and then put it into
1308 * the userdata structure.
1313 userdata = (struct userdata_struct *)ud;
1315 userdata->copy_fn = NULL;
1316 userdata->free_fn = NULL;
1317 userdata->userdata_len = sizeof(struct packet_struct *);
1318 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1321 * Use the new call to send a query directly to an IP address.
1322 * This sends the query directly to the IP address, and ensures
1323 * the recursion desired flag is not set (you were right Luke :-).
1324 * This function should *only* be called from the WINS server
1328 pull_ascii_nstring(name, sizeof(name), question->name);
1329 query_name_from_wins_server( *namerec->data.ip,
1331 question->name_type,
1332 wins_register_query_success,
1333 wins_register_query_fail,
1339 * Name did not exist - add it.
1342 pull_ascii_nstring(name, sizeof(name), question->name);
1343 add_name_to_subnet( subrec, name, question->name_type,
1344 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1346 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1347 get_global_id_and_update(&namerec->data.id, True);
1348 update_wins_owner(namerec, our_fake_ip);
1349 update_wins_flag(namerec, WINS_ACTIVE);
1350 wins_hook("add", namerec, ttl);
1353 send_wins_name_registration_response(0, ttl, p);
1356 /***********************************************************************
1357 Deal with a mutihomed name query success to the machine that
1358 requested the multihomed name registration.
1360 We have a locked pointer to the original packet stashed away in the
1362 ************************************************************************/
1364 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1365 struct userdata_struct *userdata,
1366 struct nmb_name *question_name,
1368 struct res_rec *answers)
1370 struct packet_struct *orig_reg_packet;
1371 struct nmb_packet *nmb;
1372 struct name_record *namerec = NULL;
1373 struct in_addr from_ip;
1375 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1377 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1379 nmb = &orig_reg_packet->packet.nmb;
1381 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1382 ttl = get_ttl_from_packet(nmb);
1385 * We want to just add the new IP, as we now know the requesting
1386 * machine claims to own it. But we can't just do that as an arbitary
1387 * amount of time may have taken place between the name query
1388 * request and this response. So we check that
1389 * the name still exists and is in the same state - if so
1390 * we just add the extra IP and update the ttl.
1393 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1395 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1396 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1397 a subsequent IP address.\n", nmb_namestr(question_name) ));
1398 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1400 orig_reg_packet->locked = False;
1401 free_packet(orig_reg_packet);
1406 if(!find_ip_in_name_record(namerec, from_ip)) {
1407 add_ip_to_name_record(namerec, from_ip);
1410 get_global_id_and_update(&namerec->data.id, True);
1411 update_wins_owner(namerec, our_fake_ip);
1412 update_wins_flag(namerec, WINS_ACTIVE);
1413 update_name_ttl(namerec, ttl);
1414 wins_hook("add", namerec, ttl);
1415 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1417 orig_reg_packet->locked = False;
1418 free_packet(orig_reg_packet);
1421 /***********************************************************************
1422 Deal with a name registration request query failure to a client that
1425 We have a locked pointer to the original packet stashed away in the
1427 ************************************************************************/
1429 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1430 struct response_record *rrec,
1431 struct nmb_name *question_name,
1434 struct userdata_struct *userdata = rrec->userdata;
1435 struct packet_struct *orig_reg_packet;
1437 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1439 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1440 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1441 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1443 orig_reg_packet->locked = False;
1444 free_packet(orig_reg_packet);
1448 /***********************************************************************
1449 Deal with a multihomed name registration request to a WINS server.
1450 These cannot be group name registrations.
1451 ***********************************************************************/
1453 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1454 struct packet_struct *p)
1456 struct nmb_packet *nmb = &p->packet.nmb;
1457 struct nmb_name *question = &nmb->question.question_name;
1458 BOOL bcast = nmb->header.nm_flags.bcast;
1459 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1460 int ttl = get_ttl_from_packet(nmb);
1461 struct name_record *namerec = NULL;
1462 struct in_addr from_ip;
1463 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1464 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1467 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1471 * We should only get unicast name registration packets here.
1472 * Anyone trying to register broadcast should not be going to a WINS
1473 * server. Log an error here.
1476 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1477 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1478 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1483 * Only unique names should be registered multihomed.
1487 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1488 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1489 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1493 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1494 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1497 * Deal with policy regarding 0x1d names.
1500 if(question->name_type == 0x1d) {
1501 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1502 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1503 send_wins_name_registration_response(0, ttl, p);
1508 * See if the name already exists.
1511 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1514 * if the record exists but NOT in active state,
1518 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1519 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1520 remove_name_from_namelist(subrec, namerec);
1525 * Deal with the case where the name found was a dns entry.
1526 * Remove it as we now have a NetBIOS client registering the
1530 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1531 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1532 - removing it.\n", nmb_namestr(question) ));
1533 remove_name_from_namelist( subrec, namerec);
1538 * Reject if the name exists and is not a REGISTER_NAME.
1539 * (ie. Don't allow any static names to be overwritten.
1542 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1543 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1544 to register name %s. Name already exists in WINS with source type %d.\n",
1545 nmb_namestr(question), namerec->data.source ));
1546 send_wins_name_registration_response(RFS_ERR, 0, p);
1551 * Reject if the name exists and is a GROUP name and is active.
1554 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1555 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1556 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1557 send_wins_name_registration_response(RFS_ERR, 0, p);
1562 * From here on down we know that if the name exists in the WINS db it is
1563 * a unique name, not a group name.
1567 * If the name exists and is one of our names then check the
1568 * registering IP address. If it's not one of ours then automatically
1569 * reject without doing the query - we know we will reject it.
1572 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1573 if(!ismyip(from_ip)) {
1574 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1575 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1576 send_wins_name_registration_response(RFS_ERR, 0, p);
1580 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1581 * update the ttl. Update the version ID to force replication.
1583 update_name_ttl(namerec, ttl);
1585 if(!find_ip_in_name_record(namerec, from_ip)) {
1586 get_global_id_and_update(&namerec->data.id, True);
1587 update_wins_owner(namerec, our_fake_ip);
1588 update_wins_flag(namerec, WINS_ACTIVE);
1590 add_ip_to_name_record(namerec, from_ip);
1593 wins_hook("refresh", namerec, ttl);
1594 send_wins_name_registration_response(0, ttl, p);
1600 * If the name exists and is active, check if the IP address is already registered
1601 * to that name. If so then update the ttl and reply success.
1604 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1605 update_name_ttl(namerec, ttl);
1608 * If it's a replica, we need to become the wins owner
1609 * to force the replication
1611 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1612 get_global_id_and_update(&namerec->data.id, True);
1613 update_wins_owner(namerec, our_fake_ip);
1614 update_wins_flag(namerec, WINS_ACTIVE);
1617 wins_hook("refresh", namerec, ttl);
1618 send_wins_name_registration_response(0, ttl, p);
1623 * If the name exists do a query to the owner
1624 * to see if they still want the name.
1627 if(namerec != NULL) {
1628 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1629 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1632 * First send a WACK to the registering machine.
1635 send_wins_wack_response(60, p);
1638 * When the reply comes back we need the original packet.
1639 * Lock this so it won't be freed and then put it into
1640 * the userdata structure.
1645 userdata = (struct userdata_struct *)ud;
1647 userdata->copy_fn = NULL;
1648 userdata->free_fn = NULL;
1649 userdata->userdata_len = sizeof(struct packet_struct *);
1650 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1653 * Use the new call to send a query directly to an IP address.
1654 * This sends the query directly to the IP address, and ensures
1655 * the recursion desired flag is not set (you were right Luke :-).
1656 * This function should *only* be called from the WINS server
1659 * Note that this packet is sent to the current owner of the name,
1660 * not the person who sent the packet
1663 pull_ascii_nstring( qname, sizeof(qname), question->name);
1664 query_name_from_wins_server( namerec->data.ip[0],
1666 question->name_type,
1667 wins_multihomed_register_query_success,
1668 wins_multihomed_register_query_fail,
1675 * Name did not exist - add it.
1678 pull_ascii_nstring( qname, sizeof(qname), question->name);
1679 add_name_to_subnet( subrec, qname, question->name_type,
1680 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1682 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1683 get_global_id_and_update(&namerec->data.id, True);
1684 update_wins_owner(namerec, our_fake_ip);
1685 update_wins_flag(namerec, WINS_ACTIVE);
1686 wins_hook("add", namerec, ttl);
1689 send_wins_name_registration_response(0, ttl, p);
1692 /***********************************************************************
1693 Fetch all *<1b> names from the WINS db and store on the namelist.
1694 ***********************************************************************/
1696 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1698 struct name_record *namerec = NULL;
1700 if (kbuf.dsize != sizeof(unstring) + 1) {
1704 /* Filter out all non-1b names. */
1705 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1709 namerec = wins_record_to_name_record(kbuf, dbuf);
1714 DLIST_ADD(wins_server_subnet->namelist, namerec);
1718 void fetch_all_active_wins_1b_names(void)
1720 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1723 /***********************************************************************
1724 Deal with the special name query for *<1b>.
1725 ***********************************************************************/
1727 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1728 struct packet_struct *p)
1730 struct name_record *namerec = NULL;
1735 * Go through all the ACTIVE names in the WINS db looking for those
1736 * ending in <1b>. Use this to calculate the number of IP
1737 * addresses we need to return.
1742 fetch_all_active_wins_1b_names();
1744 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1745 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1746 num_ips += namerec->data.num_ips;
1752 * There are no 0x1b names registered. Return name query fail.
1754 send_wins_name_query_response(NAM_ERR, p, NULL);
1758 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1759 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1764 * Go through all the names again in the WINS db looking for those
1765 * ending in <1b>. Add their IP addresses into the list we will
1770 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1771 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1773 for(i = 0; i < namerec->data.num_ips; i++) {
1774 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1775 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1782 * Send back the reply containing the IP list.
1785 reply_netbios_packet(p, /* Packet to reply to. */
1786 0, /* Result code. */
1787 WINS_QUERY, /* nmbd type code. */
1788 NMB_NAME_QUERY_OPCODE, /* opcode. */
1789 lp_min_wins_ttl(), /* ttl. */
1790 prdata, /* data to send. */
1791 num_ips*6); /* data length. */
1796 /****************************************************************************
1797 Send a WINS name query response.
1798 **************************************************************************/
1800 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1801 struct name_record *namerec)
1804 char *prdata = rdata;
1805 int reply_data_len = 0;
1809 memset(rdata,'\0',6);
1812 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1814 /* Copy all known ip addresses into the return data. */
1815 /* Optimise for the common case of one IP address so we don't need a malloc. */
1817 if( namerec->data.num_ips == 1 ) {
1820 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1821 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1826 for(i = 0; i < namerec->data.num_ips; i++) {
1827 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1828 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1831 sort_query_replies(prdata, i, p->ip);
1832 reply_data_len = namerec->data.num_ips * 6;
1835 reply_netbios_packet(p, /* Packet to reply to. */
1836 rcode, /* Result code. */
1837 WINS_QUERY, /* nmbd type code. */
1838 NMB_NAME_QUERY_OPCODE, /* opcode. */
1840 prdata, /* data to send. */
1841 reply_data_len); /* data length. */
1843 if(prdata != rdata) {
1848 /***********************************************************************
1849 Deal with a name query.
1850 ***********************************************************************/
1852 void wins_process_name_query_request(struct subnet_record *subrec,
1853 struct packet_struct *p)
1855 struct nmb_packet *nmb = &p->packet.nmb;
1856 struct nmb_name *question = &nmb->question.question_name;
1857 struct name_record *namerec = NULL;
1860 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1861 nmb_namestr(question), inet_ntoa(p->ip) ));
1864 * Special name code. If the queried name is *<1b> then search
1865 * the entire WINS database and return a list of all the IP addresses
1866 * registered to any <1b> name. This is to allow domain master browsers
1867 * to discover other domains that may not have a presence on their subnet.
1870 pull_ascii_nstring(qname, sizeof(qname), question->name);
1871 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1872 process_wins_dmb_query_request( subrec, p);
1876 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1878 if(namerec != NULL) {
1880 * If the name is not anymore in active state then reply not found.
1881 * it's fair even if we keep it in the cache for days.
1883 if (!WINS_STATE_ACTIVE(namerec)) {
1884 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1885 nmb_namestr(question) ));
1886 send_wins_name_query_response(NAM_ERR, p, namerec);
1891 * If it's a DNSFAIL_NAME then reply name not found.
1894 if( namerec->data.source == DNSFAIL_NAME ) {
1895 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1896 nmb_namestr(question) ));
1897 send_wins_name_query_response(NAM_ERR, p, namerec);
1902 * If the name has expired then reply name not found.
1905 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1906 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1907 nmb_namestr(question) ));
1908 send_wins_name_query_response(NAM_ERR, p, namerec);
1912 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1913 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1915 send_wins_name_query_response(0, p, namerec);
1920 * Name not found in WINS - try a dns query if it's a 0x20 name.
1923 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1924 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1925 nmb_namestr(question) ));
1927 queue_dns_query(p, question);
1932 * Name not found - return error.
1935 send_wins_name_query_response(NAM_ERR, p, NULL);
1938 /****************************************************************************
1939 Send a WINS name release response.
1940 **************************************************************************/
1942 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1944 struct nmb_packet *nmb = &p->packet.nmb;
1947 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1949 reply_netbios_packet(p, /* Packet to reply to. */
1950 rcode, /* Result code. */
1951 NMB_REL, /* nmbd type code. */
1952 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1954 rdata, /* data to send. */
1955 6); /* data length. */
1958 /***********************************************************************
1959 Deal with a name release.
1960 ***********************************************************************/
1962 void wins_process_name_release_request(struct subnet_record *subrec,
1963 struct packet_struct *p)
1965 struct nmb_packet *nmb = &p->packet.nmb;
1966 struct nmb_name *question = &nmb->question.question_name;
1967 BOOL bcast = nmb->header.nm_flags.bcast;
1968 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1969 struct name_record *namerec = NULL;
1970 struct in_addr from_ip;
1971 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1973 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1977 * We should only get unicast name registration packets here.
1978 * Anyone trying to register broadcast should not be going to a WINS
1979 * server. Log an error here.
1982 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1983 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1984 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1988 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1989 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1992 * Deal with policy regarding 0x1d names.
1995 if(!releasing_group_name && (question->name_type == 0x1d)) {
1996 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1997 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1998 send_wins_name_release_response(0, p);
2003 * See if the name already exists.
2006 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2008 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2009 send_wins_name_release_response(NAM_ERR, p);
2014 * Check that the sending machine has permission to release this name.
2015 * If it's a group name not ending in 0x1c then just say yes and let
2016 * the group time out.
2019 if(releasing_group_name && (question->name_type != 0x1c)) {
2020 send_wins_name_release_response(0, p);
2025 * Check that the releasing node is on the list of IP addresses
2026 * for this name. Disallow the release if not.
2029 if(!find_ip_in_name_record(namerec, from_ip)) {
2030 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2031 release name %s as IP %s is not one of the known IP's for this name.\n",
2032 nmb_namestr(question), inet_ntoa(from_ip) ));
2033 send_wins_name_release_response(NAM_ERR, p);
2038 * Check if the record is active. IF it's already released
2039 * or tombstoned, refuse the release.
2042 if (!WINS_STATE_ACTIVE(namerec)) {
2043 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2044 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2045 send_wins_name_release_response(NAM_ERR, p);
2050 * Check if the record is a 0x1c group
2051 * and has more then one ip
2052 * remove only this address.
2055 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2056 remove_ip_from_name_record(namerec, from_ip);
2057 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2058 inet_ntoa(from_ip),nmb_namestr(question)));
2059 wins_hook("delete", namerec, 0);
2060 send_wins_name_release_response(0, p);
2065 * Send a release response.
2066 * Flag the name as released and update the ttl
2069 namerec->data.wins_flags |= WINS_RELEASED;
2070 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2072 wins_hook("delete", namerec, 0);
2073 send_wins_name_release_response(0, p);
2076 /*******************************************************************
2077 WINS time dependent processing.
2078 ******************************************************************/
2080 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2082 time_t t = *(time_t *)state;
2083 BOOL store_record = False;
2084 struct name_record *namerec = NULL;
2085 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2087 if (kbuf.dsize != sizeof(unstring) + 1) {
2091 namerec = wins_record_to_name_record(kbuf, dbuf);
2096 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2097 if( namerec->data.source == SELF_NAME ) {
2098 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2099 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2100 namerec->data.death_time += 300;
2101 store_record = True;
2103 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2104 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2105 nmb_namestr(&namerec->name)));
2106 remove_name_from_wins_namelist(namerec );
2110 /* handle records, samba is the wins owner */
2111 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2112 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
2114 namerec->data.wins_flags&=~WINS_STATE_MASK;
2115 namerec->data.wins_flags|=WINS_RELEASED;
2116 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2117 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2118 nmb_namestr(&namerec->name)));
2119 store_record = True;
2122 namerec->data.wins_flags&=~WINS_STATE_MASK;
2123 namerec->data.wins_flags|=WINS_TOMBSTONED;
2124 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2125 get_global_id_and_update(&namerec->data.id, True);
2126 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2127 nmb_namestr(&namerec->name)));
2128 store_record = True;
2130 case WINS_TOMBSTONED:
2131 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2132 nmb_namestr(&namerec->name)));
2133 remove_name_from_wins_namelist(namerec );
2137 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
2139 /* that's not as MS says it should be */
2140 namerec->data.wins_flags&=~WINS_STATE_MASK;
2141 namerec->data.wins_flags|=WINS_TOMBSTONED;
2142 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2143 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2144 nmb_namestr(&namerec->name)));
2145 store_record = True;
2147 case WINS_TOMBSTONED:
2148 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2149 nmb_namestr(&namerec->name)));
2150 remove_name_from_wins_namelist(namerec );
2153 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2154 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2163 wins_store_changed_namerec(namerec);
2166 SAFE_FREE(namerec->data.ip);
2172 /*******************************************************************
2173 Time dependent wins processing.
2174 ******************************************************************/
2176 void initiate_wins_processing(time_t t)
2178 static time_t lasttime = 0;
2179 struct name_record *nr = NULL;
2180 struct name_record *nrnext = NULL;
2185 if (t - lasttime < 20) {
2189 if(!lp_we_are_a_wins_server()) {
2194 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2197 /* Delete all temporary name records on the wins subnet linked list. */
2198 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
2200 DLIST_REMOVE(wins_server_subnet->namelist, nr);
2201 SAFE_FREE(nr->data.ip);
2205 wins_write_database(t, True);
2210 /*******************************************************************
2211 Write out one record.
2212 ******************************************************************/
2214 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2219 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2221 if( namerec->data.death_time != PERMANENT_TTL ) {
2224 tm = localtime(&namerec->data.death_time);
2226 nl = strrchr( ts, '\n' );
2230 DEBUGADD(4,("TTL = %s ", ts ));
2232 DEBUGADD(4,("TTL = PERMANENT "));
2235 for (i = 0; i < namerec->data.num_ips; i++) {
2236 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2238 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2240 if( namerec->data.source == REGISTER_NAME ) {
2242 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2243 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2244 (int)namerec->data.death_time);
2246 for (i = 0; i < namerec->data.num_ips; i++)
2247 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2248 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2252 /*******************************************************************
2253 Write out the current WINS database.
2254 ******************************************************************/
2256 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2258 struct name_record *namerec = NULL;
2259 XFILE *fp = (XFILE *)state;
2261 if (kbuf.dsize != sizeof(unstring) + 1) {
2265 namerec = wins_record_to_name_record(kbuf, dbuf);
2270 wins_write_name_record(namerec, fp);
2272 SAFE_FREE(namerec->data.ip);
2278 void wins_write_database(time_t t, BOOL background)
2280 static time_t last_write_time = 0;
2281 pstring fname, fnamenew;
2286 if (!last_write_time) {
2287 last_write_time = t;
2289 if (t - last_write_time < 120) {
2295 if(!lp_we_are_a_wins_server()) {
2299 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2305 if (tdb_reopen(wins_tdb)) {
2306 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2312 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
2313 all_string_sub(fname,"//", "/", 0);
2314 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
2316 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2317 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2324 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2326 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2328 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2331 chmod(fnamenew,0644);
2333 rename(fnamenew,fname);
2340 Until winsrepl is done.
2341 /****************************************************************************
2342 Process a internal Samba message receiving a wins record.
2343 ***************************************************************************/
2345 void nmbd_wins_new_entry(int msg_type, struct process_id src,
2346 void *buf, size_t len)
2348 WINS_RECORD *record;
2349 struct name_record *namerec = NULL;
2350 struct name_record *new_namerec = NULL;
2351 struct nmb_name question;
2352 BOOL overwrite=False;
2353 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2360 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2361 record=(WINS_RECORD *)buf;
2363 make_nmb_name(&question, record->name, record->type);
2365 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2367 /* record doesn't exist, add it */
2368 if (namerec == NULL) {
2369 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2370 record->name, record->type, inet_ntoa(record->wins_ip)));
2372 new_namerec=add_name_to_subnet( wins_server_subnet,
2376 EXTINCTION_INTERVAL,
2381 if (new_namerec!=NULL) {
2382 update_wins_owner(new_namerec, record->wins_ip);
2383 update_wins_flag(new_namerec, record->wins_flags);
2384 new_namerec->data.id=record->id;
2386 wins_server_subnet->namelist_changed = True;
2390 /* check if we have a conflict */
2391 if (namerec != NULL) {
2392 /* both records are UNIQUE */
2393 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2395 /* the database record is a replica */
2396 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2397 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2398 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
2403 /* we are the wins owner of the database record */
2404 /* the 2 records have the same IP address */
2405 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
2406 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2407 get_global_id_and_update(&namerec->data.id, True);
2412 /* the 2 records have different IP address */
2413 if (namerec->data.wins_flags&WINS_ACTIVE) {
2414 if (record->wins_flags&WINS_TOMBSTONED)
2415 get_global_id_and_update(&namerec->data.id, True);
2416 if (record->wins_flags&WINS_ACTIVE)
2417 /* send conflict challenge to the replica node */
2426 /* the replica is a standard group */
2427 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2428 /* if the database record is unique and active force a name release */
2429 if (namerec->data.wins_flags&WINS_UNIQUE)
2430 /* send a release name to the unique node */
2436 /* the replica is a special group */
2437 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2438 if (namerec->data.wins_flags&WINS_ACTIVE) {
2439 for (i=0; i<record->num_ips; i++)
2440 if(!find_ip_in_name_record(namerec, record->ip[i]))
2441 add_ip_to_name_record(namerec, record->ip[i]);
2447 /* the replica is a multihomed host */
2449 /* I'm giving up on multi homed. Too much complex to understand */
2451 if (record->wins_flags&WINS_MHOMED) {
2452 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2453 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2457 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2460 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
2461 if (namerec->data.wins_flags&WINS_UNIQUE)
2462 get_global_id_and_update(&namerec->data.id, True);
2466 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2467 if (namerec->data.wins_flags&WINS_UNIQUE ||
2468 namerec->data.wins_flags&WINS_MHOMED)
2469 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2474 if (overwrite == False)
2475 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2476 record->name, record->type, inet_ntoa(record->wins_ip)));
2478 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2479 record->name, record->type, inet_ntoa(record->wins_ip)));
2481 /* remove the old record and add a new one */
2482 remove_name_from_namelist( wins_server_subnet, namerec );
2483 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2484 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2485 if (new_namerec!=NULL) {
2486 update_wins_owner(new_namerec, record->wins_ip);
2487 update_wins_flag(new_namerec, record->wins_flags);
2488 new_namerec->data.id=record->id;
2490 wins_server_subnet->namelist_changed = True;
2493 wins_server_subnet->namelist_changed = True;