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(state_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 (void)interpret_addr2(&ip_list[i], 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;
815 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
816 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
820 * We should only get unicast name refresh packets here.
821 * Anyone trying to refresh broadcast should not be going
822 * to a WINS server. Log an error here.
824 if( DEBUGLVL( 0 ) ) {
825 dbgtext( "wins_process_name_refresh_request: " );
826 dbgtext( "Broadcast name refresh request received " );
827 dbgtext( "for name %s ", nmb_namestr(question) );
828 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
829 dbgtext( "on subnet %s. ", subrec->subnet_name );
830 dbgtext( "Error - Broadcasts should not be sent " );
831 dbgtext( "to a WINS server\n" );
836 if( DEBUGLVL( 3 ) ) {
837 dbgtext( "wins_process_name_refresh_request: " );
838 dbgtext( "Name refresh for name %s IP %s\n",
839 nmb_namestr(question), inet_ntoa(from_ip) );
843 * See if the name already exists.
844 * If not, handle it as a name registration and return.
846 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
849 * If this is a refresh request and the name doesn't exist then
850 * treat it like a registration request. This allows us to recover
851 * from errors (tridge)
853 if(namerec == NULL) {
854 if( DEBUGLVL( 3 ) ) {
855 dbgtext( "wins_process_name_refresh_request: " );
856 dbgtext( "Name refresh for name %s ",
857 nmb_namestr( question ) );
858 dbgtext( "and the name does not exist. Treating " );
859 dbgtext( "as registration.\n" );
861 wins_process_name_registration_request(subrec,p);
866 * if the name is present but not active, simply remove it
867 * and treat the refresh request as a registration & return.
869 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
870 if( DEBUGLVL( 5 ) ) {
871 dbgtext( "wins_process_name_refresh_request: " );
872 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
873 dbgtext( "was not active - removing it.\n" );
875 remove_name_from_namelist( subrec, namerec );
877 wins_process_name_registration_request( subrec, p );
882 * Check that the group bits for the refreshing name and the
883 * name in our database match. If not, refuse the refresh.
884 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
886 if( (namerec != NULL) &&
887 ( (group && !NAME_GROUP(namerec))
888 || (!group && NAME_GROUP(namerec)) ) ) {
889 if( DEBUGLVL( 3 ) ) {
890 dbgtext( "wins_process_name_refresh_request: " );
891 dbgtext( "Name %s ", nmb_namestr(question) );
892 dbgtext( "group bit = %s does not match ",
893 group ? "True" : "False" );
894 dbgtext( "group bit in WINS for this name.\n" );
896 send_wins_name_registration_response(RFS_ERR, 0, p);
901 * For a unique name check that the person refreshing the name is
902 * one of the registered IP addresses. If not - fail the refresh.
903 * Do the same for group names with a type of 0x1c.
904 * Just return success for unique 0x1d refreshes. For normal group
905 * names update the ttl and return success.
907 if( (!group || (group && (question->name_type == 0x1c)))
908 && find_ip_in_name_record(namerec, from_ip) ) {
912 update_name_ttl(namerec, ttl);
915 * if the record is a replica:
916 * we take ownership and update the version ID.
918 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
919 update_wins_owner(namerec, our_fake_ip);
920 get_global_id_and_update(&namerec->data.id, True);
923 send_wins_name_registration_response(0, ttl, p);
924 wins_hook("refresh", namerec, ttl);
926 } else if((group && (question->name_type == 0x1c))) {
928 * Added by crh for bug #1079.
929 * Fix from Bert Driehuis
931 if( DEBUGLVL( 3 ) ) {
932 dbgtext( "wins_process_name_refresh_request: " );
933 dbgtext( "Name refresh for name %s, ",
934 nmb_namestr(question) );
935 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
936 dbgtext( "is not yet associated with " );
937 dbgtext( "that name. Treating as registration.\n" );
939 wins_process_name_registration_request(subrec,p);
943 * Normal groups are all registered with an IP address of
944 * 255.255.255.255 so we can't search for the IP address.
946 update_name_ttl(namerec, ttl);
947 wins_hook("refresh", namerec, ttl);
948 send_wins_name_registration_response(0, ttl, p);
950 } else if(!group && (question->name_type == 0x1d)) {
952 * Special name type - just pretend the refresh succeeded.
954 send_wins_name_registration_response(0, ttl, p);
960 if( DEBUGLVL( 3 ) ) {
961 dbgtext( "wins_process_name_refresh_request: " );
962 dbgtext( "Name refresh for name %s with IP %s ",
963 nmb_namestr(question), inet_ntoa(from_ip) );
964 dbgtext( "and is IP is not known to the name.\n" );
966 send_wins_name_registration_response(RFS_ERR, 0, p);
971 /***********************************************************************
972 Deal with a name registration request query success to a client that
975 We have a locked pointer to the original packet stashed away in the
976 userdata pointer. The success here is actually a failure as it means
977 the client we queried wants to keep the name, so we must return
978 a registration failure to the original requestor.
979 ************************************************************************/
981 static void wins_register_query_success(struct subnet_record *subrec,
982 struct userdata_struct *userdata,
983 struct nmb_name *question_name,
985 struct res_rec *answers)
987 struct packet_struct *orig_reg_packet;
989 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
991 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
992 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
994 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
996 orig_reg_packet->locked = False;
997 free_packet(orig_reg_packet);
1000 /***********************************************************************
1001 Deal with a name registration request query failure to a client that
1004 We have a locked pointer to the original packet stashed away in the
1005 userdata pointer. The failure here is actually a success as it means
1006 the client we queried didn't want to keep the name, so we can remove
1007 the old name record and then successfully add the new name.
1008 ************************************************************************/
1010 static void wins_register_query_fail(struct subnet_record *subrec,
1011 struct response_record *rrec,
1012 struct nmb_name *question_name,
1015 struct userdata_struct *userdata = rrec->userdata;
1016 struct packet_struct *orig_reg_packet;
1017 struct name_record *namerec = NULL;
1019 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1022 * We want to just add the name, as we now know the original owner
1023 * didn't want it. But we can't just do that as an arbitary
1024 * amount of time may have taken place between the name query
1025 * request and this timeout/error response. So we check that
1026 * the name still exists and is in the same state - if so
1027 * we remove it and call wins_process_name_registration_request()
1028 * as we know it will do the right thing now.
1031 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1033 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1034 ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1035 remove_name_from_namelist( subrec, namerec);
1039 if(namerec == NULL) {
1040 wins_process_name_registration_request(subrec, orig_reg_packet);
1042 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1043 "querying for name %s in order to replace it and this reply.\n",
1044 nmb_namestr(question_name) ));
1047 orig_reg_packet->locked = False;
1048 free_packet(orig_reg_packet);
1051 /***********************************************************************
1052 Deal with a name registration request to a WINS server.
1054 Use the following pseudocode :
1059 +--------name exists
1062 | +--- existing name is group
1065 | | +--- add name (return).
1068 | +--- exiting name is unique
1071 | +--- query existing owner (return).
1074 +--------name doesn't exist
1077 +--- add name (return).
1082 +--------name exists
1085 | +--- existing name is group
1088 | | +--- fail add (return).
1091 | +--- exiting name is unique
1094 | +--- query existing owner (return).
1097 +--------name doesn't exist
1100 +--- add name (return).
1102 As can be seen from the above, the two cases may be collapsed onto each
1103 other with the exception of the case where the name already exists and
1104 is a group name. This case we handle with an if statement.
1106 ************************************************************************/
1108 void wins_process_name_registration_request(struct subnet_record *subrec,
1109 struct packet_struct *p)
1112 struct nmb_packet *nmb = &p->packet.nmb;
1113 struct nmb_name *question = &nmb->question.question_name;
1114 bool bcast = nmb->header.nm_flags.bcast;
1115 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1116 int ttl = get_ttl_from_packet(nmb);
1117 struct name_record *namerec = NULL;
1118 struct in_addr from_ip;
1119 bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1120 struct in_addr our_fake_ip;
1122 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1123 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1127 * We should only get unicast name registration packets here.
1128 * Anyone trying to register broadcast should not be going to a WINS
1129 * server. Log an error here.
1132 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1133 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1134 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1138 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1139 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1142 * See if the name already exists.
1145 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1148 * if the record exists but NOT in active state,
1151 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1152 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1153 not active - removing it.\n", nmb_namestr(question) ));
1154 remove_name_from_namelist( subrec, namerec );
1159 * Deal with the case where the name found was a dns entry.
1160 * Remove it as we now have a NetBIOS client registering the
1164 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1165 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1166 a dns lookup - removing it.\n", nmb_namestr(question) ));
1167 remove_name_from_namelist( subrec, namerec );
1172 * Reject if the name exists and is not a REGISTER_NAME.
1173 * (ie. Don't allow any static names to be overwritten.
1176 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1177 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1178 to register name %s. Name already exists in WINS with source type %d.\n",
1179 nmb_namestr(question), namerec->data.source ));
1180 send_wins_name_registration_response(RFS_ERR, 0, p);
1185 * Special policy decisions based on MS documentation.
1186 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1187 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1191 * A group name is always added as the local broadcast address, except
1192 * for group names ending in 0x1c.
1193 * Group names with type 0x1c are registered with individual IP addresses.
1196 if(registering_group_name && (question->name_type != 0x1c)) {
1197 (void)interpret_addr2(&from_ip, "255.255.255.255");
1201 * Ignore all attempts to register a unique 0x1d name, although return success.
1204 if(!registering_group_name && (question->name_type == 0x1d)) {
1205 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1206 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1207 send_wins_name_registration_response(0, ttl, p);
1212 * Next two cases are the 'if statement' mentioned above.
1215 if((namerec != NULL) && NAME_GROUP(namerec)) {
1216 if(registering_group_name) {
1218 * If we are adding a group name, the name exists and is also a group entry just add this
1219 * IP address to it and update the ttl.
1222 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1223 inet_ntoa(from_ip), nmb_namestr(question) ));
1226 * Check the ip address is not already in the group.
1229 if(!find_ip_in_name_record(namerec, from_ip)) {
1230 add_ip_to_name_record(namerec, from_ip);
1231 /* we need to update the record for replication */
1232 get_global_id_and_update(&namerec->data.id, True);
1235 * if the record is a replica, we must change
1236 * the wins owner to us to make the replication updates
1237 * it on the other wins servers.
1238 * And when the partner will receive this record,
1239 * it will update its own record.
1242 update_wins_owner(namerec, our_fake_ip);
1244 update_name_ttl(namerec, ttl);
1245 wins_hook("refresh", namerec, ttl);
1246 send_wins_name_registration_response(0, ttl, p);
1251 * If we are adding a unique name, the name exists in the WINS db
1252 * and is a group name then reject the registration.
1254 * explanation: groups have a higher priority than unique names.
1257 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1258 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1259 send_wins_name_registration_response(RFS_ERR, 0, p);
1265 * From here on down we know that if the name exists in the WINS db it is
1266 * a unique name, not a group name.
1270 * If the name exists and is one of our names then check the
1271 * registering IP address. If it's not one of ours then automatically
1272 * reject without doing the query - we know we will reject it.
1275 if ( namerec != NULL ) {
1276 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1277 if( is_myname(name) ) {
1278 if(!ismyip_v4(from_ip)) {
1279 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1280 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1281 send_wins_name_registration_response(RFS_ERR, 0, p);
1285 * It's one of our names and one of our IP's - update the ttl.
1287 update_name_ttl(namerec, ttl);
1288 wins_hook("refresh", namerec, ttl);
1289 send_wins_name_registration_response(0, ttl, p);
1298 * If the name exists and it is a unique registration and the registering IP
1299 * is the same as the (single) already registered IP then just update the ttl.
1301 * But not if the record is an active replica. IF it's a replica, it means it can be
1302 * the same client which has moved and not yet expired. So we don't update
1303 * the ttl in this case and go beyond to do a WACK and query the old client
1306 if( !registering_group_name
1307 && (namerec != NULL)
1308 && (namerec->data.num_ips == 1)
1309 && ip_equal_v4( namerec->data.ip[0], from_ip )
1310 && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1311 update_name_ttl( namerec, ttl );
1312 wins_hook("refresh", namerec, ttl);
1313 send_wins_name_registration_response( 0, ttl, p );
1318 * Finally if the name exists do a query to the registering machine
1319 * to see if they still claim to have the name.
1322 if( namerec != NULL ) {
1323 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1324 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1327 * First send a WACK to the registering machine.
1330 send_wins_wack_response(60, p);
1333 * When the reply comes back we need the original packet.
1334 * Lock this so it won't be freed and then put it into
1335 * the userdata structure.
1340 userdata = (struct userdata_struct *)ud;
1342 userdata->copy_fn = NULL;
1343 userdata->free_fn = NULL;
1344 userdata->userdata_len = sizeof(struct packet_struct *);
1345 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1348 * Use the new call to send a query directly to an IP address.
1349 * This sends the query directly to the IP address, and ensures
1350 * the recursion desired flag is not set (you were right Luke :-).
1351 * This function should *only* be called from the WINS server
1355 pull_ascii_nstring(name, sizeof(name), question->name);
1356 query_name_from_wins_server( *namerec->data.ip,
1358 question->name_type,
1359 wins_register_query_success,
1360 wins_register_query_fail,
1366 * Name did not exist - add it.
1369 pull_ascii_nstring(name, sizeof(name), question->name);
1370 add_name_to_subnet( subrec, name, question->name_type,
1371 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1373 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1374 get_global_id_and_update(&namerec->data.id, True);
1375 update_wins_owner(namerec, our_fake_ip);
1376 update_wins_flag(namerec, WINS_ACTIVE);
1377 wins_hook("add", namerec, ttl);
1380 send_wins_name_registration_response(0, ttl, p);
1383 /***********************************************************************
1384 Deal with a mutihomed name query success to the machine that
1385 requested the multihomed name registration.
1387 We have a locked pointer to the original packet stashed away in the
1389 ************************************************************************/
1391 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1392 struct userdata_struct *userdata,
1393 struct nmb_name *question_name,
1395 struct res_rec *answers)
1397 struct packet_struct *orig_reg_packet;
1398 struct nmb_packet *nmb;
1399 struct name_record *namerec = NULL;
1400 struct in_addr from_ip;
1402 struct in_addr our_fake_ip;
1404 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1405 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1407 nmb = &orig_reg_packet->packet.nmb;
1409 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1410 ttl = get_ttl_from_packet(nmb);
1413 * We want to just add the new IP, as we now know the requesting
1414 * machine claims to own it. But we can't just do that as an arbitary
1415 * amount of time may have taken place between the name query
1416 * request and this response. So we check that
1417 * the name still exists and is in the same state - if so
1418 * we just add the extra IP and update the ttl.
1421 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1423 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1424 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1425 a subsequent IP address.\n", nmb_namestr(question_name) ));
1426 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1428 orig_reg_packet->locked = False;
1429 free_packet(orig_reg_packet);
1434 if(!find_ip_in_name_record(namerec, from_ip)) {
1435 add_ip_to_name_record(namerec, from_ip);
1438 get_global_id_and_update(&namerec->data.id, True);
1439 update_wins_owner(namerec, our_fake_ip);
1440 update_wins_flag(namerec, WINS_ACTIVE);
1441 update_name_ttl(namerec, ttl);
1442 wins_hook("add", namerec, ttl);
1443 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1445 orig_reg_packet->locked = False;
1446 free_packet(orig_reg_packet);
1449 /***********************************************************************
1450 Deal with a name registration request query failure to a client that
1453 We have a locked pointer to the original packet stashed away in the
1455 ************************************************************************/
1457 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1458 struct response_record *rrec,
1459 struct nmb_name *question_name,
1462 struct userdata_struct *userdata = rrec->userdata;
1463 struct packet_struct *orig_reg_packet;
1465 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1467 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1468 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1469 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1471 orig_reg_packet->locked = False;
1472 free_packet(orig_reg_packet);
1476 /***********************************************************************
1477 Deal with a multihomed name registration request to a WINS server.
1478 These cannot be group name registrations.
1479 ***********************************************************************/
1481 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1482 struct packet_struct *p)
1484 struct nmb_packet *nmb = &p->packet.nmb;
1485 struct nmb_name *question = &nmb->question.question_name;
1486 bool bcast = nmb->header.nm_flags.bcast;
1487 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1488 int ttl = get_ttl_from_packet(nmb);
1489 struct name_record *namerec = NULL;
1490 struct in_addr from_ip;
1491 bool group = (nb_flags & NB_GROUP) ? True : False;
1492 struct in_addr our_fake_ip;
1495 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
1496 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1500 * We should only get unicast name registration packets here.
1501 * Anyone trying to register broadcast should not be going to a WINS
1502 * server. Log an error here.
1505 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1506 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1507 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1512 * Only unique names should be registered multihomed.
1516 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1517 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1518 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1522 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1523 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1526 * Deal with policy regarding 0x1d names.
1529 if(question->name_type == 0x1d) {
1530 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1531 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1532 send_wins_name_registration_response(0, ttl, p);
1537 * See if the name already exists.
1540 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1543 * if the record exists but NOT in active state,
1547 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1548 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1549 remove_name_from_namelist(subrec, namerec);
1554 * Deal with the case where the name found was a dns entry.
1555 * Remove it as we now have a NetBIOS client registering the
1559 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1560 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1561 - removing it.\n", nmb_namestr(question) ));
1562 remove_name_from_namelist( subrec, namerec);
1567 * Reject if the name exists and is not a REGISTER_NAME.
1568 * (ie. Don't allow any static names to be overwritten.
1571 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1572 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1573 to register name %s. Name already exists in WINS with source type %d.\n",
1574 nmb_namestr(question), namerec->data.source ));
1575 send_wins_name_registration_response(RFS_ERR, 0, p);
1580 * Reject if the name exists and is a GROUP name and is active.
1583 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1584 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1585 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1586 send_wins_name_registration_response(RFS_ERR, 0, p);
1591 * From here on down we know that if the name exists in the WINS db it is
1592 * a unique name, not a group name.
1596 * If the name exists and is one of our names then check the
1597 * registering IP address. If it's not one of ours then automatically
1598 * reject without doing the query - we know we will reject it.
1601 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1602 if(!ismyip_v4(from_ip)) {
1603 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1604 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1605 send_wins_name_registration_response(RFS_ERR, 0, p);
1609 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1610 * update the ttl. Update the version ID to force replication.
1612 update_name_ttl(namerec, ttl);
1614 if(!find_ip_in_name_record(namerec, from_ip)) {
1615 get_global_id_and_update(&namerec->data.id, True);
1616 update_wins_owner(namerec, our_fake_ip);
1617 update_wins_flag(namerec, WINS_ACTIVE);
1619 add_ip_to_name_record(namerec, from_ip);
1622 wins_hook("refresh", namerec, ttl);
1623 send_wins_name_registration_response(0, ttl, p);
1629 * If the name exists and is active, check if the IP address is already registered
1630 * to that name. If so then update the ttl and reply success.
1633 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1634 update_name_ttl(namerec, ttl);
1637 * If it's a replica, we need to become the wins owner
1638 * to force the replication
1640 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1641 get_global_id_and_update(&namerec->data.id, True);
1642 update_wins_owner(namerec, our_fake_ip);
1643 update_wins_flag(namerec, WINS_ACTIVE);
1646 wins_hook("refresh", namerec, ttl);
1647 send_wins_name_registration_response(0, ttl, p);
1652 * If the name exists do a query to the owner
1653 * to see if they still want the name.
1656 if(namerec != NULL) {
1657 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1658 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1661 * First send a WACK to the registering machine.
1664 send_wins_wack_response(60, p);
1667 * When the reply comes back we need the original packet.
1668 * Lock this so it won't be freed and then put it into
1669 * the userdata structure.
1674 userdata = (struct userdata_struct *)ud;
1676 userdata->copy_fn = NULL;
1677 userdata->free_fn = NULL;
1678 userdata->userdata_len = sizeof(struct packet_struct *);
1679 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1682 * Use the new call to send a query directly to an IP address.
1683 * This sends the query directly to the IP address, and ensures
1684 * the recursion desired flag is not set (you were right Luke :-).
1685 * This function should *only* be called from the WINS server
1688 * Note that this packet is sent to the current owner of the name,
1689 * not the person who sent the packet
1692 pull_ascii_nstring( qname, sizeof(qname), question->name);
1693 query_name_from_wins_server( namerec->data.ip[0],
1695 question->name_type,
1696 wins_multihomed_register_query_success,
1697 wins_multihomed_register_query_fail,
1704 * Name did not exist - add it.
1707 pull_ascii_nstring( qname, sizeof(qname), question->name);
1708 add_name_to_subnet( subrec, qname, question->name_type,
1709 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1711 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1712 get_global_id_and_update(&namerec->data.id, True);
1713 update_wins_owner(namerec, our_fake_ip);
1714 update_wins_flag(namerec, WINS_ACTIVE);
1715 wins_hook("add", namerec, ttl);
1718 send_wins_name_registration_response(0, ttl, p);
1721 /***********************************************************************
1722 Fetch all *<1b> names from the WINS db and store on the namelist.
1723 ***********************************************************************/
1725 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1727 struct name_record *namerec = NULL;
1729 if (kbuf.dsize != sizeof(unstring) + 1) {
1733 /* Filter out all non-1b names. */
1734 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1738 namerec = wins_record_to_name_record(kbuf, dbuf);
1743 DLIST_ADD(wins_server_subnet->namelist, namerec);
1747 void fetch_all_active_wins_1b_names(void)
1749 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1752 /***********************************************************************
1753 Deal with the special name query for *<1b>.
1754 ***********************************************************************/
1756 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1757 struct packet_struct *p)
1759 struct name_record *namerec = NULL;
1764 * Go through all the ACTIVE names in the WINS db looking for those
1765 * ending in <1b>. Use this to calculate the number of IP
1766 * addresses we need to return.
1771 /* First, clear the in memory list - we're going to re-populate
1772 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1774 wins_delete_all_tmp_in_memory_records();
1776 fetch_all_active_wins_1b_names();
1778 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1779 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1780 num_ips += namerec->data.num_ips;
1786 * There are no 0x1b names registered. Return name query fail.
1788 send_wins_name_query_response(NAM_ERR, p, NULL);
1792 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1793 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1798 * Go through all the names again in the WINS db looking for those
1799 * ending in <1b>. Add their IP addresses into the list we will
1804 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1805 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1807 for(i = 0; i < namerec->data.num_ips; i++) {
1808 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1809 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1816 * Send back the reply containing the IP list.
1819 reply_netbios_packet(p, /* Packet to reply to. */
1820 0, /* Result code. */
1821 WINS_QUERY, /* nmbd type code. */
1822 NMB_NAME_QUERY_OPCODE, /* opcode. */
1823 lp_min_wins_ttl(), /* ttl. */
1824 prdata, /* data to send. */
1825 num_ips*6); /* data length. */
1830 /****************************************************************************
1831 Send a WINS name query response.
1832 **************************************************************************/
1834 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1835 struct name_record *namerec)
1838 char *prdata = rdata;
1839 int reply_data_len = 0;
1843 memset(rdata,'\0',6);
1846 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1848 /* Copy all known ip addresses into the return data. */
1849 /* Optimise for the common case of one IP address so we don't need a malloc. */
1851 if( namerec->data.num_ips == 1 ) {
1854 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1855 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1860 for(i = 0; i < namerec->data.num_ips; i++) {
1861 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1862 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1865 sort_query_replies(prdata, i, p->ip);
1866 reply_data_len = namerec->data.num_ips * 6;
1869 reply_netbios_packet(p, /* Packet to reply to. */
1870 rcode, /* Result code. */
1871 WINS_QUERY, /* nmbd type code. */
1872 NMB_NAME_QUERY_OPCODE, /* opcode. */
1874 prdata, /* data to send. */
1875 reply_data_len); /* data length. */
1877 if(prdata != rdata) {
1882 /***********************************************************************
1883 Deal with a name query.
1884 ***********************************************************************/
1886 void wins_process_name_query_request(struct subnet_record *subrec,
1887 struct packet_struct *p)
1889 struct nmb_packet *nmb = &p->packet.nmb;
1890 struct nmb_name *question = &nmb->question.question_name;
1891 struct name_record *namerec = NULL;
1894 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1895 nmb_namestr(question), inet_ntoa(p->ip) ));
1898 * Special name code. If the queried name is *<1b> then search
1899 * the entire WINS database and return a list of all the IP addresses
1900 * registered to any <1b> name. This is to allow domain master browsers
1901 * to discover other domains that may not have a presence on their subnet.
1904 pull_ascii_nstring(qname, sizeof(qname), question->name);
1905 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1906 process_wins_dmb_query_request( subrec, p);
1910 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1912 if(namerec != NULL) {
1914 * If the name is not anymore in active state then reply not found.
1915 * it's fair even if we keep it in the cache for days.
1917 if (!WINS_STATE_ACTIVE(namerec)) {
1918 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1919 nmb_namestr(question) ));
1920 send_wins_name_query_response(NAM_ERR, p, namerec);
1925 * If it's a DNSFAIL_NAME then reply name not found.
1928 if( namerec->data.source == DNSFAIL_NAME ) {
1929 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1930 nmb_namestr(question) ));
1931 send_wins_name_query_response(NAM_ERR, p, namerec);
1936 * If the name has expired then reply name not found.
1939 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1940 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1941 nmb_namestr(question) ));
1942 send_wins_name_query_response(NAM_ERR, p, namerec);
1946 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1947 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1949 send_wins_name_query_response(0, p, namerec);
1954 * Name not found in WINS - try a dns query if it's a 0x20 name.
1957 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1958 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1959 nmb_namestr(question) ));
1961 queue_dns_query(p, question);
1966 * Name not found - return error.
1969 send_wins_name_query_response(NAM_ERR, p, NULL);
1972 /****************************************************************************
1973 Send a WINS name release response.
1974 **************************************************************************/
1976 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1978 struct nmb_packet *nmb = &p->packet.nmb;
1981 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1983 reply_netbios_packet(p, /* Packet to reply to. */
1984 rcode, /* Result code. */
1985 NMB_REL, /* nmbd type code. */
1986 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1988 rdata, /* data to send. */
1989 6); /* data length. */
1992 /***********************************************************************
1993 Deal with a name release.
1994 ***********************************************************************/
1996 void wins_process_name_release_request(struct subnet_record *subrec,
1997 struct packet_struct *p)
1999 struct nmb_packet *nmb = &p->packet.nmb;
2000 struct nmb_name *question = &nmb->question.question_name;
2001 bool bcast = nmb->header.nm_flags.bcast;
2002 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
2003 struct name_record *namerec = NULL;
2004 struct in_addr from_ip;
2005 bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
2007 putip((char *)&from_ip,&nmb->additional->rdata[2]);
2011 * We should only get unicast name registration packets here.
2012 * Anyone trying to register broadcast should not be going to a WINS
2013 * server. Log an error here.
2016 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2017 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2018 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2022 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2023 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2026 * Deal with policy regarding 0x1d names.
2029 if(!releasing_group_name && (question->name_type == 0x1d)) {
2030 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2031 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2032 send_wins_name_release_response(0, p);
2037 * See if the name already exists.
2040 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2042 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2043 send_wins_name_release_response(NAM_ERR, p);
2048 * Check that the sending machine has permission to release this name.
2049 * If it's a group name not ending in 0x1c then just say yes and let
2050 * the group time out.
2053 if(releasing_group_name && (question->name_type != 0x1c)) {
2054 send_wins_name_release_response(0, p);
2059 * Check that the releasing node is on the list of IP addresses
2060 * for this name. Disallow the release if not.
2063 if(!find_ip_in_name_record(namerec, from_ip)) {
2064 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2065 release name %s as IP %s is not one of the known IP's for this name.\n",
2066 nmb_namestr(question), inet_ntoa(from_ip) ));
2067 send_wins_name_release_response(NAM_ERR, p);
2072 * Check if the record is active. IF it's already released
2073 * or tombstoned, refuse the release.
2076 if (!WINS_STATE_ACTIVE(namerec)) {
2077 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2078 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2079 send_wins_name_release_response(NAM_ERR, p);
2084 * Check if the record is a 0x1c group
2085 * and has more then one ip
2086 * remove only this address.
2089 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2090 remove_ip_from_name_record(namerec, from_ip);
2091 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2092 inet_ntoa(from_ip),nmb_namestr(question)));
2093 wins_hook("delete", namerec, 0);
2094 send_wins_name_release_response(0, p);
2099 * Send a release response.
2100 * Flag the name as released and update the ttl
2103 namerec->data.wins_flags |= WINS_RELEASED;
2104 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2106 wins_hook("delete", namerec, 0);
2107 send_wins_name_release_response(0, p);
2110 /*******************************************************************
2111 WINS time dependent processing.
2112 ******************************************************************/
2114 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2116 time_t t = *(time_t *)state;
2117 bool store_record = False;
2118 struct name_record *namerec = NULL;
2119 struct in_addr our_fake_ip;
2121 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
2122 if (kbuf.dsize != sizeof(unstring) + 1) {
2126 namerec = wins_record_to_name_record(kbuf, dbuf);
2131 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2132 if( namerec->data.source == SELF_NAME ) {
2133 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2134 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2135 namerec->data.death_time += 300;
2136 store_record = True;
2138 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2139 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2140 nmb_namestr(&namerec->name)));
2141 remove_name_from_wins_namelist(namerec );
2145 /* handle records, samba is the wins owner */
2146 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2147 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2149 namerec->data.wins_flags&=~WINS_STATE_MASK;
2150 namerec->data.wins_flags|=WINS_RELEASED;
2151 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2152 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2153 nmb_namestr(&namerec->name)));
2154 store_record = True;
2157 namerec->data.wins_flags&=~WINS_STATE_MASK;
2158 namerec->data.wins_flags|=WINS_TOMBSTONED;
2159 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2160 get_global_id_and_update(&namerec->data.id, True);
2161 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2162 nmb_namestr(&namerec->name)));
2163 store_record = True;
2165 case WINS_TOMBSTONED:
2166 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2167 nmb_namestr(&namerec->name)));
2168 remove_name_from_wins_namelist(namerec );
2172 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2174 /* that's not as MS says it should be */
2175 namerec->data.wins_flags&=~WINS_STATE_MASK;
2176 namerec->data.wins_flags|=WINS_TOMBSTONED;
2177 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2178 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2179 nmb_namestr(&namerec->name)));
2180 store_record = True;
2182 case WINS_TOMBSTONED:
2183 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2184 nmb_namestr(&namerec->name)));
2185 remove_name_from_wins_namelist(namerec );
2188 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2189 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2198 wins_store_changed_namerec(namerec);
2201 SAFE_FREE(namerec->data.ip);
2207 /*******************************************************************
2208 Time dependent wins processing.
2209 ******************************************************************/
2211 void initiate_wins_processing(time_t t)
2213 static time_t lasttime = 0;
2218 if (t - lasttime < 20) {
2222 if(!lp_we_are_a_wins_server()) {
2227 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2229 wins_delete_all_tmp_in_memory_records();
2231 wins_write_database(t, True);
2236 /*******************************************************************
2237 Write out one record.
2238 ******************************************************************/
2240 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2245 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2247 if( namerec->data.death_time != PERMANENT_TTL ) {
2250 tm = localtime(&namerec->data.death_time);
2258 nl = strrchr( ts, '\n' );
2262 DEBUGADD(4,("TTL = %s ", ts ));
2264 DEBUGADD(4,("TTL = PERMANENT "));
2267 for (i = 0; i < namerec->data.num_ips; i++) {
2268 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2270 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2272 if( namerec->data.source == REGISTER_NAME ) {
2274 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2275 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2276 (int)namerec->data.death_time);
2278 for (i = 0; i < namerec->data.num_ips; i++)
2279 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2280 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2284 /*******************************************************************
2285 Write out the current WINS database.
2286 ******************************************************************/
2288 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2290 struct name_record *namerec = NULL;
2291 XFILE *fp = (XFILE *)state;
2293 if (kbuf.dsize != sizeof(unstring) + 1) {
2297 namerec = wins_record_to_name_record(kbuf, dbuf);
2302 wins_write_name_record(namerec, fp);
2304 SAFE_FREE(namerec->data.ip);
2310 void wins_write_database(time_t t, bool background)
2312 static time_t last_write_time = 0;
2313 pstring fname, fnamenew;
2318 if (!last_write_time) {
2319 last_write_time = t;
2321 if (t - last_write_time < 120) {
2327 if(!lp_we_are_a_wins_server()) {
2331 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2337 if (tdb_reopen(wins_tdb)) {
2338 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2345 slprintf(fname,sizeof(fname)-1,"%s/%s", dyn_STATEDIR(), WINS_LIST);
2346 all_string_sub(fname,"//", "/", 0);
2347 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
2349 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2350 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2357 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2359 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2361 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2364 chmod(fnamenew,0644);
2366 rename(fnamenew,fname);
2373 Until winsrepl is done.
2374 /****************************************************************************
2375 Process a internal Samba message receiving a wins record.
2376 ***************************************************************************/
2378 void nmbd_wins_new_entry(struct messaging_context *msg,
2381 struct server_id server_id,
2384 WINS_RECORD *record;
2385 struct name_record *namerec = NULL;
2386 struct name_record *new_namerec = NULL;
2387 struct nmb_name question;
2388 bool overwrite=False;
2389 struct in_addr our_fake_ip;
2392 (void)interpret_addr2(&our_fake_ip, "0.0.0.0");
2397 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2398 record=(WINS_RECORD *)buf;
2400 make_nmb_name(&question, record->name, record->type);
2402 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2404 /* record doesn't exist, add it */
2405 if (namerec == NULL) {
2406 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2407 record->name, record->type, inet_ntoa(record->wins_ip)));
2409 new_namerec=add_name_to_subnet( wins_server_subnet,
2413 EXTINCTION_INTERVAL,
2418 if (new_namerec!=NULL) {
2419 update_wins_owner(new_namerec, record->wins_ip);
2420 update_wins_flag(new_namerec, record->wins_flags);
2421 new_namerec->data.id=record->id;
2423 wins_server_subnet->namelist_changed = True;
2427 /* check if we have a conflict */
2428 if (namerec != NULL) {
2429 /* both records are UNIQUE */
2430 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2432 /* the database record is a replica */
2433 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2434 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2435 if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2440 /* we are the wins owner of the database record */
2441 /* the 2 records have the same IP address */
2442 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2443 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2444 get_global_id_and_update(&namerec->data.id, True);
2449 /* the 2 records have different IP address */
2450 if (namerec->data.wins_flags&WINS_ACTIVE) {
2451 if (record->wins_flags&WINS_TOMBSTONED)
2452 get_global_id_and_update(&namerec->data.id, True);
2453 if (record->wins_flags&WINS_ACTIVE)
2454 /* send conflict challenge to the replica node */
2463 /* the replica is a standard group */
2464 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2465 /* if the database record is unique and active force a name release */
2466 if (namerec->data.wins_flags&WINS_UNIQUE)
2467 /* send a release name to the unique node */
2473 /* the replica is a special group */
2474 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2475 if (namerec->data.wins_flags&WINS_ACTIVE) {
2476 for (i=0; i<record->num_ips; i++)
2477 if(!find_ip_in_name_record(namerec, record->ip[i]))
2478 add_ip_to_name_record(namerec, record->ip[i]);
2484 /* the replica is a multihomed host */
2486 /* I'm giving up on multi homed. Too much complex to understand */
2488 if (record->wins_flags&WINS_MHOMED) {
2489 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2490 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2494 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2497 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2498 if (namerec->data.wins_flags&WINS_UNIQUE)
2499 get_global_id_and_update(&namerec->data.id, True);
2503 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2504 if (namerec->data.wins_flags&WINS_UNIQUE ||
2505 namerec->data.wins_flags&WINS_MHOMED)
2506 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2511 if (overwrite == False)
2512 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2513 record->name, record->type, inet_ntoa(record->wins_ip)));
2515 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2516 record->name, record->type, inet_ntoa(record->wins_ip)));
2518 /* remove the old record and add a new one */
2519 remove_name_from_namelist( wins_server_subnet, namerec );
2520 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2521 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2522 if (new_namerec!=NULL) {
2523 update_wins_owner(new_namerec, record->wins_ip);
2524 update_wins_flag(new_namerec, record->wins_flags);
2525 new_namerec->data.id=record->id;
2527 wins_server_subnet->namelist_changed = True;
2530 wins_server_subnet->namelist_changed = True;