2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Converted to store WINS data in a tdb. Dec 2005. JRA.
26 #define WINS_LIST "wins.dat"
27 #define WINS_VERSION 1
28 #define WINSDB_VERSION 1
30 /****************************************************************************
31 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
32 name (65 bytes with the last byte being the name type).
33 *****************************************************************************/
35 TDB_CONTEXT
*wins_tdb
;
37 /****************************************************************************
38 Delete all the temporary name records on the in-memory linked list.
39 *****************************************************************************/
41 static void wins_delete_all_tmp_in_memory_records(void)
43 struct name_record
*nr
= NULL
;
44 struct name_record
*nrnext
= NULL
;
46 /* Delete all temporary name records on the wins subnet linked list. */
47 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nrnext
) {
49 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
50 SAFE_FREE(nr
->data
.ip
);
55 /****************************************************************************
56 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
57 *****************************************************************************/
59 static struct name_record
*wins_record_to_name_record(TDB_DATA key
, TDB_DATA data
)
61 struct name_record
*namerec
= NULL
;
64 uint32 death_time
, refresh_time
;
65 uint32 id_low
, id_high
;
72 if (data
.dptr
== NULL
|| data
.dsize
== 0) {
76 /* Min size is "wbddddddd" + 1 ip address (4). */
77 if (data
.dsize
< 2 + 1 + (7*4) + 4) {
81 len
= tdb_unpack(data
.dptr
, data
.dsize
,
93 namerec
= SMB_MALLOC_P(struct name_record
);
97 ZERO_STRUCTP(namerec
);
99 namerec
->data
.ip
= SMB_MALLOC_ARRAY(struct in_addr
, num_ips
);
100 if (!namerec
->data
.ip
) {
105 namerec
->subnet
= wins_server_subnet
;
106 push_ascii_nstring(namerec
->name
.name
, key
.dptr
);
107 namerec
->name
.name_type
= key
.dptr
[sizeof(unstring
)];
109 push_ascii(namerec
->name
.scope
, global_scope(), 64, STR_TERMINATE
);
111 /* We're using a byte-by-byte compare, so we must be sure that
112 * unused space doesn't have garbage in it.
115 for( i
= strlen( namerec
->name
.name
); i
< sizeof( namerec
->name
.name
); i
++ ) {
116 namerec
->name
.name
[i
] = '\0';
118 for( i
= strlen( namerec
->name
.scope
); i
< sizeof( namerec
->name
.scope
); i
++ ) {
119 namerec
->name
.scope
[i
] = '\0';
122 namerec
->data
.nb_flags
= nb_flags
;
123 namerec
->data
.source
= (enum name_source
)nr_src
;
124 namerec
->data
.death_time
= (time_t)death_time
;
125 namerec
->data
.refresh_time
= (time_t)refresh_time
;
126 namerec
->data
.id
= id_low
;
127 #if defined(HAVE_LONGLONG)
128 namerec
->data
.id
|= ((SMB_BIG_UINT
)id_high
<< 32);
130 namerec
->data
.wins_ip
.s_addr
= saddr
;
131 namerec
->data
.wins_flags
= wins_flags
,
132 namerec
->data
.num_ips
= num_ips
;
134 for (i
= 0; i
< num_ips
; i
++) {
135 namerec
->data
.ip
[i
].s_addr
= IVAL(data
.dptr
, len
+ (i
*4));
141 /****************************************************************************
142 Convert a struct name_record to a wins.tdb record. Ignore the scope.
143 *****************************************************************************/
145 static TDB_DATA
name_record_to_wins_record(const struct name_record
*namerec
)
150 uint32 id_low
= (namerec
->data
.id
& 0xFFFFFFFF);
151 #if defined(HAVE_LONGLONG)
152 uint32 id_high
= (namerec
->data
.id
>> 32) & 0xFFFFFFFF;
159 len
= (2 + 1 + (7*4)); /* "wbddddddd" */
160 len
+= (namerec
->data
.num_ips
* 4);
162 data
.dptr
= (char *)SMB_MALLOC(len
);
168 len
= tdb_pack(data
.dptr
, data
.dsize
, "wbddddddd",
169 namerec
->data
.nb_flags
,
170 (unsigned char)namerec
->data
.source
,
171 (uint32
)namerec
->data
.death_time
,
172 (uint32
)namerec
->data
.refresh_time
,
175 (uint32
)namerec
->data
.wins_ip
.s_addr
,
176 (uint32
)namerec
->data
.wins_flags
,
177 (uint32
)namerec
->data
.num_ips
);
179 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
180 SIVAL(data
.dptr
, len
+ (i
*4), namerec
->data
.ip
[i
].s_addr
);
186 /****************************************************************************
187 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
188 *****************************************************************************/
190 static TDB_DATA
name_to_key(const struct nmb_name
*nmbname
)
192 static char keydata
[sizeof(unstring
) + 1];
195 memset(keydata
, '\0', sizeof(keydata
));
197 pull_ascii_nstring(keydata
, sizeof(unstring
), nmbname
->name
);
199 keydata
[sizeof(unstring
)] = nmbname
->name_type
;
201 key
.dsize
= sizeof(keydata
);
206 /****************************************************************************
207 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
208 on the linked list. We will free this later in XXXX().
209 *****************************************************************************/
211 struct name_record
*find_name_on_wins_subnet(const struct nmb_name
*nmbname
, BOOL self_only
)
214 struct name_record
*nr
= NULL
;
215 struct name_record
*namerec
= NULL
;
221 key
= name_to_key(nmbname
);
222 data
= tdb_fetch(wins_tdb
, key
);
224 if (data
.dsize
== 0) {
228 namerec
= wins_record_to_name_record(key
, data
);
230 /* done with the this */
232 SAFE_FREE( data
.dptr
);
238 /* Self names only - these include permanent names. */
239 if( self_only
&& (namerec
->data
.source
!= SELF_NAME
) && (namerec
->data
.source
!= PERMANENT_NAME
) ) {
240 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname
) ) );
241 SAFE_FREE(namerec
->data
.ip
);
246 /* Search for this name record on the list. Replace it if found. */
248 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nr
->next
) {
249 if (memcmp(nmbname
->name
, nr
->name
.name
, 16) == 0) {
251 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
252 SAFE_FREE(nr
->data
.ip
);
258 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
262 /****************************************************************************
263 Overwrite or add a given name in the wins.tdb.
264 *****************************************************************************/
266 static BOOL
store_or_replace_wins_namerec(const struct name_record
*namerec
, int tdb_flag
)
275 key
= name_to_key(&namerec
->name
);
276 data
= name_record_to_wins_record(namerec
);
278 if (data
.dptr
== NULL
) {
282 ret
= tdb_store(wins_tdb
, key
, data
, tdb_flag
);
284 SAFE_FREE(data
.dptr
);
285 return (ret
== 0) ? True
: False
;
288 /****************************************************************************
289 Overwrite a given name in the wins.tdb.
290 *****************************************************************************/
292 BOOL
wins_store_changed_namerec(const struct name_record
*namerec
)
294 return store_or_replace_wins_namerec(namerec
, TDB_REPLACE
);
297 /****************************************************************************
298 Primary interface into creating and overwriting records in the wins.tdb.
299 *****************************************************************************/
301 BOOL
add_name_to_wins_subnet(const struct name_record
*namerec
)
303 return store_or_replace_wins_namerec(namerec
, TDB_INSERT
);
306 /****************************************************************************
307 Delete a given name in the tdb and remove the temporary malloc'ed data struct
309 *****************************************************************************/
311 BOOL
remove_name_from_wins_namelist(struct name_record
*namerec
)
320 key
= name_to_key(&namerec
->name
);
321 ret
= tdb_delete(wins_tdb
, key
);
323 DLIST_REMOVE(wins_server_subnet
->namelist
, namerec
);
325 /* namerec must be freed by the caller */
327 return (ret
== 0) ? True
: False
;
330 /****************************************************************************
331 Dump out the complete namelist.
332 *****************************************************************************/
334 static int traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
336 struct name_record
*namerec
= NULL
;
337 XFILE
*fp
= (XFILE
*)state
;
339 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
343 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
348 dump_name_record(namerec
, fp
);
350 SAFE_FREE(namerec
->data
.ip
);
355 void dump_wins_subnet_namelist(XFILE
*fp
)
357 tdb_traverse(wins_tdb
, traverse_fn
, (void *)fp
);
360 /****************************************************************************
361 Change the wins owner address in the record.
362 *****************************************************************************/
364 static void update_wins_owner(struct name_record
*namerec
, struct in_addr wins_ip
)
366 namerec
->data
.wins_ip
=wins_ip
;
369 /****************************************************************************
370 Create the wins flags based on the nb flags and the input value.
371 *****************************************************************************/
373 static void update_wins_flag(struct name_record
*namerec
, int flags
)
375 namerec
->data
.wins_flags
=0x0;
377 /* if it's a group, it can be a normal or a special one */
378 if (namerec
->data
.nb_flags
& NB_GROUP
) {
379 if (namerec
->name
.name_type
==0x1C) {
380 namerec
->data
.wins_flags
|=WINS_SGROUP
;
382 if (namerec
->data
.num_ips
>1) {
383 namerec
->data
.wins_flags
|=WINS_SGROUP
;
385 namerec
->data
.wins_flags
|=WINS_NGROUP
;
389 /* can be unique or multi-homed */
390 if (namerec
->data
.num_ips
>1) {
391 namerec
->data
.wins_flags
|=WINS_MHOMED
;
393 namerec
->data
.wins_flags
|=WINS_UNIQUE
;
397 /* the node type are the same bits */
398 namerec
->data
.wins_flags
|=namerec
->data
.nb_flags
&NB_NODETYPEMASK
;
400 /* the static bit is elsewhere */
401 if (namerec
->data
.death_time
== PERMANENT_TTL
) {
402 namerec
->data
.wins_flags
|=WINS_STATIC
;
405 /* and add the given bits */
406 namerec
->data
.wins_flags
|=flags
;
408 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
409 namerec
->data
.nb_flags
, (int)namerec
->data
.death_time
, flags
, namerec
->data
.wins_flags
));
412 /****************************************************************************
413 Return the general ID value and increase it if requested.
414 *****************************************************************************/
416 static void get_global_id_and_update(SMB_BIG_UINT
*current_id
, BOOL update
)
419 * it's kept as a static here, to prevent people from messing
420 * with the value directly
423 static SMB_BIG_UINT general_id
= 1;
425 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id
));
427 *current_id
= general_id
;
434 /****************************************************************************
435 Possibly call the WINS hook external program when a WINS change is made.
436 Also stores the changed record back in the wins_tdb.
437 *****************************************************************************/
439 static void wins_hook(const char *operation
, struct name_record
*namerec
, int ttl
)
442 char *cmd
= lp_wins_hook();
446 wins_store_changed_namerec(namerec
);
452 for (p
=namerec
->name
.name
; *p
; p
++) {
453 if (!(isalnum((int)*p
) || strchr_m("._-",*p
))) {
454 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec
->name
)));
459 /* Use the name without the nametype (and scope) appended */
461 namestr
= nmb_namestr(&namerec
->name
);
462 if ((p
= strchr(namestr
, '<'))) {
467 p
+= slprintf(p
, sizeof(command
)-1, "%s %s %s %02x %d",
471 namerec
->name
.name_type
,
474 for (i
=0;i
<namerec
->data
.num_ips
;i
++) {
475 p
+= slprintf(p
, sizeof(command
) - (p
-command
) -1, " %s", inet_ntoa(namerec
->data
.ip
[i
]));
478 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec
->name
)));
479 smbrun(command
, NULL
);
482 /****************************************************************************
483 Determine if this packet should be allocated to the WINS server.
484 *****************************************************************************/
486 BOOL
packet_is_for_wins_server(struct packet_struct
*packet
)
488 struct nmb_packet
*nmb
= &packet
->packet
.nmb
;
490 /* Only unicast packets go to a WINS server. */
491 if((wins_server_subnet
== NULL
) || (nmb
->header
.nm_flags
.bcast
== True
)) {
492 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
496 /* Check for node status requests. */
497 if (nmb
->question
.question_type
!= QUESTION_TYPE_NB_QUERY
) {
501 switch(nmb
->header
.opcode
) {
503 * A WINS server issues WACKS, not receives them.
505 case NMB_WACK_OPCODE
:
506 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
509 * A WINS server only processes registration and
510 * release requests, not responses.
512 case NMB_NAME_REG_OPCODE
:
513 case NMB_NAME_MULTIHOMED_REG_OPCODE
:
514 case NMB_NAME_REFRESH_OPCODE_8
: /* ambiguity in rfc1002 about which is correct. */
515 case NMB_NAME_REFRESH_OPCODE_9
: /* WinNT uses 8 by default. */
516 if(nmb
->header
.response
) {
517 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
522 case NMB_NAME_RELEASE_OPCODE
:
523 if(nmb
->header
.response
) {
524 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
530 * Only process unicast name queries with rd = 1.
532 case NMB_NAME_QUERY_OPCODE
:
533 if(!nmb
->header
.response
&& !nmb
->header
.nm_flags
.recursion_desired
) {
534 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
543 /****************************************************************************
544 Utility function to decide what ttl to give a register/refresh request.
545 *****************************************************************************/
547 static int get_ttl_from_packet(struct nmb_packet
*nmb
)
549 int ttl
= nmb
->additional
->ttl
;
551 if (ttl
< lp_min_wins_ttl()) {
552 ttl
= lp_min_wins_ttl();
555 if (ttl
> lp_max_wins_ttl()) {
556 ttl
= lp_max_wins_ttl();
562 /****************************************************************************
563 Load or create the WINS database.
564 *****************************************************************************/
566 BOOL
initialise_wins(void)
568 time_t time_now
= time(NULL
);
572 if(!lp_we_are_a_wins_server()) {
576 /* Open the wins.tdb. */
577 wins_tdb
= tdb_open_log(lock_path("wins.tdb"), 0, TDB_DEFAULT
|TDB_CLEAR_IF_FIRST
, O_CREAT
|O_RDWR
, 0600);
579 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
584 tdb_store_int32(wins_tdb
, "WINSDB_VERSION", WINSDB_VERSION
);
586 add_samba_names_to_subnet(wins_server_subnet
);
588 if((fp
= x_fopen(lock_path(WINS_LIST
),O_RDONLY
,0)) == NULL
) {
589 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
590 WINS_LIST
, strerror(errno
) ));
594 while (!x_feof(fp
)) {
595 pstring name_str
, ip_str
, ttl_str
, nb_flags_str
;
596 unsigned int num_ips
;
598 struct in_addr
*ip_list
;
610 /* Read a line from the wins.dat file. Strips whitespace
611 from the beginning and end of the line. */
612 if (!fgets_slash(line
,sizeof(pstring
),fp
))
618 if (strncmp(line
,"VERSION ", 8) == 0) {
619 if (sscanf(line
,"VERSION %d %u", &version
, &hash
) != 2 ||
620 version
!= WINS_VERSION
) {
621 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line
));
631 * Now we handle multiple IP addresses per name we need
632 * to iterate over the line twice. The first time to
633 * determine how many IP addresses there are, the second
634 * time to actually parse them into the ip_list array.
637 if (!next_token(&ptr
,name_str
,NULL
,sizeof(name_str
))) {
638 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line
));
642 if (!next_token(&ptr
,ttl_str
,NULL
,sizeof(ttl_str
))) {
643 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line
));
648 * Determine the number of IP addresses per line.
652 got_token
= next_token(&ptr
,ip_str
,NULL
,sizeof(ip_str
));
655 if(got_token
&& strchr(ip_str
, '.')) {
659 } while( got_token
&& was_ip
);
662 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line
));
667 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line
));
671 /* Allocate the space for the ip_list. */
672 if((ip_list
= SMB_MALLOC_ARRAY( struct in_addr
, num_ips
)) == NULL
) {
673 DEBUG(0,("initialise_wins: Malloc fail !\n"));
678 /* Reset and re-parse the line. */
680 next_token(&ptr
,name_str
,NULL
,sizeof(name_str
));
681 next_token(&ptr
,ttl_str
,NULL
,sizeof(ttl_str
));
682 for(i
= 0; i
< num_ips
; i
++) {
683 next_token(&ptr
, ip_str
, NULL
, sizeof(ip_str
));
684 ip_list
[i
] = *interpret_addr2(ip_str
);
686 next_token(&ptr
,nb_flags_str
,NULL
, sizeof(nb_flags_str
));
689 * Deal with SELF or REGISTER name encoding. Default is REGISTER
690 * for compatibility with old nmbds.
693 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'S') {
694 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line
));
699 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'R') {
700 nb_flags_str
[strlen(nb_flags_str
)-1] = '\0';
703 /* Netbios name. # divides the name from the type (hex): netbios#xx */
704 pstrcpy(name
,name_str
);
706 if((p
= strchr(name
,'#')) != NULL
) {
708 sscanf(p
+1,"%x",&type
);
711 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
712 sscanf(nb_flags_str
,"%x",&nb_flags
);
713 sscanf(ttl_str
,"%d",&ttl
);
715 /* add all entries that have 60 seconds or more to live */
716 if ((ttl
- 60) > time_now
|| ttl
== PERMANENT_TTL
) {
717 if(ttl
!= PERMANENT_TTL
) {
721 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
722 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
724 (void)add_name_to_subnet( wins_server_subnet
, name
, type
, nb_flags
,
725 ttl
, REGISTER_NAME
, num_ips
, ip_list
);
727 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
728 "%s#%02x ttl = %d first IP %s flags = %2x\n",
729 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
739 /****************************************************************************
740 Send a WINS WACK (Wait ACKnowledgement) response.
741 **************************************************************************/
743 static void send_wins_wack_response(int ttl
, struct packet_struct
*p
)
745 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
746 unsigned char rdata
[2];
748 rdata
[0] = rdata
[1] = 0;
750 /* Taken from nmblib.c - we need to send back almost
751 identical bytes from the requesting packet header. */
753 rdata
[0] = (nmb
->header
.opcode
& 0xF) << 3;
754 if (nmb
->header
.nm_flags
.authoritative
&& nmb
->header
.response
) {
757 if (nmb
->header
.nm_flags
.trunc
) {
760 if (nmb
->header
.nm_flags
.recursion_desired
) {
763 if (nmb
->header
.nm_flags
.recursion_available
&& nmb
->header
.response
) {
766 if (nmb
->header
.nm_flags
.bcast
) {
770 reply_netbios_packet(p
, /* Packet to reply to. */
771 0, /* Result code. */
772 NMB_WAIT_ACK
, /* nmbd type code. */
773 NMB_WACK_OPCODE
, /* opcode. */
775 (char *)rdata
, /* data to send. */
776 2); /* data length. */
779 /****************************************************************************
780 Send a WINS name registration response.
781 **************************************************************************/
783 static void send_wins_name_registration_response(int rcode
, int ttl
, struct packet_struct
*p
)
785 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
788 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
790 reply_netbios_packet(p
, /* Packet to reply to. */
791 rcode
, /* Result code. */
792 WINS_REG
, /* nmbd type code. */
793 NMB_NAME_REG_OPCODE
, /* opcode. */
795 rdata
, /* data to send. */
796 6); /* data length. */
799 /***********************************************************************
800 Deal with a name refresh request to a WINS server.
801 ************************************************************************/
803 void wins_process_name_refresh_request( struct subnet_record
*subrec
,
804 struct packet_struct
*p
)
806 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
807 struct nmb_name
*question
= &nmb
->question
.question_name
;
808 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
809 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
810 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
811 struct name_record
*namerec
= NULL
;
812 int ttl
= get_ttl_from_packet(nmb
);
813 struct in_addr from_ip
;
814 struct in_addr our_fake_ip
= *interpret_addr2("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(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(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
= *interpret_addr2("0.0.0.0");
1122 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1126 * We should only get unicast name registration packets here.
1127 * Anyone trying to register broadcast should not be going to a WINS
1128 * server. Log an error here.
1131 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1132 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1133 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1137 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1138 IP %s\n", registering_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1141 * See if the name already exists.
1144 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1147 * if the record exists but NOT in active state,
1150 if ( (namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1151 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1152 not active - removing it.\n", nmb_namestr(question
) ));
1153 remove_name_from_namelist( subrec
, namerec
);
1158 * Deal with the case where the name found was a dns entry.
1159 * Remove it as we now have a NetBIOS client registering the
1163 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1164 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1165 a dns lookup - removing it.\n", nmb_namestr(question
) ));
1166 remove_name_from_namelist( subrec
, namerec
);
1171 * Reject if the name exists and is not a REGISTER_NAME.
1172 * (ie. Don't allow any static names to be overwritten.
1175 if((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) {
1176 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1177 to register name %s. Name already exists in WINS with source type %d.\n",
1178 nmb_namestr(question
), namerec
->data
.source
));
1179 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1184 * Special policy decisions based on MS documentation.
1185 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1186 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1190 * A group name is always added as the local broadcast address, except
1191 * for group names ending in 0x1c.
1192 * Group names with type 0x1c are registered with individual IP addresses.
1195 if(registering_group_name
&& (question
->name_type
!= 0x1c)) {
1196 from_ip
= *interpret_addr2("255.255.255.255");
1200 * Ignore all attempts to register a unique 0x1d name, although return success.
1203 if(!registering_group_name
&& (question
->name_type
== 0x1d)) {
1204 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1205 to register name %s from IP %s.\n", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1206 send_wins_name_registration_response(0, ttl
, p
);
1211 * Next two cases are the 'if statement' mentioned above.
1214 if((namerec
!= NULL
) && NAME_GROUP(namerec
)) {
1215 if(registering_group_name
) {
1217 * If we are adding a group name, the name exists and is also a group entry just add this
1218 * IP address to it and update the ttl.
1221 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1222 inet_ntoa(from_ip
), nmb_namestr(question
) ));
1225 * Check the ip address is not already in the group.
1228 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1229 add_ip_to_name_record(namerec
, from_ip
);
1230 /* we need to update the record for replication */
1231 get_global_id_and_update(&namerec
->data
.id
, True
);
1234 * if the record is a replica, we must change
1235 * the wins owner to us to make the replication updates
1236 * it on the other wins servers.
1237 * And when the partner will receive this record,
1238 * it will update its own record.
1241 update_wins_owner(namerec
, our_fake_ip
);
1243 update_name_ttl(namerec
, ttl
);
1244 wins_hook("refresh", namerec
, ttl
);
1245 send_wins_name_registration_response(0, ttl
, p
);
1250 * If we are adding a unique name, the name exists in the WINS db
1251 * and is a group name then reject the registration.
1253 * explanation: groups have a higher priority than unique names.
1256 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1257 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1258 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1264 * From here on down we know that if the name exists in the WINS db it is
1265 * a unique name, not a group name.
1269 * If the name exists and is one of our names then check the
1270 * registering IP address. If it's not one of ours then automatically
1271 * reject without doing the query - we know we will reject it.
1274 if ( namerec
!= NULL
) {
1275 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
1276 if( is_myname(name
) ) {
1277 if(!ismyip(from_ip
)) {
1278 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1279 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1280 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1284 * It's one of our names and one of our IP's - update the ttl.
1286 update_name_ttl(namerec
, ttl
);
1287 wins_hook("refresh", namerec
, ttl
);
1288 send_wins_name_registration_response(0, ttl
, p
);
1297 * If the name exists and it is a unique registration and the registering IP
1298 * is the same as the (single) already registered IP then just update the ttl.
1300 * But not if the record is an active replica. IF it's a replica, it means it can be
1301 * the same client which has moved and not yet expired. So we don't update
1302 * the ttl in this case and go beyond to do a WACK and query the old client
1305 if( !registering_group_name
1306 && (namerec
!= NULL
)
1307 && (namerec
->data
.num_ips
== 1)
1308 && ip_equal( namerec
->data
.ip
[0], from_ip
)
1309 && ip_equal(namerec
->data
.wins_ip
, our_fake_ip
) ) {
1310 update_name_ttl( namerec
, ttl
);
1311 wins_hook("refresh", namerec
, ttl
);
1312 send_wins_name_registration_response( 0, ttl
, p
);
1317 * Finally if the name exists do a query to the registering machine
1318 * to see if they still claim to have the name.
1321 if( namerec
!= NULL
) {
1322 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1323 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1326 * First send a WACK to the registering machine.
1329 send_wins_wack_response(60, p
);
1332 * When the reply comes back we need the original packet.
1333 * Lock this so it won't be freed and then put it into
1334 * the userdata structure.
1339 userdata
= (struct userdata_struct
*)ud
;
1341 userdata
->copy_fn
= NULL
;
1342 userdata
->free_fn
= NULL
;
1343 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1344 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1347 * Use the new call to send a query directly to an IP address.
1348 * This sends the query directly to the IP address, and ensures
1349 * the recursion desired flag is not set (you were right Luke :-).
1350 * This function should *only* be called from the WINS server
1354 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1355 query_name_from_wins_server( *namerec
->data
.ip
,
1357 question
->name_type
,
1358 wins_register_query_success
,
1359 wins_register_query_fail
,
1365 * Name did not exist - add it.
1368 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1369 add_name_to_subnet( subrec
, name
, question
->name_type
,
1370 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1372 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1373 get_global_id_and_update(&namerec
->data
.id
, True
);
1374 update_wins_owner(namerec
, our_fake_ip
);
1375 update_wins_flag(namerec
, WINS_ACTIVE
);
1376 wins_hook("add", namerec
, ttl
);
1379 send_wins_name_registration_response(0, ttl
, p
);
1382 /***********************************************************************
1383 Deal with a mutihomed name query success to the machine that
1384 requested the multihomed name registration.
1386 We have a locked pointer to the original packet stashed away in the
1388 ************************************************************************/
1390 static void wins_multihomed_register_query_success(struct subnet_record
*subrec
,
1391 struct userdata_struct
*userdata
,
1392 struct nmb_name
*question_name
,
1394 struct res_rec
*answers
)
1396 struct packet_struct
*orig_reg_packet
;
1397 struct nmb_packet
*nmb
;
1398 struct name_record
*namerec
= NULL
;
1399 struct in_addr from_ip
;
1401 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
1403 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1405 nmb
= &orig_reg_packet
->packet
.nmb
;
1407 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1408 ttl
= get_ttl_from_packet(nmb
);
1411 * We want to just add the new IP, as we now know the requesting
1412 * machine claims to own it. But we can't just do that as an arbitary
1413 * amount of time may have taken place between the name query
1414 * request and this response. So we check that
1415 * the name still exists and is in the same state - if so
1416 * we just add the extra IP and update the ttl.
1419 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1421 if( (namerec
== NULL
) || (namerec
->data
.source
!= REGISTER_NAME
) || !WINS_STATE_ACTIVE(namerec
) ) {
1422 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1423 a subsequent IP address.\n", nmb_namestr(question_name
) ));
1424 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1426 orig_reg_packet
->locked
= False
;
1427 free_packet(orig_reg_packet
);
1432 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1433 add_ip_to_name_record(namerec
, from_ip
);
1436 get_global_id_and_update(&namerec
->data
.id
, True
);
1437 update_wins_owner(namerec
, our_fake_ip
);
1438 update_wins_flag(namerec
, WINS_ACTIVE
);
1439 update_name_ttl(namerec
, ttl
);
1440 wins_hook("add", namerec
, ttl
);
1441 send_wins_name_registration_response(0, ttl
, orig_reg_packet
);
1443 orig_reg_packet
->locked
= False
;
1444 free_packet(orig_reg_packet
);
1447 /***********************************************************************
1448 Deal with a name registration request query failure to a client that
1451 We have a locked pointer to the original packet stashed away in the
1453 ************************************************************************/
1455 static void wins_multihomed_register_query_fail(struct subnet_record
*subrec
,
1456 struct response_record
*rrec
,
1457 struct nmb_name
*question_name
,
1460 struct userdata_struct
*userdata
= rrec
->userdata
;
1461 struct packet_struct
*orig_reg_packet
;
1463 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1465 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1466 query successfully for name %s.\n", inet_ntoa(orig_reg_packet
->ip
), nmb_namestr(question_name
) ));
1467 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1469 orig_reg_packet
->locked
= False
;
1470 free_packet(orig_reg_packet
);
1474 /***********************************************************************
1475 Deal with a multihomed name registration request to a WINS server.
1476 These cannot be group name registrations.
1477 ***********************************************************************/
1479 void wins_process_multihomed_name_registration_request( struct subnet_record
*subrec
,
1480 struct packet_struct
*p
)
1482 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1483 struct nmb_name
*question
= &nmb
->question
.question_name
;
1484 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
1485 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1486 int ttl
= get_ttl_from_packet(nmb
);
1487 struct name_record
*namerec
= NULL
;
1488 struct in_addr from_ip
;
1489 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
1490 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
1493 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1497 * We should only get unicast name registration packets here.
1498 * Anyone trying to register broadcast should not be going to a WINS
1499 * server. Log an error here.
1502 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1503 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1504 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1509 * Only unique names should be registered multihomed.
1513 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1514 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1515 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1519 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1520 IP %s\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1523 * Deal with policy regarding 0x1d names.
1526 if(question
->name_type
== 0x1d) {
1527 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1528 to register name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1529 send_wins_name_registration_response(0, ttl
, p
);
1534 * See if the name already exists.
1537 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1540 * if the record exists but NOT in active state,
1544 if ((namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1545 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question
)));
1546 remove_name_from_namelist(subrec
, namerec
);
1551 * Deal with the case where the name found was a dns entry.
1552 * Remove it as we now have a NetBIOS client registering the
1556 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1557 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1558 - removing it.\n", nmb_namestr(question
) ));
1559 remove_name_from_namelist( subrec
, namerec
);
1564 * Reject if the name exists and is not a REGISTER_NAME.
1565 * (ie. Don't allow any static names to be overwritten.
1568 if( (namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
) ) {
1569 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1570 to register name %s. Name already exists in WINS with source type %d.\n",
1571 nmb_namestr(question
), namerec
->data
.source
));
1572 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1577 * Reject if the name exists and is a GROUP name and is active.
1580 if((namerec
!= NULL
) && NAME_GROUP(namerec
) && WINS_STATE_ACTIVE(namerec
)) {
1581 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1582 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1583 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1588 * From here on down we know that if the name exists in the WINS db it is
1589 * a unique name, not a group name.
1593 * If the name exists and is one of our names then check the
1594 * registering IP address. If it's not one of ours then automatically
1595 * reject without doing the query - we know we will reject it.
1598 if((namerec
!= NULL
) && (is_myname(namerec
->name
.name
)) ) {
1599 if(!ismyip(from_ip
)) {
1600 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1601 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1602 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1606 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1607 * update the ttl. Update the version ID to force replication.
1609 update_name_ttl(namerec
, ttl
);
1611 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1612 get_global_id_and_update(&namerec
->data
.id
, True
);
1613 update_wins_owner(namerec
, our_fake_ip
);
1614 update_wins_flag(namerec
, WINS_ACTIVE
);
1616 add_ip_to_name_record(namerec
, from_ip
);
1619 wins_hook("refresh", namerec
, ttl
);
1620 send_wins_name_registration_response(0, ttl
, p
);
1626 * If the name exists and is active, check if the IP address is already registered
1627 * to that name. If so then update the ttl and reply success.
1630 if((namerec
!= NULL
) && find_ip_in_name_record(namerec
, from_ip
) && WINS_STATE_ACTIVE(namerec
)) {
1631 update_name_ttl(namerec
, ttl
);
1634 * If it's a replica, we need to become the wins owner
1635 * to force the replication
1637 if (!ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
1638 get_global_id_and_update(&namerec
->data
.id
, True
);
1639 update_wins_owner(namerec
, our_fake_ip
);
1640 update_wins_flag(namerec
, WINS_ACTIVE
);
1643 wins_hook("refresh", namerec
, ttl
);
1644 send_wins_name_registration_response(0, ttl
, p
);
1649 * If the name exists do a query to the owner
1650 * to see if they still want the name.
1653 if(namerec
!= NULL
) {
1654 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1655 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1658 * First send a WACK to the registering machine.
1661 send_wins_wack_response(60, p
);
1664 * When the reply comes back we need the original packet.
1665 * Lock this so it won't be freed and then put it into
1666 * the userdata structure.
1671 userdata
= (struct userdata_struct
*)ud
;
1673 userdata
->copy_fn
= NULL
;
1674 userdata
->free_fn
= NULL
;
1675 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1676 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1679 * Use the new call to send a query directly to an IP address.
1680 * This sends the query directly to the IP address, and ensures
1681 * the recursion desired flag is not set (you were right Luke :-).
1682 * This function should *only* be called from the WINS server
1685 * Note that this packet is sent to the current owner of the name,
1686 * not the person who sent the packet
1689 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1690 query_name_from_wins_server( namerec
->data
.ip
[0],
1692 question
->name_type
,
1693 wins_multihomed_register_query_success
,
1694 wins_multihomed_register_query_fail
,
1701 * Name did not exist - add it.
1704 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1705 add_name_to_subnet( subrec
, qname
, question
->name_type
,
1706 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1708 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1709 get_global_id_and_update(&namerec
->data
.id
, True
);
1710 update_wins_owner(namerec
, our_fake_ip
);
1711 update_wins_flag(namerec
, WINS_ACTIVE
);
1712 wins_hook("add", namerec
, ttl
);
1715 send_wins_name_registration_response(0, ttl
, p
);
1718 /***********************************************************************
1719 Fetch all *<1b> names from the WINS db and store on the namelist.
1720 ***********************************************************************/
1722 static int fetch_1b_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
1724 struct name_record
*namerec
= NULL
;
1726 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
1730 /* Filter out all non-1b names. */
1731 if (kbuf
.dptr
[sizeof(unstring
)] != 0x1b) {
1735 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
1740 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
1744 void fetch_all_active_wins_1b_names(void)
1746 tdb_traverse(wins_tdb
, fetch_1b_traverse_fn
, NULL
);
1749 /***********************************************************************
1750 Deal with the special name query for *<1b>.
1751 ***********************************************************************/
1753 static void process_wins_dmb_query_request(struct subnet_record
*subrec
,
1754 struct packet_struct
*p
)
1756 struct name_record
*namerec
= NULL
;
1761 * Go through all the ACTIVE names in the WINS db looking for those
1762 * ending in <1b>. Use this to calculate the number of IP
1763 * addresses we need to return.
1768 /* First, clear the in memory list - we're going to re-populate
1769 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1771 wins_delete_all_tmp_in_memory_records();
1773 fetch_all_active_wins_1b_names();
1775 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1776 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1777 num_ips
+= namerec
->data
.num_ips
;
1783 * There are no 0x1b names registered. Return name query fail.
1785 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1789 if((prdata
= (char *)SMB_MALLOC( num_ips
* 6 )) == NULL
) {
1790 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1795 * Go through all the names again in the WINS db looking for those
1796 * ending in <1b>. Add their IP addresses into the list we will
1801 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1802 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1804 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1805 set_nb_flags(&prdata
[num_ips
* 6],namerec
->data
.nb_flags
);
1806 putip((char *)&prdata
[(num_ips
* 6) + 2], &namerec
->data
.ip
[i
]);
1813 * Send back the reply containing the IP list.
1816 reply_netbios_packet(p
, /* Packet to reply to. */
1817 0, /* Result code. */
1818 WINS_QUERY
, /* nmbd type code. */
1819 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1820 lp_min_wins_ttl(), /* ttl. */
1821 prdata
, /* data to send. */
1822 num_ips
*6); /* data length. */
1827 /****************************************************************************
1828 Send a WINS name query response.
1829 **************************************************************************/
1831 void send_wins_name_query_response(int rcode
, struct packet_struct
*p
,
1832 struct name_record
*namerec
)
1835 char *prdata
= rdata
;
1836 int reply_data_len
= 0;
1840 memset(rdata
,'\0',6);
1843 ttl
= (namerec
->data
.death_time
!= PERMANENT_TTL
) ? namerec
->data
.death_time
- p
->timestamp
: lp_max_wins_ttl();
1845 /* Copy all known ip addresses into the return data. */
1846 /* Optimise for the common case of one IP address so we don't need a malloc. */
1848 if( namerec
->data
.num_ips
== 1 ) {
1851 if((prdata
= (char *)SMB_MALLOC( namerec
->data
.num_ips
* 6 )) == NULL
) {
1852 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1857 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1858 set_nb_flags(&prdata
[i
*6],namerec
->data
.nb_flags
);
1859 putip((char *)&prdata
[2+(i
*6)], &namerec
->data
.ip
[i
]);
1862 sort_query_replies(prdata
, i
, p
->ip
);
1863 reply_data_len
= namerec
->data
.num_ips
* 6;
1866 reply_netbios_packet(p
, /* Packet to reply to. */
1867 rcode
, /* Result code. */
1868 WINS_QUERY
, /* nmbd type code. */
1869 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1871 prdata
, /* data to send. */
1872 reply_data_len
); /* data length. */
1874 if(prdata
!= rdata
) {
1879 /***********************************************************************
1880 Deal with a name query.
1881 ***********************************************************************/
1883 void wins_process_name_query_request(struct subnet_record
*subrec
,
1884 struct packet_struct
*p
)
1886 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1887 struct nmb_name
*question
= &nmb
->question
.question_name
;
1888 struct name_record
*namerec
= NULL
;
1891 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1892 nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1895 * Special name code. If the queried name is *<1b> then search
1896 * the entire WINS database and return a list of all the IP addresses
1897 * registered to any <1b> name. This is to allow domain master browsers
1898 * to discover other domains that may not have a presence on their subnet.
1901 pull_ascii_nstring(qname
, sizeof(qname
), question
->name
);
1902 if(strequal( qname
, "*") && (question
->name_type
== 0x1b)) {
1903 process_wins_dmb_query_request( subrec
, p
);
1907 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1909 if(namerec
!= NULL
) {
1911 * If the name is not anymore in active state then reply not found.
1912 * it's fair even if we keep it in the cache for days.
1914 if (!WINS_STATE_ACTIVE(namerec
)) {
1915 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1916 nmb_namestr(question
) ));
1917 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1922 * If it's a DNSFAIL_NAME then reply name not found.
1925 if( namerec
->data
.source
== DNSFAIL_NAME
) {
1926 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1927 nmb_namestr(question
) ));
1928 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1933 * If the name has expired then reply name not found.
1936 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< p
->timestamp
) ) {
1937 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1938 nmb_namestr(question
) ));
1939 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1943 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1944 nmb_namestr(question
), inet_ntoa(namerec
->data
.ip
[0]) ));
1946 send_wins_name_query_response(0, p
, namerec
);
1951 * Name not found in WINS - try a dns query if it's a 0x20 name.
1954 if(lp_dns_proxy() && ((question
->name_type
== 0x20) || question
->name_type
== 0)) {
1955 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1956 nmb_namestr(question
) ));
1958 queue_dns_query(p
, question
);
1963 * Name not found - return error.
1966 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1969 /****************************************************************************
1970 Send a WINS name release response.
1971 **************************************************************************/
1973 static void send_wins_name_release_response(int rcode
, struct packet_struct
*p
)
1975 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1978 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
1980 reply_netbios_packet(p
, /* Packet to reply to. */
1981 rcode
, /* Result code. */
1982 NMB_REL
, /* nmbd type code. */
1983 NMB_NAME_RELEASE_OPCODE
, /* opcode. */
1985 rdata
, /* data to send. */
1986 6); /* data length. */
1989 /***********************************************************************
1990 Deal with a name release.
1991 ***********************************************************************/
1993 void wins_process_name_release_request(struct subnet_record
*subrec
,
1994 struct packet_struct
*p
)
1996 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1997 struct nmb_name
*question
= &nmb
->question
.question_name
;
1998 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
1999 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
2000 struct name_record
*namerec
= NULL
;
2001 struct in_addr from_ip
;
2002 BOOL releasing_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;;
2004 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
2008 * We should only get unicast name registration packets here.
2009 * Anyone trying to register broadcast should not be going to a WINS
2010 * server. Log an error here.
2013 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2014 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2015 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
2019 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2020 IP %s\n", releasing_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
2023 * Deal with policy regarding 0x1d names.
2026 if(!releasing_group_name
&& (question
->name_type
== 0x1d)) {
2027 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2028 to release name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
2029 send_wins_name_release_response(0, p
);
2034 * See if the name already exists.
2037 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
2039 if( (namerec
== NULL
) || ((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) ) {
2040 send_wins_name_release_response(NAM_ERR
, p
);
2045 * Check that the sending machine has permission to release this name.
2046 * If it's a group name not ending in 0x1c then just say yes and let
2047 * the group time out.
2050 if(releasing_group_name
&& (question
->name_type
!= 0x1c)) {
2051 send_wins_name_release_response(0, p
);
2056 * Check that the releasing node is on the list of IP addresses
2057 * for this name. Disallow the release if not.
2060 if(!find_ip_in_name_record(namerec
, from_ip
)) {
2061 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2062 release name %s as IP %s is not one of the known IP's for this name.\n",
2063 nmb_namestr(question
), inet_ntoa(from_ip
) ));
2064 send_wins_name_release_response(NAM_ERR
, p
);
2069 * Check if the record is active. IF it's already released
2070 * or tombstoned, refuse the release.
2073 if (!WINS_STATE_ACTIVE(namerec
)) {
2074 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2075 release name %s as this record is not active anymore.\n", nmb_namestr(question
) ));
2076 send_wins_name_release_response(NAM_ERR
, p
);
2081 * Check if the record is a 0x1c group
2082 * and has more then one ip
2083 * remove only this address.
2086 if(releasing_group_name
&& (question
->name_type
== 0x1c) && (namerec
->data
.num_ips
> 1)) {
2087 remove_ip_from_name_record(namerec
, from_ip
);
2088 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2089 inet_ntoa(from_ip
),nmb_namestr(question
)));
2090 wins_hook("delete", namerec
, 0);
2091 send_wins_name_release_response(0, p
);
2096 * Send a release response.
2097 * Flag the name as released and update the ttl
2100 namerec
->data
.wins_flags
|= WINS_RELEASED
;
2101 update_name_ttl(namerec
, EXTINCTION_INTERVAL
);
2103 wins_hook("delete", namerec
, 0);
2104 send_wins_name_release_response(0, p
);
2107 /*******************************************************************
2108 WINS time dependent processing.
2109 ******************************************************************/
2111 static int wins_processing_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2113 time_t t
= *(time_t *)state
;
2114 BOOL store_record
= False
;
2115 struct name_record
*namerec
= NULL
;
2116 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
2118 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2122 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2127 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< t
) ) {
2128 if( namerec
->data
.source
== SELF_NAME
) {
2129 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2130 wins_server_subnet
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
2131 namerec
->data
.death_time
+= 300;
2132 store_record
= True
;
2134 } else if (namerec
->data
.source
== DNS_NAME
|| namerec
->data
.source
== DNSFAIL_NAME
) {
2135 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2136 nmb_namestr(&namerec
->name
)));
2137 remove_name_from_wins_namelist(namerec
);
2141 /* handle records, samba is the wins owner */
2142 if (ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
2143 switch (namerec
->data
.wins_flags
| WINS_STATE_MASK
) {
2145 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2146 namerec
->data
.wins_flags
|=WINS_RELEASED
;
2147 namerec
->data
.death_time
= t
+ EXTINCTION_INTERVAL
;
2148 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2149 nmb_namestr(&namerec
->name
)));
2150 store_record
= True
;
2153 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2154 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2155 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2156 get_global_id_and_update(&namerec
->data
.id
, True
);
2157 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2158 nmb_namestr(&namerec
->name
)));
2159 store_record
= True
;
2161 case WINS_TOMBSTONED
:
2162 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2163 nmb_namestr(&namerec
->name
)));
2164 remove_name_from_wins_namelist(namerec
);
2168 switch (namerec
->data
.wins_flags
| WINS_STATE_MASK
) {
2170 /* that's not as MS says it should be */
2171 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2172 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2173 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2174 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2175 nmb_namestr(&namerec
->name
)));
2176 store_record
= True
;
2178 case WINS_TOMBSTONED
:
2179 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2180 nmb_namestr(&namerec
->name
)));
2181 remove_name_from_wins_namelist(namerec
);
2184 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2185 we are not the wins owner !\n", nmb_namestr(&namerec
->name
)));
2194 wins_store_changed_namerec(namerec
);
2197 SAFE_FREE(namerec
->data
.ip
);
2203 /*******************************************************************
2204 Time dependent wins processing.
2205 ******************************************************************/
2207 void initiate_wins_processing(time_t t
)
2209 static time_t lasttime
= 0;
2214 if (t
- lasttime
< 20) {
2218 if(!lp_we_are_a_wins_server()) {
2223 tdb_traverse(wins_tdb
, wins_processing_traverse_fn
, &t
);
2225 wins_delete_all_tmp_in_memory_records();
2227 wins_write_database(t
, True
);
2232 /*******************************************************************
2233 Write out one record.
2234 ******************************************************************/
2236 void wins_write_name_record(struct name_record
*namerec
, XFILE
*fp
)
2241 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec
->name
) ));
2243 if( namerec
->data
.death_time
!= PERMANENT_TTL
) {
2246 tm
= localtime(&namerec
->data
.death_time
);
2254 nl
= strrchr( ts
, '\n' );
2258 DEBUGADD(4,("TTL = %s ", ts
));
2260 DEBUGADD(4,("TTL = PERMANENT "));
2263 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
2264 DEBUGADD(4,("%15s ", inet_ntoa(namerec
->data
.ip
[i
]) ));
2266 DEBUGADD(4,("%2x\n", namerec
->data
.nb_flags
));
2268 if( namerec
->data
.source
== REGISTER_NAME
) {
2270 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
2271 x_fprintf(fp
, "\"%s#%02x\" %d ", name
,namerec
->name
.name_type
, /* Ignore scope. */
2272 (int)namerec
->data
.death_time
);
2274 for (i
= 0; i
< namerec
->data
.num_ips
; i
++)
2275 x_fprintf( fp
, "%s ", inet_ntoa( namerec
->data
.ip
[i
] ) );
2276 x_fprintf( fp
, "%2xR\n", namerec
->data
.nb_flags
);
2280 /*******************************************************************
2281 Write out the current WINS database.
2282 ******************************************************************/
2284 static int wins_writedb_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2286 struct name_record
*namerec
= NULL
;
2287 XFILE
*fp
= (XFILE
*)state
;
2289 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2293 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2298 wins_write_name_record(namerec
, fp
);
2300 SAFE_FREE(namerec
->data
.ip
);
2306 void wins_write_database(time_t t
, BOOL background
)
2308 static time_t last_write_time
= 0;
2309 pstring fname
, fnamenew
;
2314 if (!last_write_time
) {
2315 last_write_time
= t
;
2317 if (t
- last_write_time
< 120) {
2323 if(!lp_we_are_a_wins_server()) {
2327 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2333 if (tdb_reopen(wins_tdb
)) {
2334 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2340 slprintf(fname
,sizeof(fname
)-1,"%s/%s", lp_lockdir(), WINS_LIST
);
2341 all_string_sub(fname
,"//", "/", 0);
2342 slprintf(fnamenew
,sizeof(fnamenew
)-1,"%s.%u", fname
, (unsigned int)sys_getpid());
2344 if((fp
= x_fopen(fnamenew
,O_WRONLY
|O_CREAT
,0644)) == NULL
) {
2345 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew
, strerror(errno
)));
2352 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2354 x_fprintf(fp
,"VERSION %d %u\n", WINS_VERSION
, 0);
2356 tdb_traverse(wins_tdb
, wins_writedb_traverse_fn
, fp
);
2359 chmod(fnamenew
,0644);
2361 rename(fnamenew
,fname
);
2368 Until winsrepl is done
.
2369 /****************************************************************************
2370 Process a internal Samba message receiving a wins record.
2371 ***************************************************************************/
2373 void nmbd_wins_new_entry(int msg_type
, struct process_id src
,
2374 void *buf
, size_t len
)
2376 WINS_RECORD
*record
;
2377 struct name_record
*namerec
= NULL
;
2378 struct name_record
*new_namerec
= NULL
;
2379 struct nmb_name question
;
2380 BOOL overwrite
=False
;
2381 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
2388 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2389 record
=(WINS_RECORD
*)buf
;
2391 make_nmb_name(&question
, record
->name
, record
->type
);
2393 namerec
= find_name_on_subnet(wins_server_subnet
, &question
, FIND_ANY_NAME
);
2395 /* record doesn't exist, add it */
2396 if (namerec
== NULL
) {
2397 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2398 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2400 new_namerec
=add_name_to_subnet( wins_server_subnet
,
2404 EXTINCTION_INTERVAL
,
2409 if (new_namerec
!=NULL
) {
2410 update_wins_owner(new_namerec
, record
->wins_ip
);
2411 update_wins_flag(new_namerec
, record
->wins_flags
);
2412 new_namerec
->data
.id
=record
->id
;
2414 wins_server_subnet
->namelist_changed
= True
;
2418 /* check if we have a conflict */
2419 if (namerec
!= NULL
) {
2420 /* both records are UNIQUE */
2421 if (namerec
->data
.wins_flags
&WINS_UNIQUE
&& record
->wins_flags
&WINS_UNIQUE
) {
2423 /* the database record is a replica */
2424 if (!ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
2425 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
) {
2426 if (ip_equal(namerec
->data
.wins_ip
, record
->wins_ip
))
2431 /* we are the wins owner of the database record */
2432 /* the 2 records have the same IP address */
2433 if (ip_equal(namerec
->data
.ip
[0], record
->ip
[0])) {
2434 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
)
2435 get_global_id_and_update(&namerec
->data
.id
, True
);
2440 /* the 2 records have different IP address */
2441 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2442 if (record
->wins_flags
&WINS_TOMBSTONED
)
2443 get_global_id_and_update(&namerec
->data
.id
, True
);
2444 if (record
->wins_flags
&WINS_ACTIVE
)
2445 /* send conflict challenge to the replica node */
2454 /* the replica is a standard group */
2455 if (record
->wins_flags
&WINS_NGROUP
|| record
->wins_flags
&WINS_SGROUP
) {
2456 /* if the database record is unique and active force a name release */
2457 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2458 /* send a release name to the unique node */
2464 /* the replica is a special group */
2465 if (record
->wins_flags
&WINS_SGROUP
&& namerec
->data
.wins_flags
&WINS_SGROUP
) {
2466 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2467 for (i
=0; i
<record
->num_ips
; i
++)
2468 if(!find_ip_in_name_record(namerec
, record
->ip
[i
]))
2469 add_ip_to_name_record(namerec
, record
->ip
[i
]);
2475 /* the replica is a multihomed host */
2477 /* I'm giving up on multi homed. Too much complex to understand */
2479 if (record
->wins_flags
&WINS_MHOMED
) {
2480 if (! (namerec
->data
.wins_flags
&WINS_ACTIVE
)) {
2481 if ( !(namerec
->data
.wins_flags
&WINS_RELEASED
) && !(namerec
->data
.wins_flags
&WINS_NGROUP
))
2485 if (ip_equal(record
->wins_ip
, namerec
->data
.wins_ip
))
2488 if (ip_equal(namerec
->data
.wins_ip
, our_fake_ip
))
2489 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2490 get_global_id_and_update(&namerec
->data
.id
, True
);
2494 if (record
->wins_flags
&WINS_ACTIVE
&& namerec
->data
.wins_flags
&WINS_ACTIVE
)
2495 if (namerec
->data
.wins_flags
&WINS_UNIQUE
||
2496 namerec
->data
.wins_flags
&WINS_MHOMED
)
2497 if (ip_equal(record
->wins_ip
, namerec
->data
.wins_ip
))
2502 if (overwrite
== False
)
2503 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2504 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2506 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2507 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2509 /* remove the old record and add a new one */
2510 remove_name_from_namelist( wins_server_subnet
, namerec
);
2511 new_namerec
=add_name_to_subnet( wins_server_subnet
, record
->name
, record
->type
, record
->nb_flags
,
2512 EXTINCTION_INTERVAL
, REGISTER_NAME
, record
->num_ips
, record
->ip
);
2513 if (new_namerec
!=NULL
) {
2514 update_wins_owner(new_namerec
, record
->wins_ip
);
2515 update_wins_flag(new_namerec
, record
->wins_flags
);
2516 new_namerec
->data
.id
=record
->id
;
2518 wins_server_subnet
->namelist_changed
= True
;
2521 wins_server_subnet
->namelist_changed
= True
;