2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Converted to store WINS data in a tdb. Dec 2005. JRA.
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
27 #define WINSDB_VERSION 1
29 /****************************************************************************
30 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
31 name (65 bytes with the last byte being the name type).
32 *****************************************************************************/
34 TDB_CONTEXT *wins_tdb;
36 /****************************************************************************
37 Delete all the temporary name records on the in-memory linked list.
38 *****************************************************************************/
40 static void wins_delete_all_tmp_in_memory_records(void)
42 struct name_record *nr = NULL;
43 struct name_record *nrnext = NULL;
45 /* Delete all temporary name records on the wins subnet linked list. */
46 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
48 DLIST_REMOVE(wins_server_subnet->namelist, nr);
49 SAFE_FREE(nr->data.ip);
54 /****************************************************************************
55 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
56 *****************************************************************************/
58 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
60 struct name_record *namerec = NULL;
63 uint32 death_time, refresh_time;
64 uint32 id_low, id_high;
71 if (data.dptr == NULL || data.dsize == 0) {
75 /* Min size is "wbddddddd" + 1 ip address (4). */
76 if (data.dsize < 2 + 1 + (7*4) + 4) {
80 len = tdb_unpack(data.dptr, data.dsize,
92 namerec = SMB_MALLOC_P(struct name_record);
96 ZERO_STRUCTP(namerec);
98 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
99 if (!namerec->data.ip) {
104 namerec->subnet = wins_server_subnet;
105 push_ascii_nstring(namerec->name.name, (const char *)key.dptr);
106 namerec->name.name_type = key.dptr[sizeof(unstring)];
108 push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
110 /* We're using a byte-by-byte compare, so we must be sure that
111 * unused space doesn't have garbage in it.
114 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
115 namerec->name.name[i] = '\0';
117 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
118 namerec->name.scope[i] = '\0';
121 namerec->data.nb_flags = nb_flags;
122 namerec->data.source = (enum name_source)nr_src;
123 namerec->data.death_time = (time_t)death_time;
124 namerec->data.refresh_time = (time_t)refresh_time;
125 namerec->data.id = id_low;
126 #if defined(HAVE_LONGLONG)
127 namerec->data.id |= ((SMB_BIG_UINT)id_high << 32);
129 namerec->data.wins_ip.s_addr = saddr;
130 namerec->data.wins_flags = wins_flags,
131 namerec->data.num_ips = num_ips;
133 for (i = 0; i < num_ips; i++) {
134 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
140 /****************************************************************************
141 Convert a struct name_record to a wins.tdb record. Ignore the scope.
142 *****************************************************************************/
144 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
149 uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
150 #if defined(HAVE_LONGLONG)
151 uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
158 len = (2 + 1 + (7*4)); /* "wbddddddd" */
159 len += (namerec->data.num_ips * 4);
161 data.dptr = (uint8 *)SMB_MALLOC(len);
167 len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
168 namerec->data.nb_flags,
169 (unsigned char)namerec->data.source,
170 (uint32)namerec->data.death_time,
171 (uint32)namerec->data.refresh_time,
174 (uint32)namerec->data.wins_ip.s_addr,
175 (uint32)namerec->data.wins_flags,
176 (uint32)namerec->data.num_ips );
178 for (i = 0; i < namerec->data.num_ips; i++) {
179 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
185 /****************************************************************************
186 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
187 *****************************************************************************/
189 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
191 static char keydata[sizeof(unstring) + 1];
194 memset(keydata, '\0', sizeof(keydata));
196 pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
198 keydata[sizeof(unstring)] = nmbname->name_type;
199 key.dptr = (uint8 *)keydata;
200 key.dsize = sizeof(keydata);
205 /****************************************************************************
206 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
207 on the linked list. We will free this later in XXXX().
208 *****************************************************************************/
210 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, BOOL self_only)
213 struct name_record *nr = NULL;
214 struct name_record *namerec = NULL;
220 key = name_to_key(nmbname);
221 data = tdb_fetch(wins_tdb, key);
223 if (data.dsize == 0) {
227 namerec = wins_record_to_name_record(key, data);
229 /* done with the this */
231 SAFE_FREE( data.dptr );
237 /* Self names only - these include permanent names. */
238 if( self_only && (namerec->data.source != SELF_NAME) && (namerec->data.source != PERMANENT_NAME) ) {
239 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname) ) );
240 SAFE_FREE(namerec->data.ip);
245 /* Search for this name record on the list. Replace it if found. */
247 for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
248 if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
250 DLIST_REMOVE(wins_server_subnet->namelist, nr);
251 SAFE_FREE(nr->data.ip);
257 DLIST_ADD(wins_server_subnet->namelist, namerec);
261 /****************************************************************************
262 Overwrite or add a given name in the wins.tdb.
263 *****************************************************************************/
265 static BOOL store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
274 key = name_to_key(&namerec->name);
275 data = name_record_to_wins_record(namerec);
277 if (data.dptr == NULL) {
281 ret = tdb_store(wins_tdb, key, data, tdb_flag);
283 SAFE_FREE(data.dptr);
284 return (ret == 0) ? True : False;
287 /****************************************************************************
288 Overwrite a given name in the wins.tdb.
289 *****************************************************************************/
291 BOOL wins_store_changed_namerec(const struct name_record *namerec)
293 return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
296 /****************************************************************************
297 Primary interface into creating and overwriting records in the wins.tdb.
298 *****************************************************************************/
300 BOOL add_name_to_wins_subnet(const struct name_record *namerec)
302 return store_or_replace_wins_namerec(namerec, TDB_INSERT);
305 /****************************************************************************
306 Delete a given name in the tdb and remove the temporary malloc'ed data struct
308 *****************************************************************************/
310 BOOL remove_name_from_wins_namelist(struct name_record *namerec)
319 key = name_to_key(&namerec->name);
320 ret = tdb_delete(wins_tdb, key);
322 DLIST_REMOVE(wins_server_subnet->namelist, namerec);
324 /* namerec must be freed by the caller */
326 return (ret == 0) ? True : False;
329 /****************************************************************************
330 Dump out the complete namelist.
331 *****************************************************************************/
333 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
335 struct name_record *namerec = NULL;
336 XFILE *fp = (XFILE *)state;
338 if (kbuf.dsize != sizeof(unstring) + 1) {
342 namerec = wins_record_to_name_record(kbuf, dbuf);
347 dump_name_record(namerec, fp);
349 SAFE_FREE(namerec->data.ip);
354 void dump_wins_subnet_namelist(XFILE *fp)
356 tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
359 /****************************************************************************
360 Change the wins owner address in the record.
361 *****************************************************************************/
363 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
365 namerec->data.wins_ip=wins_ip;
368 /****************************************************************************
369 Create the wins flags based on the nb flags and the input value.
370 *****************************************************************************/
372 static void update_wins_flag(struct name_record *namerec, int flags)
374 namerec->data.wins_flags=0x0;
376 /* if it's a group, it can be a normal or a special one */
377 if (namerec->data.nb_flags & NB_GROUP) {
378 if (namerec->name.name_type==0x1C) {
379 namerec->data.wins_flags|=WINS_SGROUP;
381 if (namerec->data.num_ips>1) {
382 namerec->data.wins_flags|=WINS_SGROUP;
384 namerec->data.wins_flags|=WINS_NGROUP;
388 /* can be unique or multi-homed */
389 if (namerec->data.num_ips>1) {
390 namerec->data.wins_flags|=WINS_MHOMED;
392 namerec->data.wins_flags|=WINS_UNIQUE;
396 /* the node type are the same bits */
397 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
399 /* the static bit is elsewhere */
400 if (namerec->data.death_time == PERMANENT_TTL) {
401 namerec->data.wins_flags|=WINS_STATIC;
404 /* and add the given bits */
405 namerec->data.wins_flags|=flags;
407 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
408 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
411 /****************************************************************************
412 Return the general ID value and increase it if requested.
413 *****************************************************************************/
415 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
418 * it's kept as a static here, to prevent people from messing
419 * with the value directly
422 static SMB_BIG_UINT general_id = 1;
424 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
426 *current_id = general_id;
433 /****************************************************************************
434 Possibly call the WINS hook external program when a WINS change is made.
435 Also stores the changed record back in the wins_tdb.
436 *****************************************************************************/
438 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
441 char *cmd = lp_wins_hook();
445 wins_store_changed_namerec(namerec);
451 for (p=namerec->name.name; *p; p++) {
452 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
453 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
458 /* Use the name without the nametype (and scope) appended */
460 namestr = nmb_namestr(&namerec->name);
461 if ((p = strchr(namestr, '<'))) {
466 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
470 namerec->name.name_type,
473 for (i=0;i<namerec->data.num_ips;i++) {
474 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
477 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
478 smbrun(command, NULL);
481 /****************************************************************************
482 Determine if this packet should be allocated to the WINS server.
483 *****************************************************************************/
485 BOOL packet_is_for_wins_server(struct packet_struct *packet)
487 struct nmb_packet *nmb = &packet->packet.nmb;
489 /* Only unicast packets go to a WINS server. */
490 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
491 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
495 /* Check for node status requests. */
496 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
500 switch(nmb->header.opcode) {
502 * A WINS server issues WACKS, not receives them.
504 case NMB_WACK_OPCODE:
505 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
508 * A WINS server only processes registration and
509 * release requests, not responses.
511 case NMB_NAME_REG_OPCODE:
512 case NMB_NAME_MULTIHOMED_REG_OPCODE:
513 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
514 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
515 if(nmb->header.response) {
516 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
521 case NMB_NAME_RELEASE_OPCODE:
522 if(nmb->header.response) {
523 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
529 * Only process unicast name queries with rd = 1.
531 case NMB_NAME_QUERY_OPCODE:
532 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
533 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
542 /****************************************************************************
543 Utility function to decide what ttl to give a register/refresh request.
544 *****************************************************************************/
546 static int get_ttl_from_packet(struct nmb_packet *nmb)
548 int ttl = nmb->additional->ttl;
550 if (ttl < lp_min_wins_ttl()) {
551 ttl = lp_min_wins_ttl();
554 if (ttl > lp_max_wins_ttl()) {
555 ttl = lp_max_wins_ttl();
561 /****************************************************************************
562 Load or create the WINS database.
563 *****************************************************************************/
565 BOOL initialise_wins(void)
567 time_t time_now = time(NULL);
571 if(!lp_we_are_a_wins_server()) {
575 /* Open the wins.tdb. */
576 wins_tdb = tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, O_CREAT|O_RDWR, 0600);
578 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
583 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
585 add_samba_names_to_subnet(wins_server_subnet);
587 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
588 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
589 WINS_LIST, strerror(errno) ));
593 while (!x_feof(fp)) {
594 pstring name_str, ip_str, ttl_str, nb_flags_str;
595 unsigned int num_ips;
597 struct in_addr *ip_list;
609 /* Read a line from the wins.dat file. Strips whitespace
610 from the beginning and end of the line. */
611 if (!fgets_slash(line,sizeof(pstring),fp))
617 if (strncmp(line,"VERSION ", 8) == 0) {
618 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
619 version != WINS_VERSION) {
620 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
630 * Now we handle multiple IP addresses per name we need
631 * to iterate over the line twice. The first time to
632 * determine how many IP addresses there are, the second
633 * time to actually parse them into the ip_list array.
636 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
637 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
641 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
642 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
647 * Determine the number of IP addresses per line.
651 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
654 if(got_token && strchr(ip_str, '.')) {
658 } while( got_token && was_ip);
661 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
666 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
670 /* Allocate the space for the ip_list. */
671 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
672 DEBUG(0,("initialise_wins: Malloc fail !\n"));
677 /* Reset and re-parse the line. */
679 next_token(&ptr,name_str,NULL,sizeof(name_str));
680 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
681 for(i = 0; i < num_ips; i++) {
682 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
683 ip_list[i] = *interpret_addr2(ip_str);
685 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
688 * Deal with SELF or REGISTER name encoding. Default is REGISTER
689 * for compatibility with old nmbds.
692 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
693 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
698 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
699 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
702 /* Netbios name. # divides the name from the type (hex): netbios#xx */
703 pstrcpy(name,name_str);
705 if((p = strchr(name,'#')) != NULL) {
707 sscanf(p+1,"%x",&type);
710 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
711 sscanf(nb_flags_str,"%x",&nb_flags);
712 sscanf(ttl_str,"%d",&ttl);
714 /* add all entries that have 60 seconds or more to live */
715 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
716 if(ttl != PERMANENT_TTL) {
720 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
721 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
723 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
724 ttl, REGISTER_NAME, num_ips, ip_list );
726 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
727 "%s#%02x ttl = %d first IP %s flags = %2x\n",
728 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
738 /****************************************************************************
739 Send a WINS WACK (Wait ACKnowledgement) response.
740 **************************************************************************/
742 static void send_wins_wack_response(int ttl, struct packet_struct *p)
744 struct nmb_packet *nmb = &p->packet.nmb;
745 unsigned char rdata[2];
747 rdata[0] = rdata[1] = 0;
749 /* Taken from nmblib.c - we need to send back almost
750 identical bytes from the requesting packet header. */
752 rdata[0] = (nmb->header.opcode & 0xF) << 3;
753 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
756 if (nmb->header.nm_flags.trunc) {
759 if (nmb->header.nm_flags.recursion_desired) {
762 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
765 if (nmb->header.nm_flags.bcast) {
769 reply_netbios_packet(p, /* Packet to reply to. */
770 0, /* Result code. */
771 NMB_WAIT_ACK, /* nmbd type code. */
772 NMB_WACK_OPCODE, /* opcode. */
774 (char *)rdata, /* data to send. */
775 2); /* data length. */
778 /****************************************************************************
779 Send a WINS name registration response.
780 **************************************************************************/
782 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
784 struct nmb_packet *nmb = &p->packet.nmb;
787 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
789 reply_netbios_packet(p, /* Packet to reply to. */
790 rcode, /* Result code. */
791 WINS_REG, /* nmbd type code. */
792 NMB_NAME_REG_OPCODE, /* opcode. */
794 rdata, /* data to send. */
795 6); /* data length. */
798 /***********************************************************************
799 Deal with a name refresh request to a WINS server.
800 ************************************************************************/
802 void wins_process_name_refresh_request( struct subnet_record *subrec,
803 struct packet_struct *p )
805 struct nmb_packet *nmb = &p->packet.nmb;
806 struct nmb_name *question = &nmb->question.question_name;
807 BOOL bcast = nmb->header.nm_flags.bcast;
808 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
809 BOOL group = (nb_flags & NB_GROUP) ? True : False;
810 struct name_record *namerec = NULL;
811 int ttl = get_ttl_from_packet(nmb);
812 struct in_addr from_ip;
813 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
815 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
819 * We should only get unicast name refresh packets here.
820 * Anyone trying to refresh broadcast should not be going
821 * to a WINS server. Log an error here.
823 if( DEBUGLVL( 0 ) ) {
824 dbgtext( "wins_process_name_refresh_request: " );
825 dbgtext( "Broadcast name refresh request received " );
826 dbgtext( "for name %s ", nmb_namestr(question) );
827 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
828 dbgtext( "on subnet %s. ", subrec->subnet_name );
829 dbgtext( "Error - Broadcasts should not be sent " );
830 dbgtext( "to a WINS server\n" );
835 if( DEBUGLVL( 3 ) ) {
836 dbgtext( "wins_process_name_refresh_request: " );
837 dbgtext( "Name refresh for name %s IP %s\n",
838 nmb_namestr(question), inet_ntoa(from_ip) );
842 * See if the name already exists.
843 * If not, handle it as a name registration and return.
845 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
848 * If this is a refresh request and the name doesn't exist then
849 * treat it like a registration request. This allows us to recover
850 * from errors (tridge)
852 if(namerec == NULL) {
853 if( DEBUGLVL( 3 ) ) {
854 dbgtext( "wins_process_name_refresh_request: " );
855 dbgtext( "Name refresh for name %s ",
856 nmb_namestr( question ) );
857 dbgtext( "and the name does not exist. Treating " );
858 dbgtext( "as registration.\n" );
860 wins_process_name_registration_request(subrec,p);
865 * if the name is present but not active, simply remove it
866 * and treat the refresh request as a registration & return.
868 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
869 if( DEBUGLVL( 5 ) ) {
870 dbgtext( "wins_process_name_refresh_request: " );
871 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
872 dbgtext( "was not active - removing it.\n" );
874 remove_name_from_namelist( subrec, namerec );
876 wins_process_name_registration_request( subrec, p );
881 * Check that the group bits for the refreshing name and the
882 * name in our database match. If not, refuse the refresh.
883 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
885 if( (namerec != NULL) &&
886 ( (group && !NAME_GROUP(namerec))
887 || (!group && NAME_GROUP(namerec)) ) ) {
888 if( DEBUGLVL( 3 ) ) {
889 dbgtext( "wins_process_name_refresh_request: " );
890 dbgtext( "Name %s ", nmb_namestr(question) );
891 dbgtext( "group bit = %s does not match ",
892 group ? "True" : "False" );
893 dbgtext( "group bit in WINS for this name.\n" );
895 send_wins_name_registration_response(RFS_ERR, 0, p);
900 * For a unique name check that the person refreshing the name is
901 * one of the registered IP addresses. If not - fail the refresh.
902 * Do the same for group names with a type of 0x1c.
903 * Just return success for unique 0x1d refreshes. For normal group
904 * names update the ttl and return success.
906 if( (!group || (group && (question->name_type == 0x1c)))
907 && find_ip_in_name_record(namerec, from_ip) ) {
911 update_name_ttl(namerec, ttl);
914 * if the record is a replica:
915 * we take ownership and update the version ID.
917 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
918 update_wins_owner(namerec, our_fake_ip);
919 get_global_id_and_update(&namerec->data.id, True);
922 send_wins_name_registration_response(0, ttl, p);
923 wins_hook("refresh", namerec, ttl);
925 } else if((group && (question->name_type == 0x1c))) {
927 * Added by crh for bug #1079.
928 * Fix from Bert Driehuis
930 if( DEBUGLVL( 3 ) ) {
931 dbgtext( "wins_process_name_refresh_request: " );
932 dbgtext( "Name refresh for name %s, ",
933 nmb_namestr(question) );
934 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
935 dbgtext( "is not yet associated with " );
936 dbgtext( "that name. Treating as registration.\n" );
938 wins_process_name_registration_request(subrec,p);
942 * Normal groups are all registered with an IP address of
943 * 255.255.255.255 so we can't search for the IP address.
945 update_name_ttl(namerec, ttl);
946 wins_hook("refresh", namerec, ttl);
947 send_wins_name_registration_response(0, ttl, p);
949 } else if(!group && (question->name_type == 0x1d)) {
951 * Special name type - just pretend the refresh succeeded.
953 send_wins_name_registration_response(0, ttl, p);
959 if( DEBUGLVL( 3 ) ) {
960 dbgtext( "wins_process_name_refresh_request: " );
961 dbgtext( "Name refresh for name %s with IP %s ",
962 nmb_namestr(question), inet_ntoa(from_ip) );
963 dbgtext( "and is IP is not known to the name.\n" );
965 send_wins_name_registration_response(RFS_ERR, 0, p);
970 /***********************************************************************
971 Deal with a name registration request query success to a client that
974 We have a locked pointer to the original packet stashed away in the
975 userdata pointer. The success here is actually a failure as it means
976 the client we queried wants to keep the name, so we must return
977 a registration failure to the original requestor.
978 ************************************************************************/
980 static void wins_register_query_success(struct subnet_record *subrec,
981 struct userdata_struct *userdata,
982 struct nmb_name *question_name,
984 struct res_rec *answers)
986 struct packet_struct *orig_reg_packet;
988 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
990 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
991 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
993 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
995 orig_reg_packet->locked = False;
996 free_packet(orig_reg_packet);
999 /***********************************************************************
1000 Deal with a name registration request query failure to a client that
1003 We have a locked pointer to the original packet stashed away in the
1004 userdata pointer. The failure here is actually a success as it means
1005 the client we queried didn't want to keep the name, so we can remove
1006 the old name record and then successfully add the new name.
1007 ************************************************************************/
1009 static void wins_register_query_fail(struct subnet_record *subrec,
1010 struct response_record *rrec,
1011 struct nmb_name *question_name,
1014 struct userdata_struct *userdata = rrec->userdata;
1015 struct packet_struct *orig_reg_packet;
1016 struct name_record *namerec = NULL;
1018 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1021 * We want to just add the name, as we now know the original owner
1022 * didn't want it. But we can't just do that as an arbitary
1023 * amount of time may have taken place between the name query
1024 * request and this timeout/error response. So we check that
1025 * the name still exists and is in the same state - if so
1026 * we remove it and call wins_process_name_registration_request()
1027 * as we know it will do the right thing now.
1030 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1032 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1033 ip_equal(rrec->packet->ip, *namerec->data.ip)) {
1034 remove_name_from_namelist( subrec, namerec);
1038 if(namerec == NULL) {
1039 wins_process_name_registration_request(subrec, orig_reg_packet);
1041 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1042 "querying for name %s in order to replace it and this reply.\n",
1043 nmb_namestr(question_name) ));
1046 orig_reg_packet->locked = False;
1047 free_packet(orig_reg_packet);
1050 /***********************************************************************
1051 Deal with a name registration request to a WINS server.
1053 Use the following pseudocode :
1058 +--------name exists
1061 | +--- existing name is group
1064 | | +--- add name (return).
1067 | +--- exiting name is unique
1070 | +--- query existing owner (return).
1073 +--------name doesn't exist
1076 +--- add name (return).
1081 +--------name exists
1084 | +--- existing name is group
1087 | | +--- fail add (return).
1090 | +--- exiting name is unique
1093 | +--- query existing owner (return).
1096 +--------name doesn't exist
1099 +--- add name (return).
1101 As can be seen from the above, the two cases may be collapsed onto each
1102 other with the exception of the case where the name already exists and
1103 is a group name. This case we handle with an if statement.
1105 ************************************************************************/
1107 void wins_process_name_registration_request(struct subnet_record *subrec,
1108 struct packet_struct *p)
1111 struct nmb_packet *nmb = &p->packet.nmb;
1112 struct nmb_name *question = &nmb->question.question_name;
1113 BOOL bcast = nmb->header.nm_flags.bcast;
1114 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1115 int ttl = get_ttl_from_packet(nmb);
1116 struct name_record *namerec = NULL;
1117 struct in_addr from_ip;
1118 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1119 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1121 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1125 * We should only get unicast name registration packets here.
1126 * Anyone trying to register broadcast should not be going to a WINS
1127 * server. Log an error here.
1130 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1131 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1132 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1136 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1137 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1140 * See if the name already exists.
1143 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1146 * if the record exists but NOT in active state,
1149 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1150 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1151 not active - removing it.\n", nmb_namestr(question) ));
1152 remove_name_from_namelist( subrec, namerec );
1157 * Deal with the case where the name found was a dns entry.
1158 * Remove it as we now have a NetBIOS client registering the
1162 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1163 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1164 a dns lookup - removing it.\n", nmb_namestr(question) ));
1165 remove_name_from_namelist( subrec, namerec );
1170 * Reject if the name exists and is not a REGISTER_NAME.
1171 * (ie. Don't allow any static names to be overwritten.
1174 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1175 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1176 to register name %s. Name already exists in WINS with source type %d.\n",
1177 nmb_namestr(question), namerec->data.source ));
1178 send_wins_name_registration_response(RFS_ERR, 0, p);
1183 * Special policy decisions based on MS documentation.
1184 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1185 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1189 * A group name is always added as the local broadcast address, except
1190 * for group names ending in 0x1c.
1191 * Group names with type 0x1c are registered with individual IP addresses.
1194 if(registering_group_name && (question->name_type != 0x1c)) {
1195 from_ip = *interpret_addr2("255.255.255.255");
1199 * Ignore all attempts to register a unique 0x1d name, although return success.
1202 if(!registering_group_name && (question->name_type == 0x1d)) {
1203 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1204 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1205 send_wins_name_registration_response(0, ttl, p);
1210 * Next two cases are the 'if statement' mentioned above.
1213 if((namerec != NULL) && NAME_GROUP(namerec)) {
1214 if(registering_group_name) {
1216 * If we are adding a group name, the name exists and is also a group entry just add this
1217 * IP address to it and update the ttl.
1220 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1221 inet_ntoa(from_ip), nmb_namestr(question) ));
1224 * Check the ip address is not already in the group.
1227 if(!find_ip_in_name_record(namerec, from_ip)) {
1228 add_ip_to_name_record(namerec, from_ip);
1229 /* we need to update the record for replication */
1230 get_global_id_and_update(&namerec->data.id, True);
1233 * if the record is a replica, we must change
1234 * the wins owner to us to make the replication updates
1235 * it on the other wins servers.
1236 * And when the partner will receive this record,
1237 * it will update its own record.
1240 update_wins_owner(namerec, our_fake_ip);
1242 update_name_ttl(namerec, ttl);
1243 wins_hook("refresh", namerec, ttl);
1244 send_wins_name_registration_response(0, ttl, p);
1249 * If we are adding a unique name, the name exists in the WINS db
1250 * and is a group name then reject the registration.
1252 * explanation: groups have a higher priority than unique names.
1255 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1256 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1257 send_wins_name_registration_response(RFS_ERR, 0, p);
1263 * From here on down we know that if the name exists in the WINS db it is
1264 * a unique name, not a group name.
1268 * If the name exists and is one of our names then check the
1269 * registering IP address. If it's not one of ours then automatically
1270 * reject without doing the query - we know we will reject it.
1273 if ( namerec != NULL ) {
1274 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1275 if( is_myname(name) ) {
1276 if(!ismyip(from_ip)) {
1277 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1278 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1279 send_wins_name_registration_response(RFS_ERR, 0, p);
1283 * It's one of our names and one of our IP's - update the ttl.
1285 update_name_ttl(namerec, ttl);
1286 wins_hook("refresh", namerec, ttl);
1287 send_wins_name_registration_response(0, ttl, p);
1296 * If the name exists and it is a unique registration and the registering IP
1297 * is the same as the (single) already registered IP then just update the ttl.
1299 * But not if the record is an active replica. IF it's a replica, it means it can be
1300 * the same client which has moved and not yet expired. So we don't update
1301 * the ttl in this case and go beyond to do a WACK and query the old client
1304 if( !registering_group_name
1305 && (namerec != NULL)
1306 && (namerec->data.num_ips == 1)
1307 && ip_equal( namerec->data.ip[0], from_ip )
1308 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
1309 update_name_ttl( namerec, ttl );
1310 wins_hook("refresh", namerec, ttl);
1311 send_wins_name_registration_response( 0, ttl, p );
1316 * Finally if the name exists do a query to the registering machine
1317 * to see if they still claim to have the name.
1320 if( namerec != NULL ) {
1321 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1322 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1325 * First send a WACK to the registering machine.
1328 send_wins_wack_response(60, p);
1331 * When the reply comes back we need the original packet.
1332 * Lock this so it won't be freed and then put it into
1333 * the userdata structure.
1338 userdata = (struct userdata_struct *)ud;
1340 userdata->copy_fn = NULL;
1341 userdata->free_fn = NULL;
1342 userdata->userdata_len = sizeof(struct packet_struct *);
1343 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1346 * Use the new call to send a query directly to an IP address.
1347 * This sends the query directly to the IP address, and ensures
1348 * the recursion desired flag is not set (you were right Luke :-).
1349 * This function should *only* be called from the WINS server
1353 pull_ascii_nstring(name, sizeof(name), question->name);
1354 query_name_from_wins_server( *namerec->data.ip,
1356 question->name_type,
1357 wins_register_query_success,
1358 wins_register_query_fail,
1364 * Name did not exist - add it.
1367 pull_ascii_nstring(name, sizeof(name), question->name);
1368 add_name_to_subnet( subrec, name, question->name_type,
1369 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1371 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1372 get_global_id_and_update(&namerec->data.id, True);
1373 update_wins_owner(namerec, our_fake_ip);
1374 update_wins_flag(namerec, WINS_ACTIVE);
1375 wins_hook("add", namerec, ttl);
1378 send_wins_name_registration_response(0, ttl, p);
1381 /***********************************************************************
1382 Deal with a mutihomed name query success to the machine that
1383 requested the multihomed name registration.
1385 We have a locked pointer to the original packet stashed away in the
1387 ************************************************************************/
1389 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1390 struct userdata_struct *userdata,
1391 struct nmb_name *question_name,
1393 struct res_rec *answers)
1395 struct packet_struct *orig_reg_packet;
1396 struct nmb_packet *nmb;
1397 struct name_record *namerec = NULL;
1398 struct in_addr from_ip;
1400 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1402 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1404 nmb = &orig_reg_packet->packet.nmb;
1406 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1407 ttl = get_ttl_from_packet(nmb);
1410 * We want to just add the new IP, as we now know the requesting
1411 * machine claims to own it. But we can't just do that as an arbitary
1412 * amount of time may have taken place between the name query
1413 * request and this response. So we check that
1414 * the name still exists and is in the same state - if so
1415 * we just add the extra IP and update the ttl.
1418 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1420 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1421 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1422 a subsequent IP address.\n", nmb_namestr(question_name) ));
1423 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1425 orig_reg_packet->locked = False;
1426 free_packet(orig_reg_packet);
1431 if(!find_ip_in_name_record(namerec, from_ip)) {
1432 add_ip_to_name_record(namerec, from_ip);
1435 get_global_id_and_update(&namerec->data.id, True);
1436 update_wins_owner(namerec, our_fake_ip);
1437 update_wins_flag(namerec, WINS_ACTIVE);
1438 update_name_ttl(namerec, ttl);
1439 wins_hook("add", namerec, ttl);
1440 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1442 orig_reg_packet->locked = False;
1443 free_packet(orig_reg_packet);
1446 /***********************************************************************
1447 Deal with a name registration request query failure to a client that
1450 We have a locked pointer to the original packet stashed away in the
1452 ************************************************************************/
1454 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1455 struct response_record *rrec,
1456 struct nmb_name *question_name,
1459 struct userdata_struct *userdata = rrec->userdata;
1460 struct packet_struct *orig_reg_packet;
1462 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1464 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1465 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1466 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1468 orig_reg_packet->locked = False;
1469 free_packet(orig_reg_packet);
1473 /***********************************************************************
1474 Deal with a multihomed name registration request to a WINS server.
1475 These cannot be group name registrations.
1476 ***********************************************************************/
1478 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1479 struct packet_struct *p)
1481 struct nmb_packet *nmb = &p->packet.nmb;
1482 struct nmb_name *question = &nmb->question.question_name;
1483 BOOL bcast = nmb->header.nm_flags.bcast;
1484 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1485 int ttl = get_ttl_from_packet(nmb);
1486 struct name_record *namerec = NULL;
1487 struct in_addr from_ip;
1488 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1489 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1492 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1496 * We should only get unicast name registration packets here.
1497 * Anyone trying to register broadcast should not be going to a WINS
1498 * server. Log an error here.
1501 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1502 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1503 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1508 * Only unique names should be registered multihomed.
1512 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1513 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1514 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1518 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1519 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1522 * Deal with policy regarding 0x1d names.
1525 if(question->name_type == 0x1d) {
1526 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1527 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1528 send_wins_name_registration_response(0, ttl, p);
1533 * See if the name already exists.
1536 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1539 * if the record exists but NOT in active state,
1543 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1544 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1545 remove_name_from_namelist(subrec, namerec);
1550 * Deal with the case where the name found was a dns entry.
1551 * Remove it as we now have a NetBIOS client registering the
1555 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1556 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1557 - removing it.\n", nmb_namestr(question) ));
1558 remove_name_from_namelist( subrec, namerec);
1563 * Reject if the name exists and is not a REGISTER_NAME.
1564 * (ie. Don't allow any static names to be overwritten.
1567 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1568 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1569 to register name %s. Name already exists in WINS with source type %d.\n",
1570 nmb_namestr(question), namerec->data.source ));
1571 send_wins_name_registration_response(RFS_ERR, 0, p);
1576 * Reject if the name exists and is a GROUP name and is active.
1579 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1580 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1581 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1582 send_wins_name_registration_response(RFS_ERR, 0, p);
1587 * From here on down we know that if the name exists in the WINS db it is
1588 * a unique name, not a group name.
1592 * If the name exists and is one of our names then check the
1593 * registering IP address. If it's not one of ours then automatically
1594 * reject without doing the query - we know we will reject it.
1597 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1598 if(!ismyip(from_ip)) {
1599 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1600 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1601 send_wins_name_registration_response(RFS_ERR, 0, p);
1605 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1606 * update the ttl. Update the version ID to force replication.
1608 update_name_ttl(namerec, ttl);
1610 if(!find_ip_in_name_record(namerec, from_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);
1615 add_ip_to_name_record(namerec, from_ip);
1618 wins_hook("refresh", namerec, ttl);
1619 send_wins_name_registration_response(0, ttl, p);
1625 * If the name exists and is active, check if the IP address is already registered
1626 * to that name. If so then update the ttl and reply success.
1629 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1630 update_name_ttl(namerec, ttl);
1633 * If it's a replica, we need to become the wins owner
1634 * to force the replication
1636 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1637 get_global_id_and_update(&namerec->data.id, True);
1638 update_wins_owner(namerec, our_fake_ip);
1639 update_wins_flag(namerec, WINS_ACTIVE);
1642 wins_hook("refresh", namerec, ttl);
1643 send_wins_name_registration_response(0, ttl, p);
1648 * If the name exists do a query to the owner
1649 * to see if they still want the name.
1652 if(namerec != NULL) {
1653 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1654 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1657 * First send a WACK to the registering machine.
1660 send_wins_wack_response(60, p);
1663 * When the reply comes back we need the original packet.
1664 * Lock this so it won't be freed and then put it into
1665 * the userdata structure.
1670 userdata = (struct userdata_struct *)ud;
1672 userdata->copy_fn = NULL;
1673 userdata->free_fn = NULL;
1674 userdata->userdata_len = sizeof(struct packet_struct *);
1675 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1678 * Use the new call to send a query directly to an IP address.
1679 * This sends the query directly to the IP address, and ensures
1680 * the recursion desired flag is not set (you were right Luke :-).
1681 * This function should *only* be called from the WINS server
1684 * Note that this packet is sent to the current owner of the name,
1685 * not the person who sent the packet
1688 pull_ascii_nstring( qname, sizeof(qname), question->name);
1689 query_name_from_wins_server( namerec->data.ip[0],
1691 question->name_type,
1692 wins_multihomed_register_query_success,
1693 wins_multihomed_register_query_fail,
1700 * Name did not exist - add it.
1703 pull_ascii_nstring( qname, sizeof(qname), question->name);
1704 add_name_to_subnet( subrec, qname, question->name_type,
1705 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1707 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1708 get_global_id_and_update(&namerec->data.id, True);
1709 update_wins_owner(namerec, our_fake_ip);
1710 update_wins_flag(namerec, WINS_ACTIVE);
1711 wins_hook("add", namerec, ttl);
1714 send_wins_name_registration_response(0, ttl, p);
1717 /***********************************************************************
1718 Fetch all *<1b> names from the WINS db and store on the namelist.
1719 ***********************************************************************/
1721 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1723 struct name_record *namerec = NULL;
1725 if (kbuf.dsize != sizeof(unstring) + 1) {
1729 /* Filter out all non-1b names. */
1730 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1734 namerec = wins_record_to_name_record(kbuf, dbuf);
1739 DLIST_ADD(wins_server_subnet->namelist, namerec);
1743 void fetch_all_active_wins_1b_names(void)
1745 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1748 /***********************************************************************
1749 Deal with the special name query for *<1b>.
1750 ***********************************************************************/
1752 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1753 struct packet_struct *p)
1755 struct name_record *namerec = NULL;
1760 * Go through all the ACTIVE names in the WINS db looking for those
1761 * ending in <1b>. Use this to calculate the number of IP
1762 * addresses we need to return.
1767 /* First, clear the in memory list - we're going to re-populate
1768 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1770 wins_delete_all_tmp_in_memory_records();
1772 fetch_all_active_wins_1b_names();
1774 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1775 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1776 num_ips += namerec->data.num_ips;
1782 * There are no 0x1b names registered. Return name query fail.
1784 send_wins_name_query_response(NAM_ERR, p, NULL);
1788 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1789 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1794 * Go through all the names again in the WINS db looking for those
1795 * ending in <1b>. Add their IP addresses into the list we will
1800 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1801 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1803 for(i = 0; i < namerec->data.num_ips; i++) {
1804 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1805 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1812 * Send back the reply containing the IP list.
1815 reply_netbios_packet(p, /* Packet to reply to. */
1816 0, /* Result code. */
1817 WINS_QUERY, /* nmbd type code. */
1818 NMB_NAME_QUERY_OPCODE, /* opcode. */
1819 lp_min_wins_ttl(), /* ttl. */
1820 prdata, /* data to send. */
1821 num_ips*6); /* data length. */
1826 /****************************************************************************
1827 Send a WINS name query response.
1828 **************************************************************************/
1830 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1831 struct name_record *namerec)
1834 char *prdata = rdata;
1835 int reply_data_len = 0;
1839 memset(rdata,'\0',6);
1842 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1844 /* Copy all known ip addresses into the return data. */
1845 /* Optimise for the common case of one IP address so we don't need a malloc. */
1847 if( namerec->data.num_ips == 1 ) {
1850 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1851 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1856 for(i = 0; i < namerec->data.num_ips; i++) {
1857 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1858 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1861 sort_query_replies(prdata, i, p->ip);
1862 reply_data_len = namerec->data.num_ips * 6;
1865 reply_netbios_packet(p, /* Packet to reply to. */
1866 rcode, /* Result code. */
1867 WINS_QUERY, /* nmbd type code. */
1868 NMB_NAME_QUERY_OPCODE, /* opcode. */
1870 prdata, /* data to send. */
1871 reply_data_len); /* data length. */
1873 if(prdata != rdata) {
1878 /***********************************************************************
1879 Deal with a name query.
1880 ***********************************************************************/
1882 void wins_process_name_query_request(struct subnet_record *subrec,
1883 struct packet_struct *p)
1885 struct nmb_packet *nmb = &p->packet.nmb;
1886 struct nmb_name *question = &nmb->question.question_name;
1887 struct name_record *namerec = NULL;
1890 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1891 nmb_namestr(question), inet_ntoa(p->ip) ));
1894 * Special name code. If the queried name is *<1b> then search
1895 * the entire WINS database and return a list of all the IP addresses
1896 * registered to any <1b> name. This is to allow domain master browsers
1897 * to discover other domains that may not have a presence on their subnet.
1900 pull_ascii_nstring(qname, sizeof(qname), question->name);
1901 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1902 process_wins_dmb_query_request( subrec, p);
1906 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1908 if(namerec != NULL) {
1910 * If the name is not anymore in active state then reply not found.
1911 * it's fair even if we keep it in the cache for days.
1913 if (!WINS_STATE_ACTIVE(namerec)) {
1914 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1915 nmb_namestr(question) ));
1916 send_wins_name_query_response(NAM_ERR, p, namerec);
1921 * If it's a DNSFAIL_NAME then reply name not found.
1924 if( namerec->data.source == DNSFAIL_NAME ) {
1925 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1926 nmb_namestr(question) ));
1927 send_wins_name_query_response(NAM_ERR, p, namerec);
1932 * If the name has expired then reply name not found.
1935 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1936 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1937 nmb_namestr(question) ));
1938 send_wins_name_query_response(NAM_ERR, p, namerec);
1942 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1943 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1945 send_wins_name_query_response(0, p, namerec);
1950 * Name not found in WINS - try a dns query if it's a 0x20 name.
1953 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1954 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1955 nmb_namestr(question) ));
1957 queue_dns_query(p, question);
1962 * Name not found - return error.
1965 send_wins_name_query_response(NAM_ERR, p, NULL);
1968 /****************************************************************************
1969 Send a WINS name release response.
1970 **************************************************************************/
1972 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1974 struct nmb_packet *nmb = &p->packet.nmb;
1977 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1979 reply_netbios_packet(p, /* Packet to reply to. */
1980 rcode, /* Result code. */
1981 NMB_REL, /* nmbd type code. */
1982 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1984 rdata, /* data to send. */
1985 6); /* data length. */
1988 /***********************************************************************
1989 Deal with a name release.
1990 ***********************************************************************/
1992 void wins_process_name_release_request(struct subnet_record *subrec,
1993 struct packet_struct *p)
1995 struct nmb_packet *nmb = &p->packet.nmb;
1996 struct nmb_name *question = &nmb->question.question_name;
1997 BOOL bcast = nmb->header.nm_flags.bcast;
1998 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1999 struct name_record *namerec = NULL;
2000 struct in_addr from_ip;
2001 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
2003 putip((char *)&from_ip,&nmb->additional->rdata[2]);
2007 * We should only get unicast name registration packets here.
2008 * Anyone trying to register broadcast should not be going to a WINS
2009 * server. Log an error here.
2012 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2013 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2014 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2018 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2019 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2022 * Deal with policy regarding 0x1d names.
2025 if(!releasing_group_name && (question->name_type == 0x1d)) {
2026 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2027 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2028 send_wins_name_release_response(0, p);
2033 * See if the name already exists.
2036 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2038 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2039 send_wins_name_release_response(NAM_ERR, p);
2044 * Check that the sending machine has permission to release this name.
2045 * If it's a group name not ending in 0x1c then just say yes and let
2046 * the group time out.
2049 if(releasing_group_name && (question->name_type != 0x1c)) {
2050 send_wins_name_release_response(0, p);
2055 * Check that the releasing node is on the list of IP addresses
2056 * for this name. Disallow the release if not.
2059 if(!find_ip_in_name_record(namerec, from_ip)) {
2060 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2061 release name %s as IP %s is not one of the known IP's for this name.\n",
2062 nmb_namestr(question), inet_ntoa(from_ip) ));
2063 send_wins_name_release_response(NAM_ERR, p);
2068 * Check if the record is active. IF it's already released
2069 * or tombstoned, refuse the release.
2072 if (!WINS_STATE_ACTIVE(namerec)) {
2073 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2074 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2075 send_wins_name_release_response(NAM_ERR, p);
2080 * Check if the record is a 0x1c group
2081 * and has more then one ip
2082 * remove only this address.
2085 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2086 remove_ip_from_name_record(namerec, from_ip);
2087 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2088 inet_ntoa(from_ip),nmb_namestr(question)));
2089 wins_hook("delete", namerec, 0);
2090 send_wins_name_release_response(0, p);
2095 * Send a release response.
2096 * Flag the name as released and update the ttl
2099 namerec->data.wins_flags |= WINS_RELEASED;
2100 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2102 wins_hook("delete", namerec, 0);
2103 send_wins_name_release_response(0, p);
2106 /*******************************************************************
2107 WINS time dependent processing.
2108 ******************************************************************/
2110 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2112 time_t t = *(time_t *)state;
2113 BOOL store_record = False;
2114 struct name_record *namerec = NULL;
2115 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2117 if (kbuf.dsize != sizeof(unstring) + 1) {
2121 namerec = wins_record_to_name_record(kbuf, dbuf);
2126 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2127 if( namerec->data.source == SELF_NAME ) {
2128 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2129 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2130 namerec->data.death_time += 300;
2131 store_record = True;
2133 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2134 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2135 nmb_namestr(&namerec->name)));
2136 remove_name_from_wins_namelist(namerec );
2140 /* handle records, samba is the wins owner */
2141 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2142 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2144 namerec->data.wins_flags&=~WINS_STATE_MASK;
2145 namerec->data.wins_flags|=WINS_RELEASED;
2146 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2147 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2148 nmb_namestr(&namerec->name)));
2149 store_record = True;
2152 namerec->data.wins_flags&=~WINS_STATE_MASK;
2153 namerec->data.wins_flags|=WINS_TOMBSTONED;
2154 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2155 get_global_id_and_update(&namerec->data.id, True);
2156 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2157 nmb_namestr(&namerec->name)));
2158 store_record = True;
2160 case WINS_TOMBSTONED:
2161 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2162 nmb_namestr(&namerec->name)));
2163 remove_name_from_wins_namelist(namerec );
2167 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2169 /* that's not as MS says it should be */
2170 namerec->data.wins_flags&=~WINS_STATE_MASK;
2171 namerec->data.wins_flags|=WINS_TOMBSTONED;
2172 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2173 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2174 nmb_namestr(&namerec->name)));
2175 store_record = True;
2177 case WINS_TOMBSTONED:
2178 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2179 nmb_namestr(&namerec->name)));
2180 remove_name_from_wins_namelist(namerec );
2183 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2184 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2193 wins_store_changed_namerec(namerec);
2196 SAFE_FREE(namerec->data.ip);
2202 /*******************************************************************
2203 Time dependent wins processing.
2204 ******************************************************************/
2206 void initiate_wins_processing(time_t t)
2208 static time_t lasttime = 0;
2213 if (t - lasttime < 20) {
2217 if(!lp_we_are_a_wins_server()) {
2222 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2224 wins_delete_all_tmp_in_memory_records();
2226 wins_write_database(t, True);
2231 /*******************************************************************
2232 Write out one record.
2233 ******************************************************************/
2235 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2240 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2242 if( namerec->data.death_time != PERMANENT_TTL ) {
2245 tm = localtime(&namerec->data.death_time);
2253 nl = strrchr( ts, '\n' );
2257 DEBUGADD(4,("TTL = %s ", ts ));
2259 DEBUGADD(4,("TTL = PERMANENT "));
2262 for (i = 0; i < namerec->data.num_ips; i++) {
2263 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2265 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2267 if( namerec->data.source == REGISTER_NAME ) {
2269 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2270 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2271 (int)namerec->data.death_time);
2273 for (i = 0; i < namerec->data.num_ips; i++)
2274 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2275 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2279 /*******************************************************************
2280 Write out the current WINS database.
2281 ******************************************************************/
2283 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2285 struct name_record *namerec = NULL;
2286 XFILE *fp = (XFILE *)state;
2288 if (kbuf.dsize != sizeof(unstring) + 1) {
2292 namerec = wins_record_to_name_record(kbuf, dbuf);
2297 wins_write_name_record(namerec, fp);
2299 SAFE_FREE(namerec->data.ip);
2305 void wins_write_database(time_t t, BOOL background)
2307 static time_t last_write_time = 0;
2308 pstring fname, fnamenew;
2313 if (!last_write_time) {
2314 last_write_time = t;
2316 if (t - last_write_time < 120) {
2322 if(!lp_we_are_a_wins_server()) {
2326 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2332 if (tdb_reopen(wins_tdb)) {
2333 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2340 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
2341 all_string_sub(fname,"//", "/", 0);
2342 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
2344 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2345 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2352 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2354 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2356 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2359 chmod(fnamenew,0644);
2361 rename(fnamenew,fname);
2368 Until winsrepl is done.
2369 /****************************************************************************
2370 Process a internal Samba message receiving a wins record.
2371 ***************************************************************************/
2373 void nmbd_wins_new_entry(struct messaging_context *msg,
2376 struct server_id server_id,
2379 WINS_RECORD *record;
2380 struct name_record *namerec = NULL;
2381 struct name_record *new_namerec = NULL;
2382 struct nmb_name question;
2383 BOOL overwrite=False;
2384 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
2391 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2392 record=(WINS_RECORD *)buf;
2394 make_nmb_name(&question, record->name, record->type);
2396 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2398 /* record doesn't exist, add it */
2399 if (namerec == NULL) {
2400 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2401 record->name, record->type, inet_ntoa(record->wins_ip)));
2403 new_namerec=add_name_to_subnet( wins_server_subnet,
2407 EXTINCTION_INTERVAL,
2412 if (new_namerec!=NULL) {
2413 update_wins_owner(new_namerec, record->wins_ip);
2414 update_wins_flag(new_namerec, record->wins_flags);
2415 new_namerec->data.id=record->id;
2417 wins_server_subnet->namelist_changed = True;
2421 /* check if we have a conflict */
2422 if (namerec != NULL) {
2423 /* both records are UNIQUE */
2424 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2426 /* the database record is a replica */
2427 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
2428 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2429 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
2434 /* we are the wins owner of the database record */
2435 /* the 2 records have the same IP address */
2436 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
2437 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2438 get_global_id_and_update(&namerec->data.id, True);
2443 /* the 2 records have different IP address */
2444 if (namerec->data.wins_flags&WINS_ACTIVE) {
2445 if (record->wins_flags&WINS_TOMBSTONED)
2446 get_global_id_and_update(&namerec->data.id, True);
2447 if (record->wins_flags&WINS_ACTIVE)
2448 /* send conflict challenge to the replica node */
2457 /* the replica is a standard group */
2458 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2459 /* if the database record is unique and active force a name release */
2460 if (namerec->data.wins_flags&WINS_UNIQUE)
2461 /* send a release name to the unique node */
2467 /* the replica is a special group */
2468 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2469 if (namerec->data.wins_flags&WINS_ACTIVE) {
2470 for (i=0; i<record->num_ips; i++)
2471 if(!find_ip_in_name_record(namerec, record->ip[i]))
2472 add_ip_to_name_record(namerec, record->ip[i]);
2478 /* the replica is a multihomed host */
2480 /* I'm giving up on multi homed. Too much complex to understand */
2482 if (record->wins_flags&WINS_MHOMED) {
2483 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2484 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2488 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2491 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
2492 if (namerec->data.wins_flags&WINS_UNIQUE)
2493 get_global_id_and_update(&namerec->data.id, True);
2497 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2498 if (namerec->data.wins_flags&WINS_UNIQUE ||
2499 namerec->data.wins_flags&WINS_MHOMED)
2500 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2505 if (overwrite == False)
2506 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2507 record->name, record->type, inet_ntoa(record->wins_ip)));
2509 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2510 record->name, record->type, inet_ntoa(record->wins_ip)));
2512 /* remove the old record and add a new one */
2513 remove_name_from_namelist( wins_server_subnet, namerec );
2514 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2515 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2516 if (new_namerec!=NULL) {
2517 update_wins_owner(new_namerec, record->wins_ip);
2518 update_wins_flag(new_namerec, record->wins_flags);
2519 new_namerec->data.id=record->id;
2521 wins_server_subnet->namelist_changed = True;
2524 wins_server_subnet->namelist_changed = True;