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.
24 #include "system/filesys.h"
25 #include "nmbd/nmbd.h"
27 #define WINS_LIST "wins.dat"
28 #define WINS_VERSION 1
29 #define WINSDB_VERSION 1
31 /****************************************************************************
32 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
33 name (65 bytes with the last byte being the name type).
34 *****************************************************************************/
36 TDB_CONTEXT *wins_tdb;
38 /****************************************************************************
39 Delete all the temporary name records on the in-memory linked list.
40 *****************************************************************************/
42 static void wins_delete_all_tmp_in_memory_records(void)
44 struct name_record *nr = NULL;
45 struct name_record *nrnext = NULL;
47 /* Delete all temporary name records on the wins subnet linked list. */
48 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
50 DLIST_REMOVE(wins_server_subnet->namelist, nr);
51 SAFE_FREE(nr->data.ip);
56 /****************************************************************************
57 Delete all the temporary 1b name records on the in-memory linked list.
58 *****************************************************************************/
60 static void wins_delete_all_1b_in_memory_records(void)
62 struct name_record *nr = NULL;
63 struct name_record *nrnext = NULL;
65 /* Delete all temporary 1b name records on the wins subnet linked list. */
66 for( nr = wins_server_subnet->namelist; nr; nr = nrnext) {
68 if (nr->name.name_type == 0x1b) {
69 DLIST_REMOVE(wins_server_subnet->namelist, nr);
70 SAFE_FREE(nr->data.ip);
76 /****************************************************************************
77 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
78 *****************************************************************************/
80 static struct name_record *wins_record_to_name_record(TDB_DATA key, TDB_DATA data)
82 struct name_record *namerec = NULL;
85 uint32 death_time, refresh_time;
86 uint32 id_low, id_high;
93 if (data.dptr == NULL || data.dsize == 0) {
97 /* Min size is "wbddddddd" + 1 ip address (4). */
98 if (data.dsize < 2 + 1 + (7*4) + 4) {
102 len = tdb_unpack(data.dptr, data.dsize,
114 namerec = SMB_MALLOC_P(struct name_record);
118 ZERO_STRUCTP(namerec);
120 namerec->data.ip = SMB_MALLOC_ARRAY(struct in_addr, num_ips);
121 if (!namerec->data.ip) {
126 namerec->subnet = wins_server_subnet;
127 push_ascii_nstring(namerec->name.name, (const char *)key.dptr);
128 namerec->name.name_type = key.dptr[sizeof(unstring)];
130 push_ascii(namerec->name.scope, global_scope(), 64, STR_TERMINATE);
132 /* We're using a byte-by-byte compare, so we must be sure that
133 * unused space doesn't have garbage in it.
136 for( i = strlen( namerec->name.name ); i < sizeof( namerec->name.name ); i++ ) {
137 namerec->name.name[i] = '\0';
139 for( i = strlen( namerec->name.scope ); i < sizeof( namerec->name.scope ); i++ ) {
140 namerec->name.scope[i] = '\0';
143 namerec->data.nb_flags = nb_flags;
144 namerec->data.source = (enum name_source)nr_src;
145 namerec->data.death_time = (time_t)death_time;
146 namerec->data.refresh_time = (time_t)refresh_time;
147 namerec->data.id = id_low;
148 #if defined(HAVE_LONGLONG)
149 namerec->data.id |= ((uint64_t)id_high << 32);
151 namerec->data.wins_ip.s_addr = saddr;
152 namerec->data.wins_flags = wins_flags,
153 namerec->data.num_ips = num_ips;
155 for (i = 0; i < num_ips; i++) {
156 namerec->data.ip[i].s_addr = IVAL(data.dptr, len + (i*4));
162 /****************************************************************************
163 Convert a struct name_record to a wins.tdb record. Ignore the scope.
164 *****************************************************************************/
166 static TDB_DATA name_record_to_wins_record(const struct name_record *namerec)
171 uint32 id_low = (namerec->data.id & 0xFFFFFFFF);
172 #if defined(HAVE_LONGLONG)
173 uint32 id_high = (namerec->data.id >> 32) & 0xFFFFFFFF;
180 len = (2 + 1 + (7*4)); /* "wbddddddd" */
181 len += (namerec->data.num_ips * 4);
183 data.dptr = (uint8 *)SMB_MALLOC(len);
189 len = tdb_pack(data.dptr, data.dsize, "wbddddddd",
190 namerec->data.nb_flags,
191 (unsigned char)namerec->data.source,
192 (uint32)namerec->data.death_time,
193 (uint32)namerec->data.refresh_time,
196 (uint32)namerec->data.wins_ip.s_addr,
197 (uint32)namerec->data.wins_flags,
198 (uint32)namerec->data.num_ips );
200 for (i = 0; i < namerec->data.num_ips; i++) {
201 SIVAL(data.dptr, len + (i*4), namerec->data.ip[i].s_addr);
207 /****************************************************************************
208 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
209 *****************************************************************************/
211 static TDB_DATA name_to_key(const struct nmb_name *nmbname)
213 static char keydata[sizeof(unstring) + 1];
216 memset(keydata, '\0', sizeof(keydata));
218 pull_ascii_nstring(keydata, sizeof(unstring), nmbname->name);
220 keydata[sizeof(unstring)] = nmbname->name_type;
221 key.dptr = (uint8 *)keydata;
222 key.dsize = sizeof(keydata);
227 /****************************************************************************
228 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
229 on the linked list. We will free this later in XXXX().
230 *****************************************************************************/
232 struct name_record *find_name_on_wins_subnet(const struct nmb_name *nmbname, bool self_only)
235 struct name_record *nr = NULL;
236 struct name_record *namerec = NULL;
242 key = name_to_key(nmbname);
243 data = tdb_fetch(wins_tdb, key);
245 if (data.dsize == 0) {
249 namerec = wins_record_to_name_record(key, data);
251 /* done with the this */
253 SAFE_FREE( data.dptr );
259 /* Self names only - these include permanent names. */
260 if( self_only && (namerec->data.source != SELF_NAME) && (namerec->data.source != PERMANENT_NAME) ) {
261 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname) ) );
262 SAFE_FREE(namerec->data.ip);
267 /* Search for this name record on the list. Replace it if found. */
269 for( nr = wins_server_subnet->namelist; nr; nr = nr->next) {
270 if (memcmp(nmbname->name, nr->name.name, 16) == 0) {
272 DLIST_REMOVE(wins_server_subnet->namelist, nr);
273 SAFE_FREE(nr->data.ip);
279 DLIST_ADD(wins_server_subnet->namelist, namerec);
283 /****************************************************************************
284 Overwrite or add a given name in the wins.tdb.
285 *****************************************************************************/
287 static bool store_or_replace_wins_namerec(const struct name_record *namerec, int tdb_flag)
296 key = name_to_key(&namerec->name);
297 data = name_record_to_wins_record(namerec);
299 if (data.dptr == NULL) {
303 ret = tdb_store(wins_tdb, key, data, tdb_flag);
305 SAFE_FREE(data.dptr);
306 return (ret == 0) ? True : False;
309 /****************************************************************************
310 Overwrite a given name in the wins.tdb.
311 *****************************************************************************/
313 bool wins_store_changed_namerec(const struct name_record *namerec)
315 return store_or_replace_wins_namerec(namerec, TDB_REPLACE);
318 /****************************************************************************
319 Primary interface into creating and overwriting records in the wins.tdb.
320 *****************************************************************************/
322 bool add_name_to_wins_subnet(const struct name_record *namerec)
324 return store_or_replace_wins_namerec(namerec, TDB_INSERT);
327 /****************************************************************************
328 Delete a given name in the tdb and remove the temporary malloc'ed data struct
330 *****************************************************************************/
332 bool remove_name_from_wins_namelist(struct name_record *namerec)
341 key = name_to_key(&namerec->name);
342 ret = tdb_delete(wins_tdb, key);
344 DLIST_REMOVE(wins_server_subnet->namelist, namerec);
346 /* namerec must be freed by the caller */
348 return (ret == 0) ? True : False;
351 /****************************************************************************
352 Dump out the complete namelist.
353 *****************************************************************************/
355 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
357 struct name_record *namerec = NULL;
358 XFILE *fp = (XFILE *)state;
360 if (kbuf.dsize != sizeof(unstring) + 1) {
364 namerec = wins_record_to_name_record(kbuf, dbuf);
369 dump_name_record(namerec, fp);
371 SAFE_FREE(namerec->data.ip);
376 void dump_wins_subnet_namelist(XFILE *fp)
378 tdb_traverse(wins_tdb, traverse_fn, (void *)fp);
381 /****************************************************************************
382 Change the wins owner address in the record.
383 *****************************************************************************/
385 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
387 namerec->data.wins_ip=wins_ip;
390 /****************************************************************************
391 Create the wins flags based on the nb flags and the input value.
392 *****************************************************************************/
394 static void update_wins_flag(struct name_record *namerec, int flags)
396 namerec->data.wins_flags=0x0;
398 /* if it's a group, it can be a normal or a special one */
399 if (namerec->data.nb_flags & NB_GROUP) {
400 if (namerec->name.name_type==0x1C) {
401 namerec->data.wins_flags|=WINS_SGROUP;
403 if (namerec->data.num_ips>1) {
404 namerec->data.wins_flags|=WINS_SGROUP;
406 namerec->data.wins_flags|=WINS_NGROUP;
410 /* can be unique or multi-homed */
411 if (namerec->data.num_ips>1) {
412 namerec->data.wins_flags|=WINS_MHOMED;
414 namerec->data.wins_flags|=WINS_UNIQUE;
418 /* the node type are the same bits */
419 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
421 /* the static bit is elsewhere */
422 if (namerec->data.death_time == PERMANENT_TTL) {
423 namerec->data.wins_flags|=WINS_STATIC;
426 /* and add the given bits */
427 namerec->data.wins_flags|=flags;
429 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: %d, flags: 0x%x, winsflags: 0x%x\n",
430 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
433 /****************************************************************************
434 Return the general ID value and increase it if requested.
435 *****************************************************************************/
437 static void get_global_id_and_update(uint64_t *current_id, bool update)
440 * it's kept as a static here, to prevent people from messing
441 * with the value directly
444 static uint64_t general_id = 1;
446 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
448 *current_id = general_id;
455 /****************************************************************************
456 Possibly call the WINS hook external program when a WINS change is made.
457 Also stores the changed record back in the wins_tdb.
458 *****************************************************************************/
460 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
462 char *command = NULL;
463 char *cmd = lp_wins_hook();
466 TALLOC_CTX *ctx = talloc_tos();
468 wins_store_changed_namerec(namerec);
474 for (p=namerec->name.name; *p; p++) {
475 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
476 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
481 /* Use the name without the nametype (and scope) appended */
483 namestr = nmb_namestr(&namerec->name);
484 if ((p = strchr(namestr, '<'))) {
488 command = talloc_asprintf(ctx,
493 namerec->name.name_type,
499 for (i=0;i<namerec->data.num_ips;i++) {
500 command = talloc_asprintf_append(command,
502 inet_ntoa(namerec->data.ip[i]));
508 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
509 smbrun(command, NULL);
510 TALLOC_FREE(command);
513 /****************************************************************************
514 Determine if this packet should be allocated to the WINS server.
515 *****************************************************************************/
517 bool packet_is_for_wins_server(struct packet_struct *packet)
519 struct nmb_packet *nmb = &packet->packet.nmb;
521 /* Only unicast packets go to a WINS server. */
522 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
523 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
527 /* Check for node status requests. */
528 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
532 switch(nmb->header.opcode) {
534 * A WINS server issues WACKS, not receives them.
536 case NMB_WACK_OPCODE:
537 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
540 * A WINS server only processes registration and
541 * release requests, not responses.
543 case NMB_NAME_REG_OPCODE:
544 case NMB_NAME_MULTIHOMED_REG_OPCODE:
545 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
546 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
547 if(nmb->header.response) {
548 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
553 case NMB_NAME_RELEASE_OPCODE:
554 if(nmb->header.response) {
555 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
561 * Only process unicast name queries with rd = 1.
563 case NMB_NAME_QUERY_OPCODE:
564 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
565 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
574 /****************************************************************************
575 Utility function to decide what ttl to give a register/refresh request.
576 *****************************************************************************/
578 static int get_ttl_from_packet(struct nmb_packet *nmb)
580 int ttl = nmb->additional->ttl;
582 if (ttl < lp_min_wins_ttl()) {
583 ttl = lp_min_wins_ttl();
586 if (ttl > lp_max_wins_ttl()) {
587 ttl = lp_max_wins_ttl();
593 /****************************************************************************
594 Load or create the WINS database.
595 *****************************************************************************/
597 bool initialise_wins(void)
599 time_t time_now = time(NULL);
603 if(!lp_we_are_a_wins_server()) {
607 /* Open the wins.tdb. */
608 wins_tdb = tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
609 O_CREAT|O_RDWR, 0600);
611 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
616 tdb_store_int32(wins_tdb, "WINSDB_VERSION", WINSDB_VERSION);
618 add_samba_names_to_subnet(wins_server_subnet);
620 if((fp = x_fopen(state_path(WINS_LIST),O_RDONLY,0)) == NULL) {
621 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
622 WINS_LIST, strerror(errno) ));
626 while (!x_feof(fp)) {
627 char *name_str = NULL;
629 char *ttl_str = NULL, *nb_flags_str = NULL;
630 unsigned int num_ips;
632 struct in_addr *ip_list = NULL;
643 TALLOC_CTX *frame = NULL;
645 /* Read a line from the wins.dat file. Strips whitespace
646 from the beginning and end of the line. */
647 if (!fgets_slash(line,sizeof(line),fp)) {
655 if (strncmp(line,"VERSION ", 8) == 0) {
656 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
657 version != WINS_VERSION) {
658 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
668 * Now we handle multiple IP addresses per name we need
669 * to iterate over the line twice. The first time to
670 * determine how many IP addresses there are, the second
671 * time to actually parse them into the ip_list array.
674 frame = talloc_stackframe();
675 if (!next_token_talloc(frame,&ptr,&name_str,NULL)) {
676 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
681 if (!next_token_talloc(frame,&ptr,&ttl_str,NULL)) {
682 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
688 * Determine the number of IP addresses per line.
692 got_token = next_token_talloc(frame,&ptr,&ip_str,NULL);
695 if(got_token && strchr(ip_str, '.')) {
699 } while(got_token && was_ip);
702 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
708 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
713 /* Allocate the space for the ip_list. */
714 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
715 DEBUG(0,("initialise_wins: Malloc fail !\n"));
721 /* Reset and re-parse the line. */
723 next_token_talloc(frame,&ptr,&name_str,NULL);
724 next_token_talloc(frame,&ptr,&ttl_str,NULL);
725 for(i = 0; i < num_ips; i++) {
726 next_token_talloc(frame,&ptr, &ip_str, NULL);
727 ip_list[i] = interpret_addr2(ip_str);
729 next_token_talloc(frame,&ptr,&nb_flags_str,NULL);
732 * Deal with SELF or REGISTER name encoding. Default is REGISTER
733 * for compatibility with old nmbds.
736 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
737 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
743 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
744 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
747 /* Netbios name. # divides the name from the type (hex): netbios#xx */
750 if((p = strchr(name,'#')) != NULL) {
752 sscanf(p+1,"%x",&type);
755 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
756 sscanf(nb_flags_str,"%x",&nb_flags);
757 sscanf(ttl_str,"%d",&ttl);
759 /* add all entries that have 60 seconds or more to live */
760 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
761 if(ttl != PERMANENT_TTL) {
765 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
766 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
768 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
769 ttl, REGISTER_NAME, num_ips, ip_list );
771 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
772 "%s#%02x ttl = %d first IP %s flags = %2x\n",
773 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
784 /****************************************************************************
785 Send a WINS WACK (Wait ACKnowledgement) response.
786 **************************************************************************/
788 static void send_wins_wack_response(int ttl, struct packet_struct *p)
790 struct nmb_packet *nmb = &p->packet.nmb;
791 unsigned char rdata[2];
793 rdata[0] = rdata[1] = 0;
795 /* Taken from nmblib.c - we need to send back almost
796 identical bytes from the requesting packet header. */
798 rdata[0] = (nmb->header.opcode & 0xF) << 3;
799 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
802 if (nmb->header.nm_flags.trunc) {
805 if (nmb->header.nm_flags.recursion_desired) {
808 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
811 if (nmb->header.nm_flags.bcast) {
815 reply_netbios_packet(p, /* Packet to reply to. */
816 0, /* Result code. */
817 NMB_WAIT_ACK, /* nmbd type code. */
818 NMB_WACK_OPCODE, /* opcode. */
820 (char *)rdata, /* data to send. */
821 2); /* data length. */
824 /****************************************************************************
825 Send a WINS name registration response.
826 **************************************************************************/
828 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
830 struct nmb_packet *nmb = &p->packet.nmb;
833 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
835 reply_netbios_packet(p, /* Packet to reply to. */
836 rcode, /* Result code. */
837 WINS_REG, /* nmbd type code. */
838 NMB_NAME_REG_OPCODE, /* opcode. */
840 rdata, /* data to send. */
841 6); /* data length. */
844 /***********************************************************************
845 Deal with a name refresh request to a WINS server.
846 ************************************************************************/
848 void wins_process_name_refresh_request( struct subnet_record *subrec,
849 struct packet_struct *p )
851 struct nmb_packet *nmb = &p->packet.nmb;
852 struct nmb_name *question = &nmb->question.question_name;
853 bool bcast = nmb->header.nm_flags.bcast;
854 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
855 bool group = (nb_flags & NB_GROUP) ? True : False;
856 struct name_record *namerec = NULL;
857 int ttl = get_ttl_from_packet(nmb);
858 struct in_addr from_ip;
859 struct in_addr our_fake_ip;
861 our_fake_ip = interpret_addr2("0.0.0.0");
862 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
866 * We should only get unicast name refresh packets here.
867 * Anyone trying to refresh broadcast should not be going
868 * to a WINS server. Log an error here.
870 if( DEBUGLVL( 0 ) ) {
871 dbgtext( "wins_process_name_refresh_request: " );
872 dbgtext( "Broadcast name refresh request received " );
873 dbgtext( "for name %s ", nmb_namestr(question) );
874 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
875 dbgtext( "on subnet %s. ", subrec->subnet_name );
876 dbgtext( "Error - Broadcasts should not be sent " );
877 dbgtext( "to a WINS server\n" );
882 if( DEBUGLVL( 3 ) ) {
883 dbgtext( "wins_process_name_refresh_request: " );
884 dbgtext( "Name refresh for name %s IP %s\n",
885 nmb_namestr(question), inet_ntoa(from_ip) );
889 * See if the name already exists.
890 * If not, handle it as a name registration and return.
892 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
895 * If this is a refresh request and the name doesn't exist then
896 * treat it like a registration request. This allows us to recover
897 * from errors (tridge)
899 if(namerec == NULL) {
900 if( DEBUGLVL( 3 ) ) {
901 dbgtext( "wins_process_name_refresh_request: " );
902 dbgtext( "Name refresh for name %s ",
903 nmb_namestr( question ) );
904 dbgtext( "and the name does not exist. Treating " );
905 dbgtext( "as registration.\n" );
907 wins_process_name_registration_request(subrec,p);
912 * if the name is present but not active, simply remove it
913 * and treat the refresh request as a registration & return.
915 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
916 if( DEBUGLVL( 5 ) ) {
917 dbgtext( "wins_process_name_refresh_request: " );
918 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
919 dbgtext( "was not active - removing it.\n" );
921 remove_name_from_namelist( subrec, namerec );
923 wins_process_name_registration_request( subrec, p );
928 * Check that the group bits for the refreshing name and the
929 * name in our database match. If not, refuse the refresh.
930 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
932 if( (namerec != NULL) &&
933 ( (group && !NAME_GROUP(namerec))
934 || (!group && NAME_GROUP(namerec)) ) ) {
935 if( DEBUGLVL( 3 ) ) {
936 dbgtext( "wins_process_name_refresh_request: " );
937 dbgtext( "Name %s ", nmb_namestr(question) );
938 dbgtext( "group bit = %s does not match ",
939 group ? "True" : "False" );
940 dbgtext( "group bit in WINS for this name.\n" );
942 send_wins_name_registration_response(RFS_ERR, 0, p);
947 * For a unique name check that the person refreshing the name is
948 * one of the registered IP addresses. If not - fail the refresh.
949 * Do the same for group names with a type of 0x1c.
950 * Just return success for unique 0x1d refreshes. For normal group
951 * names update the ttl and return success.
953 if( (!group || (group && (question->name_type == 0x1c)))
954 && find_ip_in_name_record(namerec, from_ip) ) {
958 update_name_ttl(namerec, ttl);
961 * if the record is a replica:
962 * we take ownership and update the version ID.
964 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
965 update_wins_owner(namerec, our_fake_ip);
966 get_global_id_and_update(&namerec->data.id, True);
969 send_wins_name_registration_response(0, ttl, p);
970 wins_hook("refresh", namerec, ttl);
972 } else if((group && (question->name_type == 0x1c))) {
974 * Added by crh for bug #1079.
975 * Fix from Bert Driehuis
977 if( DEBUGLVL( 3 ) ) {
978 dbgtext( "wins_process_name_refresh_request: " );
979 dbgtext( "Name refresh for name %s, ",
980 nmb_namestr(question) );
981 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
982 dbgtext( "is not yet associated with " );
983 dbgtext( "that name. Treating as registration.\n" );
985 wins_process_name_registration_request(subrec,p);
989 * Normal groups are all registered with an IP address of
990 * 255.255.255.255 so we can't search for the IP address.
992 update_name_ttl(namerec, ttl);
993 wins_hook("refresh", namerec, ttl);
994 send_wins_name_registration_response(0, ttl, p);
996 } else if(!group && (question->name_type == 0x1d)) {
998 * Special name type - just pretend the refresh succeeded.
1000 send_wins_name_registration_response(0, ttl, p);
1006 if( DEBUGLVL( 3 ) ) {
1007 dbgtext( "wins_process_name_refresh_request: " );
1008 dbgtext( "Name refresh for name %s with IP %s ",
1009 nmb_namestr(question), inet_ntoa(from_ip) );
1010 dbgtext( "and is IP is not known to the name.\n" );
1012 send_wins_name_registration_response(RFS_ERR, 0, p);
1017 /***********************************************************************
1018 Deal with a name registration request query success to a client that
1021 We have a locked pointer to the original packet stashed away in the
1022 userdata pointer. The success here is actually a failure as it means
1023 the client we queried wants to keep the name, so we must return
1024 a registration failure to the original requestor.
1025 ************************************************************************/
1027 static void wins_register_query_success(struct subnet_record *subrec,
1028 struct userdata_struct *userdata,
1029 struct nmb_name *question_name,
1031 struct res_rec *answers)
1033 struct packet_struct *orig_reg_packet;
1035 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1037 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1038 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
1040 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1042 orig_reg_packet->locked = False;
1043 free_packet(orig_reg_packet);
1046 /***********************************************************************
1047 Deal with a name registration request query failure to a client that
1050 We have a locked pointer to the original packet stashed away in the
1051 userdata pointer. The failure here is actually a success as it means
1052 the client we queried didn't want to keep the name, so we can remove
1053 the old name record and then successfully add the new name.
1054 ************************************************************************/
1056 static void wins_register_query_fail(struct subnet_record *subrec,
1057 struct response_record *rrec,
1058 struct nmb_name *question_name,
1061 struct userdata_struct *userdata = rrec->userdata;
1062 struct packet_struct *orig_reg_packet;
1063 struct name_record *namerec = NULL;
1065 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1068 * We want to just add the name, as we now know the original owner
1069 * didn't want it. But we can't just do that as an arbitary
1070 * amount of time may have taken place between the name query
1071 * request and this timeout/error response. So we check that
1072 * the name still exists and is in the same state - if so
1073 * we remove it and call wins_process_name_registration_request()
1074 * as we know it will do the right thing now.
1077 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1079 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
1080 ip_equal_v4(rrec->packet->ip, *namerec->data.ip)) {
1081 remove_name_from_namelist( subrec, namerec);
1085 if(namerec == NULL) {
1086 wins_process_name_registration_request(subrec, orig_reg_packet);
1088 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1089 "querying for name %s in order to replace it and this reply.\n",
1090 nmb_namestr(question_name) ));
1093 orig_reg_packet->locked = False;
1094 free_packet(orig_reg_packet);
1097 /***********************************************************************
1098 Deal with a name registration request to a WINS server.
1100 Use the following pseudocode :
1105 +--------name exists
1108 | +--- existing name is group
1111 | | +--- add name (return).
1114 | +--- exiting name is unique
1117 | +--- query existing owner (return).
1120 +--------name doesn't exist
1123 +--- add name (return).
1128 +--------name exists
1131 | +--- existing name is group
1134 | | +--- fail add (return).
1137 | +--- exiting name is unique
1140 | +--- query existing owner (return).
1143 +--------name doesn't exist
1146 +--- add name (return).
1148 As can be seen from the above, the two cases may be collapsed onto each
1149 other with the exception of the case where the name already exists and
1150 is a group name. This case we handle with an if statement.
1152 ************************************************************************/
1154 void wins_process_name_registration_request(struct subnet_record *subrec,
1155 struct packet_struct *p)
1158 struct nmb_packet *nmb = &p->packet.nmb;
1159 struct nmb_name *question = &nmb->question.question_name;
1160 bool bcast = nmb->header.nm_flags.bcast;
1161 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1162 int ttl = get_ttl_from_packet(nmb);
1163 struct name_record *namerec = NULL;
1164 struct in_addr from_ip;
1165 bool registering_group_name = (nb_flags & NB_GROUP) ? True : False;
1166 struct in_addr our_fake_ip;
1168 our_fake_ip = interpret_addr2("0.0.0.0");
1169 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1173 * We should only get unicast name registration packets here.
1174 * Anyone trying to register broadcast should not be going to a WINS
1175 * server. Log an error here.
1178 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1179 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1180 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1184 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1185 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1188 * See if the name already exists.
1191 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1194 * if the record exists but NOT in active state,
1197 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1198 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1199 not active - removing it.\n", nmb_namestr(question) ));
1200 remove_name_from_namelist( subrec, namerec );
1205 * Deal with the case where the name found was a dns entry.
1206 * Remove it as we now have a NetBIOS client registering the
1210 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1211 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1212 a dns lookup - removing it.\n", nmb_namestr(question) ));
1213 remove_name_from_namelist( subrec, namerec );
1218 * Reject if the name exists and is not a REGISTER_NAME.
1219 * (ie. Don't allow any static names to be overwritten.
1222 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
1223 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1224 to register name %s. Name already exists in WINS with source type %d.\n",
1225 nmb_namestr(question), namerec->data.source ));
1226 send_wins_name_registration_response(RFS_ERR, 0, p);
1231 * Special policy decisions based on MS documentation.
1232 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1233 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1237 * A group name is always added as the local broadcast address, except
1238 * for group names ending in 0x1c.
1239 * Group names with type 0x1c are registered with individual IP addresses.
1242 if(registering_group_name && (question->name_type != 0x1c)) {
1243 from_ip = interpret_addr2("255.255.255.255");
1247 * Ignore all attempts to register a unique 0x1d name, although return success.
1250 if(!registering_group_name && (question->name_type == 0x1d)) {
1251 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1252 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
1253 send_wins_name_registration_response(0, ttl, p);
1258 * Next two cases are the 'if statement' mentioned above.
1261 if((namerec != NULL) && NAME_GROUP(namerec)) {
1262 if(registering_group_name) {
1264 * If we are adding a group name, the name exists and is also a group entry just add this
1265 * IP address to it and update the ttl.
1268 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1269 inet_ntoa(from_ip), nmb_namestr(question) ));
1272 * Check the ip address is not already in the group.
1275 if(!find_ip_in_name_record(namerec, from_ip)) {
1277 * Need to emulate the behaviour of Windows, as
1279 * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1280 * (is there an MS reference for this
1281 * somewhere?) because if the 1c list gets over
1282 * 86 entries, the reply packet is too big
1283 * (rdata>576 bytes) so no reply is sent.
1285 * Keep only the "latest" 25 records, while
1286 * ensuring that the PDC (0x1b) is never removed
1287 * We do this by removing the first entry that
1288 * isn't the 1b entry for the same name,
1289 * on the grounds that insertion is at the end
1290 * of the list, so the oldest entries are at
1294 while(namerec->data.num_ips>=25) {
1295 struct name_record *name1brec = NULL;
1297 /* We only do this for 1c types. */
1298 if (namerec->name.name_type != 0x1c) {
1301 DEBUG(3,("wins_process_name_registration_request: "
1302 "More than 25 IPs already in "
1303 "the list. Looking for a 1b "
1306 /* Ensure we have all the active 1b
1307 * names on the list. */
1308 wins_delete_all_1b_in_memory_records();
1309 fetch_all_active_wins_1b_names();
1311 /* Per the above, find the 1b record,
1312 and then remove the first IP that isn't the same */
1313 for(name1brec = subrec->namelist;
1315 name1brec = name1brec->next ) {
1316 if( WINS_STATE_ACTIVE(name1brec) &&
1317 name1brec->name.name_type == 0x1b) {
1318 DEBUG(3,("wins_process_name_registration_request: "
1319 "Found the #1b record "
1321 inet_ntoa(name1brec->data.ip[0])));
1326 DEBUG(3,("wins_process_name_registration_request: "
1327 "Didn't find a #1b name record. "
1328 "Removing the first available "
1330 inet_ntoa(namerec->data.ip[0])));
1331 remove_ip_from_name_record(namerec, namerec->data.ip[0]);
1332 wins_hook("delete", namerec, 0);
1335 for(i=0; i<namerec->data.num_ips; i++) {
1336 /* The name1brec should only have
1337 * the single IP address in it,
1338 * so we only check against the first one*/
1339 if(!ip_equal_v4( namerec->data.ip[i], name1brec->data.ip[0])) {
1340 /* The i'th entry isn't the 1b address; delete it */
1341 DEBUG(3,("wins_process_name_registration_request: "
1342 "Entry at %d is not the #1b address. "
1343 "About to remove it\n",
1345 remove_ip_from_name_record(namerec, namerec->data.ip[i]);
1346 wins_hook("delete", namerec, 0);
1352 /* The list is guaranteed to be < 25 entries now
1353 * - safe to add a new one */
1354 add_ip_to_name_record(namerec, from_ip);
1355 /* we need to update the record for replication */
1356 get_global_id_and_update(&namerec->data.id, True);
1359 * if the record is a replica, we must change
1360 * the wins owner to us to make the replication updates
1361 * it on the other wins servers.
1362 * And when the partner will receive this record,
1363 * it will update its own record.
1366 update_wins_owner(namerec, our_fake_ip);
1368 update_name_ttl(namerec, ttl);
1369 wins_hook("refresh", namerec, ttl);
1370 send_wins_name_registration_response(0, ttl, p);
1375 * If we are adding a unique name, the name exists in the WINS db
1376 * and is a group name then reject the registration.
1378 * explanation: groups have a higher priority than unique names.
1381 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1382 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1383 send_wins_name_registration_response(RFS_ERR, 0, p);
1389 * From here on down we know that if the name exists in the WINS db it is
1390 * a unique name, not a group name.
1394 * If the name exists and is one of our names then check the
1395 * registering IP address. If it's not one of ours then automatically
1396 * reject without doing the query - we know we will reject it.
1399 if ( namerec != NULL ) {
1400 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1401 if( is_myname(name) ) {
1402 if(!ismyip_v4(from_ip)) {
1403 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1404 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1405 send_wins_name_registration_response(RFS_ERR, 0, p);
1409 * It's one of our names and one of our IP's - update the ttl.
1411 update_name_ttl(namerec, ttl);
1412 wins_hook("refresh", namerec, ttl);
1413 send_wins_name_registration_response(0, ttl, p);
1422 * If the name exists and it is a unique registration and the registering IP
1423 * is the same as the (single) already registered IP then just update the ttl.
1425 * But not if the record is an active replica. IF it's a replica, it means it can be
1426 * the same client which has moved and not yet expired. So we don't update
1427 * the ttl in this case and go beyond to do a WACK and query the old client
1430 if( !registering_group_name
1431 && (namerec != NULL)
1432 && (namerec->data.num_ips == 1)
1433 && ip_equal_v4( namerec->data.ip[0], from_ip )
1434 && ip_equal_v4(namerec->data.wins_ip, our_fake_ip) ) {
1435 update_name_ttl( namerec, ttl );
1436 wins_hook("refresh", namerec, ttl);
1437 send_wins_name_registration_response( 0, ttl, p );
1442 * Finally if the name exists do a query to the registering machine
1443 * to see if they still claim to have the name.
1446 if( namerec != NULL ) {
1447 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1448 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1451 * First send a WACK to the registering machine.
1454 send_wins_wack_response(60, p);
1457 * When the reply comes back we need the original packet.
1458 * Lock this so it won't be freed and then put it into
1459 * the userdata structure.
1464 userdata = (struct userdata_struct *)ud;
1466 userdata->copy_fn = NULL;
1467 userdata->free_fn = NULL;
1468 userdata->userdata_len = sizeof(struct packet_struct *);
1469 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1472 * Use the new call to send a query directly to an IP address.
1473 * This sends the query directly to the IP address, and ensures
1474 * the recursion desired flag is not set (you were right Luke :-).
1475 * This function should *only* be called from the WINS server
1479 pull_ascii_nstring(name, sizeof(name), question->name);
1480 query_name_from_wins_server( *namerec->data.ip,
1482 question->name_type,
1483 wins_register_query_success,
1484 wins_register_query_fail,
1490 * Name did not exist - add it.
1493 pull_ascii_nstring(name, sizeof(name), question->name);
1494 add_name_to_subnet( subrec, name, question->name_type,
1495 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1497 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1498 get_global_id_and_update(&namerec->data.id, True);
1499 update_wins_owner(namerec, our_fake_ip);
1500 update_wins_flag(namerec, WINS_ACTIVE);
1501 wins_hook("add", namerec, ttl);
1504 send_wins_name_registration_response(0, ttl, p);
1507 /***********************************************************************
1508 Deal with a mutihomed name query success to the machine that
1509 requested the multihomed name registration.
1511 We have a locked pointer to the original packet stashed away in the
1513 ************************************************************************/
1515 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1516 struct userdata_struct *userdata,
1517 struct nmb_name *question_name,
1519 struct res_rec *answers)
1521 struct packet_struct *orig_reg_packet;
1522 struct nmb_packet *nmb;
1523 struct name_record *namerec = NULL;
1524 struct in_addr from_ip;
1526 struct in_addr our_fake_ip;
1528 our_fake_ip = interpret_addr2("0.0.0.0");
1529 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1531 nmb = &orig_reg_packet->packet.nmb;
1533 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1534 ttl = get_ttl_from_packet(nmb);
1537 * We want to just add the new IP, as we now know the requesting
1538 * machine claims to own it. But we can't just do that as an arbitary
1539 * amount of time may have taken place between the name query
1540 * request and this response. So we check that
1541 * the name still exists and is in the same state - if so
1542 * we just add the extra IP and update the ttl.
1545 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1547 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1548 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1549 a subsequent IP address.\n", nmb_namestr(question_name) ));
1550 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1552 orig_reg_packet->locked = False;
1553 free_packet(orig_reg_packet);
1558 if(!find_ip_in_name_record(namerec, from_ip)) {
1559 add_ip_to_name_record(namerec, from_ip);
1562 get_global_id_and_update(&namerec->data.id, True);
1563 update_wins_owner(namerec, our_fake_ip);
1564 update_wins_flag(namerec, WINS_ACTIVE);
1565 update_name_ttl(namerec, ttl);
1566 wins_hook("add", namerec, ttl);
1567 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1569 orig_reg_packet->locked = False;
1570 free_packet(orig_reg_packet);
1573 /***********************************************************************
1574 Deal with a name registration request query failure to a client that
1577 We have a locked pointer to the original packet stashed away in the
1579 ************************************************************************/
1581 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1582 struct response_record *rrec,
1583 struct nmb_name *question_name,
1586 struct userdata_struct *userdata = rrec->userdata;
1587 struct packet_struct *orig_reg_packet;
1589 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1591 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1592 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1593 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1595 orig_reg_packet->locked = False;
1596 free_packet(orig_reg_packet);
1600 /***********************************************************************
1601 Deal with a multihomed name registration request to a WINS server.
1602 These cannot be group name registrations.
1603 ***********************************************************************/
1605 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1606 struct packet_struct *p)
1608 struct nmb_packet *nmb = &p->packet.nmb;
1609 struct nmb_name *question = &nmb->question.question_name;
1610 bool bcast = nmb->header.nm_flags.bcast;
1611 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1612 int ttl = get_ttl_from_packet(nmb);
1613 struct name_record *namerec = NULL;
1614 struct in_addr from_ip;
1615 bool group = (nb_flags & NB_GROUP) ? True : False;
1616 struct in_addr our_fake_ip;
1619 our_fake_ip = interpret_addr2("0.0.0.0");
1620 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1624 * We should only get unicast name registration packets here.
1625 * Anyone trying to register broadcast should not be going to a WINS
1626 * server. Log an error here.
1629 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1630 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1631 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1636 * Only unique names should be registered multihomed.
1640 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1641 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1642 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1646 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1647 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1650 * Deal with policy regarding 0x1d names.
1653 if(question->name_type == 0x1d) {
1654 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1655 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1656 send_wins_name_registration_response(0, ttl, p);
1661 * See if the name already exists.
1664 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1667 * if the record exists but NOT in active state,
1671 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1672 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1673 remove_name_from_namelist(subrec, namerec);
1678 * Deal with the case where the name found was a dns entry.
1679 * Remove it as we now have a NetBIOS client registering the
1683 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1684 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1685 - removing it.\n", nmb_namestr(question) ));
1686 remove_name_from_namelist( subrec, namerec);
1691 * Reject if the name exists and is not a REGISTER_NAME.
1692 * (ie. Don't allow any static names to be overwritten.
1695 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1696 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1697 to register name %s. Name already exists in WINS with source type %d.\n",
1698 nmb_namestr(question), namerec->data.source ));
1699 send_wins_name_registration_response(RFS_ERR, 0, p);
1704 * Reject if the name exists and is a GROUP name and is active.
1707 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1708 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1709 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1710 send_wins_name_registration_response(RFS_ERR, 0, p);
1715 * From here on down we know that if the name exists in the WINS db it is
1716 * a unique name, not a group name.
1720 * If the name exists and is one of our names then check the
1721 * registering IP address. If it's not one of ours then automatically
1722 * reject without doing the query - we know we will reject it.
1725 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1726 if(!ismyip_v4(from_ip)) {
1727 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1728 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1729 send_wins_name_registration_response(RFS_ERR, 0, p);
1733 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1734 * update the ttl. Update the version ID to force replication.
1736 update_name_ttl(namerec, ttl);
1738 if(!find_ip_in_name_record(namerec, from_ip)) {
1739 get_global_id_and_update(&namerec->data.id, True);
1740 update_wins_owner(namerec, our_fake_ip);
1741 update_wins_flag(namerec, WINS_ACTIVE);
1743 add_ip_to_name_record(namerec, from_ip);
1746 wins_hook("refresh", namerec, ttl);
1747 send_wins_name_registration_response(0, ttl, p);
1753 * If the name exists and is active, check if the IP address is already registered
1754 * to that name. If so then update the ttl and reply success.
1757 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1758 update_name_ttl(namerec, ttl);
1761 * If it's a replica, we need to become the wins owner
1762 * to force the replication
1764 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
1765 get_global_id_and_update(&namerec->data.id, True);
1766 update_wins_owner(namerec, our_fake_ip);
1767 update_wins_flag(namerec, WINS_ACTIVE);
1770 wins_hook("refresh", namerec, ttl);
1771 send_wins_name_registration_response(0, ttl, p);
1776 * If the name exists do a query to the owner
1777 * to see if they still want the name.
1780 if(namerec != NULL) {
1781 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1782 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1785 * First send a WACK to the registering machine.
1788 send_wins_wack_response(60, p);
1791 * When the reply comes back we need the original packet.
1792 * Lock this so it won't be freed and then put it into
1793 * the userdata structure.
1798 userdata = (struct userdata_struct *)ud;
1800 userdata->copy_fn = NULL;
1801 userdata->free_fn = NULL;
1802 userdata->userdata_len = sizeof(struct packet_struct *);
1803 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1806 * Use the new call to send a query directly to an IP address.
1807 * This sends the query directly to the IP address, and ensures
1808 * the recursion desired flag is not set (you were right Luke :-).
1809 * This function should *only* be called from the WINS server
1812 * Note that this packet is sent to the current owner of the name,
1813 * not the person who sent the packet
1816 pull_ascii_nstring( qname, sizeof(qname), question->name);
1817 query_name_from_wins_server( namerec->data.ip[0],
1819 question->name_type,
1820 wins_multihomed_register_query_success,
1821 wins_multihomed_register_query_fail,
1828 * Name did not exist - add it.
1831 pull_ascii_nstring( qname, sizeof(qname), question->name);
1832 add_name_to_subnet( subrec, qname, question->name_type,
1833 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1835 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1836 get_global_id_and_update(&namerec->data.id, True);
1837 update_wins_owner(namerec, our_fake_ip);
1838 update_wins_flag(namerec, WINS_ACTIVE);
1839 wins_hook("add", namerec, ttl);
1842 send_wins_name_registration_response(0, ttl, p);
1845 /***********************************************************************
1846 Fetch all *<1b> names from the WINS db and store on the namelist.
1847 ***********************************************************************/
1849 static int fetch_1b_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
1851 struct name_record *namerec = NULL;
1853 if (kbuf.dsize != sizeof(unstring) + 1) {
1857 /* Filter out all non-1b names. */
1858 if (kbuf.dptr[sizeof(unstring)] != 0x1b) {
1862 namerec = wins_record_to_name_record(kbuf, dbuf);
1867 DLIST_ADD(wins_server_subnet->namelist, namerec);
1871 void fetch_all_active_wins_1b_names(void)
1873 tdb_traverse(wins_tdb, fetch_1b_traverse_fn, NULL);
1876 /***********************************************************************
1877 Deal with the special name query for *<1b>.
1878 ***********************************************************************/
1880 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1881 struct packet_struct *p)
1883 struct name_record *namerec = NULL;
1888 * Go through all the ACTIVE names in the WINS db looking for those
1889 * ending in <1b>. Use this to calculate the number of IP
1890 * addresses we need to return.
1895 /* First, clear the in memory list - we're going to re-populate
1896 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1898 wins_delete_all_tmp_in_memory_records();
1900 fetch_all_active_wins_1b_names();
1902 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1903 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1904 num_ips += namerec->data.num_ips;
1910 * There are no 0x1b names registered. Return name query fail.
1912 send_wins_name_query_response(NAM_ERR, p, NULL);
1916 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1917 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1922 * Go through all the names again in the WINS db looking for those
1923 * ending in <1b>. Add their IP addresses into the list we will
1928 for( namerec = subrec->namelist; namerec; namerec = namerec->next ) {
1929 if( WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1931 for(i = 0; i < namerec->data.num_ips; i++) {
1932 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1933 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1940 * Send back the reply containing the IP list.
1943 reply_netbios_packet(p, /* Packet to reply to. */
1944 0, /* Result code. */
1945 WINS_QUERY, /* nmbd type code. */
1946 NMB_NAME_QUERY_OPCODE, /* opcode. */
1947 lp_min_wins_ttl(), /* ttl. */
1948 prdata, /* data to send. */
1949 num_ips*6); /* data length. */
1954 /****************************************************************************
1955 Send a WINS name query response.
1956 **************************************************************************/
1958 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1959 struct name_record *namerec)
1962 char *prdata = rdata;
1963 int reply_data_len = 0;
1967 memset(rdata,'\0',6);
1973 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1975 /* The netbios reply packet data section is limited to 576 bytes. In theory
1976 * this should give us space for 96 addresses, but in practice, 86 appears
1977 * to be the max (don't know why). If we send any more than that,
1978 * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
1979 * overflow. Keep the count to 85 and it will be ok */
1980 ip_count=namerec->data.num_ips;
1985 /* Copy all known ip addresses into the return data. */
1986 /* Optimise for the common case of one IP address so we don't need a malloc. */
1988 if( ip_count == 1 ) {
1991 if((prdata = (char *)SMB_MALLOC( ip_count * 6 )) == NULL) {
1992 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1997 for(i = 0; i < ip_count; i++) {
1998 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1999 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
2002 sort_query_replies(prdata, i, p->ip);
2003 reply_data_len = ip_count * 6;
2006 reply_netbios_packet(p, /* Packet to reply to. */
2007 rcode, /* Result code. */
2008 WINS_QUERY, /* nmbd type code. */
2009 NMB_NAME_QUERY_OPCODE, /* opcode. */
2011 prdata, /* data to send. */
2012 reply_data_len); /* data length. */
2014 if(prdata != rdata) {
2019 /***********************************************************************
2020 Deal with a name query.
2021 ***********************************************************************/
2023 void wins_process_name_query_request(struct subnet_record *subrec,
2024 struct packet_struct *p)
2026 struct nmb_packet *nmb = &p->packet.nmb;
2027 struct nmb_name *question = &nmb->question.question_name;
2028 struct name_record *namerec = NULL;
2031 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
2032 nmb_namestr(question), inet_ntoa(p->ip) ));
2035 * Special name code. If the queried name is *<1b> then search
2036 * the entire WINS database and return a list of all the IP addresses
2037 * registered to any <1b> name. This is to allow domain master browsers
2038 * to discover other domains that may not have a presence on their subnet.
2041 pull_ascii_nstring(qname, sizeof(qname), question->name);
2042 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
2043 process_wins_dmb_query_request( subrec, p);
2047 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2049 if(namerec != NULL) {
2051 * If the name is not anymore in active state then reply not found.
2052 * it's fair even if we keep it in the cache for days.
2054 if (!WINS_STATE_ACTIVE(namerec)) {
2055 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2056 nmb_namestr(question) ));
2057 send_wins_name_query_response(NAM_ERR, p, namerec);
2062 * If it's a DNSFAIL_NAME then reply name not found.
2065 if( namerec->data.source == DNSFAIL_NAME ) {
2066 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2067 nmb_namestr(question) ));
2068 send_wins_name_query_response(NAM_ERR, p, namerec);
2073 * If the name has expired then reply name not found.
2076 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
2077 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2078 nmb_namestr(question) ));
2079 send_wins_name_query_response(NAM_ERR, p, namerec);
2083 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2084 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
2086 send_wins_name_query_response(0, p, namerec);
2091 * Name not found in WINS - try a dns query if it's a 0x20 name.
2094 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
2095 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2096 nmb_namestr(question) ));
2098 queue_dns_query(p, question);
2103 * Name not found - return error.
2106 send_wins_name_query_response(NAM_ERR, p, NULL);
2109 /****************************************************************************
2110 Send a WINS name release response.
2111 **************************************************************************/
2113 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
2115 struct nmb_packet *nmb = &p->packet.nmb;
2118 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
2120 reply_netbios_packet(p, /* Packet to reply to. */
2121 rcode, /* Result code. */
2122 NMB_REL, /* nmbd type code. */
2123 NMB_NAME_RELEASE_OPCODE, /* opcode. */
2125 rdata, /* data to send. */
2126 6); /* data length. */
2129 /***********************************************************************
2130 Deal with a name release.
2131 ***********************************************************************/
2133 void wins_process_name_release_request(struct subnet_record *subrec,
2134 struct packet_struct *p)
2136 struct nmb_packet *nmb = &p->packet.nmb;
2137 struct nmb_name *question = &nmb->question.question_name;
2138 bool bcast = nmb->header.nm_flags.bcast;
2139 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
2140 struct name_record *namerec = NULL;
2141 struct in_addr from_ip;
2142 bool releasing_group_name = (nb_flags & NB_GROUP) ? True : False;
2144 putip((char *)&from_ip,&nmb->additional->rdata[2]);
2148 * We should only get unicast name registration packets here.
2149 * Anyone trying to register broadcast should not be going to a WINS
2150 * server. Log an error here.
2153 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2154 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2155 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
2159 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2160 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
2163 * Deal with policy regarding 0x1d names.
2166 if(!releasing_group_name && (question->name_type == 0x1d)) {
2167 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2168 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
2169 send_wins_name_release_response(0, p);
2174 * See if the name already exists.
2177 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
2179 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
2180 send_wins_name_release_response(NAM_ERR, p);
2185 * Check that the sending machine has permission to release this name.
2186 * If it's a group name not ending in 0x1c then just say yes and let
2187 * the group time out.
2190 if(releasing_group_name && (question->name_type != 0x1c)) {
2191 send_wins_name_release_response(0, p);
2196 * Check that the releasing node is on the list of IP addresses
2197 * for this name. Disallow the release if not.
2200 if(!find_ip_in_name_record(namerec, from_ip)) {
2201 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2202 release name %s as IP %s is not one of the known IP's for this name.\n",
2203 nmb_namestr(question), inet_ntoa(from_ip) ));
2204 send_wins_name_release_response(NAM_ERR, p);
2209 * Check if the record is active. IF it's already released
2210 * or tombstoned, refuse the release.
2213 if (!WINS_STATE_ACTIVE(namerec)) {
2214 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2215 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
2216 send_wins_name_release_response(NAM_ERR, p);
2221 * Check if the record is a 0x1c group
2222 * and has more then one ip
2223 * remove only this address.
2226 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
2227 remove_ip_from_name_record(namerec, from_ip);
2228 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2229 inet_ntoa(from_ip),nmb_namestr(question)));
2230 wins_hook("delete", namerec, 0);
2231 send_wins_name_release_response(0, p);
2236 * Send a release response.
2237 * Flag the name as released and update the ttl
2240 namerec->data.wins_flags |= WINS_RELEASED;
2241 update_name_ttl(namerec, EXTINCTION_INTERVAL);
2243 wins_hook("delete", namerec, 0);
2244 send_wins_name_release_response(0, p);
2247 /*******************************************************************
2248 WINS time dependent processing.
2249 ******************************************************************/
2251 static int wins_processing_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2253 time_t t = *(time_t *)state;
2254 bool store_record = False;
2255 struct name_record *namerec = NULL;
2256 struct in_addr our_fake_ip;
2258 our_fake_ip = interpret_addr2("0.0.0.0");
2259 if (kbuf.dsize != sizeof(unstring) + 1) {
2263 namerec = wins_record_to_name_record(kbuf, dbuf);
2268 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) {
2269 if( namerec->data.source == SELF_NAME ) {
2270 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2271 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
2272 namerec->data.death_time += 300;
2273 store_record = True;
2275 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
2276 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2277 nmb_namestr(&namerec->name)));
2278 remove_name_from_wins_namelist(namerec );
2282 /* handle records, samba is the wins owner */
2283 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2284 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2286 namerec->data.wins_flags&=~WINS_STATE_MASK;
2287 namerec->data.wins_flags|=WINS_RELEASED;
2288 namerec->data.death_time = t + EXTINCTION_INTERVAL;
2289 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2290 nmb_namestr(&namerec->name)));
2291 store_record = True;
2294 namerec->data.wins_flags&=~WINS_STATE_MASK;
2295 namerec->data.wins_flags|=WINS_TOMBSTONED;
2296 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2297 get_global_id_and_update(&namerec->data.id, True);
2298 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2299 nmb_namestr(&namerec->name)));
2300 store_record = True;
2302 case WINS_TOMBSTONED:
2303 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2304 nmb_namestr(&namerec->name)));
2305 remove_name_from_wins_namelist(namerec );
2309 switch (namerec->data.wins_flags & WINS_STATE_MASK) {
2311 /* that's not as MS says it should be */
2312 namerec->data.wins_flags&=~WINS_STATE_MASK;
2313 namerec->data.wins_flags|=WINS_TOMBSTONED;
2314 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
2315 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2316 nmb_namestr(&namerec->name)));
2317 store_record = True;
2319 case WINS_TOMBSTONED:
2320 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2321 nmb_namestr(&namerec->name)));
2322 remove_name_from_wins_namelist(namerec );
2325 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2326 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
2335 wins_store_changed_namerec(namerec);
2338 SAFE_FREE(namerec->data.ip);
2344 /*******************************************************************
2345 Time dependent wins processing.
2346 ******************************************************************/
2348 void initiate_wins_processing(time_t t)
2350 static time_t lasttime = 0;
2355 if (t - lasttime < 20) {
2359 if(!lp_we_are_a_wins_server()) {
2364 tdb_traverse(wins_tdb, wins_processing_traverse_fn, &t);
2366 wins_delete_all_tmp_in_memory_records();
2368 wins_write_database(t, True);
2373 /*******************************************************************
2374 Write out one record.
2375 ******************************************************************/
2377 void wins_write_name_record(struct name_record *namerec, XFILE *fp)
2382 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
2384 if( namerec->data.death_time != PERMANENT_TTL ) {
2387 tm = localtime(&namerec->data.death_time);
2395 nl = strrchr( ts, '\n' );
2399 DEBUGADD(4,("TTL = %s ", ts ));
2401 DEBUGADD(4,("TTL = PERMANENT "));
2404 for (i = 0; i < namerec->data.num_ips; i++) {
2405 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
2407 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
2409 if( namerec->data.source == REGISTER_NAME ) {
2411 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
2412 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
2413 (int)namerec->data.death_time);
2415 for (i = 0; i < namerec->data.num_ips; i++)
2416 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
2417 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
2421 /*******************************************************************
2422 Write out the current WINS database.
2423 ******************************************************************/
2425 static int wins_writedb_traverse_fn(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
2427 struct name_record *namerec = NULL;
2428 XFILE *fp = (XFILE *)state;
2430 if (kbuf.dsize != sizeof(unstring) + 1) {
2434 namerec = wins_record_to_name_record(kbuf, dbuf);
2439 wins_write_name_record(namerec, fp);
2441 SAFE_FREE(namerec->data.ip);
2447 void wins_write_database(time_t t, bool background)
2449 static time_t last_write_time = 0;
2451 char *fnamenew = NULL;
2456 if (!last_write_time) {
2457 last_write_time = t;
2459 if (t - last_write_time < 120) {
2465 if(!lp_we_are_a_wins_server()) {
2469 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2475 if (tdb_reopen(wins_tdb)) {
2476 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2483 if (!(fname = state_path(WINS_LIST))) {
2486 /* This is safe as the 0 length means "don't expand". */
2487 all_string_sub(fname,"//", "/", 0);
2489 if (asprintf(&fnamenew, "%s.%u", fname, (unsigned int)sys_getpid()) < 0) {
2493 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
2494 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
2498 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2500 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
2502 tdb_traverse(wins_tdb, wins_writedb_traverse_fn, fp);
2505 chmod(fnamenew,0644);
2507 rename(fnamenew,fname);
2511 SAFE_FREE(fnamenew);
2520 Until winsrepl is done.
2521 /****************************************************************************
2522 Process a internal Samba message receiving a wins record.
2523 ***************************************************************************/
2525 void nmbd_wins_new_entry(struct messaging_context *msg,
2528 struct server_id server_id,
2531 WINS_RECORD *record;
2532 struct name_record *namerec = NULL;
2533 struct name_record *new_namerec = NULL;
2534 struct nmb_name question;
2535 bool overwrite=False;
2536 struct in_addr our_fake_ip;
2539 our_fake_ip = interpret_addr2("0.0.0.0");
2544 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2545 record=(WINS_RECORD *)buf;
2547 make_nmb_name(&question, record->name, record->type);
2549 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
2551 /* record doesn't exist, add it */
2552 if (namerec == NULL) {
2553 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2554 record->name, record->type, inet_ntoa(record->wins_ip)));
2556 new_namerec=add_name_to_subnet( wins_server_subnet,
2560 EXTINCTION_INTERVAL,
2565 if (new_namerec!=NULL) {
2566 update_wins_owner(new_namerec, record->wins_ip);
2567 update_wins_flag(new_namerec, record->wins_flags);
2568 new_namerec->data.id=record->id;
2570 wins_server_subnet->namelist_changed = True;
2574 /* check if we have a conflict */
2575 if (namerec != NULL) {
2576 /* both records are UNIQUE */
2577 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
2579 /* the database record is a replica */
2580 if (!ip_equal_v4(namerec->data.wins_ip, our_fake_ip)) {
2581 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
2582 if (ip_equal_v4(namerec->data.wins_ip, record->wins_ip))
2587 /* we are the wins owner of the database record */
2588 /* the 2 records have the same IP address */
2589 if (ip_equal_v4(namerec->data.ip[0], record->ip[0])) {
2590 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
2591 get_global_id_and_update(&namerec->data.id, True);
2596 /* the 2 records have different IP address */
2597 if (namerec->data.wins_flags&WINS_ACTIVE) {
2598 if (record->wins_flags&WINS_TOMBSTONED)
2599 get_global_id_and_update(&namerec->data.id, True);
2600 if (record->wins_flags&WINS_ACTIVE)
2601 /* send conflict challenge to the replica node */
2610 /* the replica is a standard group */
2611 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
2612 /* if the database record is unique and active force a name release */
2613 if (namerec->data.wins_flags&WINS_UNIQUE)
2614 /* send a release name to the unique node */
2620 /* the replica is a special group */
2621 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2622 if (namerec->data.wins_flags&WINS_ACTIVE) {
2623 for (i=0; i<record->num_ips; i++)
2624 if(!find_ip_in_name_record(namerec, record->ip[i]))
2625 add_ip_to_name_record(namerec, record->ip[i]);
2631 /* the replica is a multihomed host */
2633 /* I'm giving up on multi homed. Too much complex to understand */
2635 if (record->wins_flags&WINS_MHOMED) {
2636 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2637 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2641 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2644 if (ip_equal_v4(namerec->data.wins_ip, our_fake_ip))
2645 if (namerec->data.wins_flags&WINS_UNIQUE)
2646 get_global_id_and_update(&namerec->data.id, True);
2650 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2651 if (namerec->data.wins_flags&WINS_UNIQUE ||
2652 namerec->data.wins_flags&WINS_MHOMED)
2653 if (ip_equal_v4(record->wins_ip, namerec->data.wins_ip))
2658 if (overwrite == False)
2659 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2660 record->name, record->type, inet_ntoa(record->wins_ip)));
2662 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2663 record->name, record->type, inet_ntoa(record->wins_ip)));
2665 /* remove the old record and add a new one */
2666 remove_name_from_namelist( wins_server_subnet, namerec );
2667 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2668 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2669 if (new_namerec!=NULL) {
2670 update_wins_owner(new_namerec, record->wins_ip);
2671 update_wins_flag(new_namerec, record->wins_flags);
2672 new_namerec->data.id=record->id;
2674 wins_server_subnet->namelist_changed = True;
2677 wins_server_subnet->namelist_changed = True;