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 "nmbd/nmbd.h"
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 Delete all the temporary 1b name records on the in-memory linked list.
57 *****************************************************************************/
59 static void wins_delete_all_1b_in_memory_records(void)
61 struct name_record
*nr
= NULL
;
62 struct name_record
*nrnext
= NULL
;
64 /* Delete all temporary 1b name records on the wins subnet linked list. */
65 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nrnext
) {
67 if (nr
->name
.name_type
== 0x1b) {
68 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
69 SAFE_FREE(nr
->data
.ip
);
75 /****************************************************************************
76 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
77 *****************************************************************************/
79 static struct name_record
*wins_record_to_name_record(TDB_DATA key
, TDB_DATA data
)
81 struct name_record
*namerec
= NULL
;
84 uint32 death_time
, refresh_time
;
85 uint32 id_low
, id_high
;
92 if (data
.dptr
== NULL
|| data
.dsize
== 0) {
96 /* Min size is "wbddddddd" + 1 ip address (4). */
97 if (data
.dsize
< 2 + 1 + (7*4) + 4) {
101 len
= tdb_unpack(data
.dptr
, data
.dsize
,
113 namerec
= SMB_MALLOC_P(struct name_record
);
117 ZERO_STRUCTP(namerec
);
119 namerec
->data
.ip
= SMB_MALLOC_ARRAY(struct in_addr
, num_ips
);
120 if (!namerec
->data
.ip
) {
125 namerec
->subnet
= wins_server_subnet
;
126 push_ascii_nstring(namerec
->name
.name
, (const char *)key
.dptr
);
127 namerec
->name
.name_type
= key
.dptr
[sizeof(unstring
)];
129 push_ascii(namerec
->name
.scope
, global_scope(), 64, STR_TERMINATE
);
131 /* We're using a byte-by-byte compare, so we must be sure that
132 * unused space doesn't have garbage in it.
135 for( i
= strlen( namerec
->name
.name
); i
< sizeof( namerec
->name
.name
); i
++ ) {
136 namerec
->name
.name
[i
] = '\0';
138 for( i
= strlen( namerec
->name
.scope
); i
< sizeof( namerec
->name
.scope
); i
++ ) {
139 namerec
->name
.scope
[i
] = '\0';
142 namerec
->data
.nb_flags
= nb_flags
;
143 namerec
->data
.source
= (enum name_source
)nr_src
;
144 namerec
->data
.death_time
= (time_t)death_time
;
145 namerec
->data
.refresh_time
= (time_t)refresh_time
;
146 namerec
->data
.id
= id_low
;
147 #if defined(HAVE_LONGLONG)
148 namerec
->data
.id
|= ((uint64_t)id_high
<< 32);
150 namerec
->data
.wins_ip
.s_addr
= saddr
;
151 namerec
->data
.wins_flags
= wins_flags
,
152 namerec
->data
.num_ips
= num_ips
;
154 for (i
= 0; i
< num_ips
; i
++) {
155 namerec
->data
.ip
[i
].s_addr
= IVAL(data
.dptr
, len
+ (i
*4));
161 /****************************************************************************
162 Convert a struct name_record to a wins.tdb record. Ignore the scope.
163 *****************************************************************************/
165 static TDB_DATA
name_record_to_wins_record(const struct name_record
*namerec
)
170 uint32 id_low
= (namerec
->data
.id
& 0xFFFFFFFF);
171 #if defined(HAVE_LONGLONG)
172 uint32 id_high
= (namerec
->data
.id
>> 32) & 0xFFFFFFFF;
179 len
= (2 + 1 + (7*4)); /* "wbddddddd" */
180 len
+= (namerec
->data
.num_ips
* 4);
182 data
.dptr
= (uint8
*)SMB_MALLOC(len
);
188 len
= tdb_pack(data
.dptr
, data
.dsize
, "wbddddddd",
189 namerec
->data
.nb_flags
,
190 (unsigned char)namerec
->data
.source
,
191 (uint32
)namerec
->data
.death_time
,
192 (uint32
)namerec
->data
.refresh_time
,
195 (uint32
)namerec
->data
.wins_ip
.s_addr
,
196 (uint32
)namerec
->data
.wins_flags
,
197 (uint32
)namerec
->data
.num_ips
);
199 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
200 SIVAL(data
.dptr
, len
+ (i
*4), namerec
->data
.ip
[i
].s_addr
);
206 /****************************************************************************
207 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
208 *****************************************************************************/
210 static TDB_DATA
name_to_key(const struct nmb_name
*nmbname
)
212 static char keydata
[sizeof(unstring
) + 1];
215 memset(keydata
, '\0', sizeof(keydata
));
217 pull_ascii_nstring(keydata
, sizeof(unstring
), nmbname
->name
);
219 keydata
[sizeof(unstring
)] = nmbname
->name_type
;
220 key
.dptr
= (uint8
*)keydata
;
221 key
.dsize
= sizeof(keydata
);
226 /****************************************************************************
227 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
228 on the linked list. We will free this later in XXXX().
229 *****************************************************************************/
231 struct name_record
*find_name_on_wins_subnet(const struct nmb_name
*nmbname
, bool self_only
)
234 struct name_record
*nr
= NULL
;
235 struct name_record
*namerec
= NULL
;
241 key
= name_to_key(nmbname
);
242 data
= tdb_fetch(wins_tdb
, key
);
244 if (data
.dsize
== 0) {
248 namerec
= wins_record_to_name_record(key
, data
);
250 /* done with the this */
252 SAFE_FREE( data
.dptr
);
258 /* Self names only - these include permanent names. */
259 if( self_only
&& (namerec
->data
.source
!= SELF_NAME
) && (namerec
->data
.source
!= PERMANENT_NAME
) ) {
260 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname
) ) );
261 SAFE_FREE(namerec
->data
.ip
);
266 /* Search for this name record on the list. Replace it if found. */
268 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nr
->next
) {
269 if (memcmp(nmbname
->name
, nr
->name
.name
, 16) == 0) {
271 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
272 SAFE_FREE(nr
->data
.ip
);
278 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
282 /****************************************************************************
283 Overwrite or add a given name in the wins.tdb.
284 *****************************************************************************/
286 static bool store_or_replace_wins_namerec(const struct name_record
*namerec
, int tdb_flag
)
295 key
= name_to_key(&namerec
->name
);
296 data
= name_record_to_wins_record(namerec
);
298 if (data
.dptr
== NULL
) {
302 ret
= tdb_store(wins_tdb
, key
, data
, tdb_flag
);
304 SAFE_FREE(data
.dptr
);
305 return (ret
== 0) ? True
: False
;
308 /****************************************************************************
309 Overwrite a given name in the wins.tdb.
310 *****************************************************************************/
312 bool wins_store_changed_namerec(const struct name_record
*namerec
)
314 return store_or_replace_wins_namerec(namerec
, TDB_REPLACE
);
317 /****************************************************************************
318 Primary interface into creating and overwriting records in the wins.tdb.
319 *****************************************************************************/
321 bool add_name_to_wins_subnet(const struct name_record
*namerec
)
323 return store_or_replace_wins_namerec(namerec
, TDB_INSERT
);
326 /****************************************************************************
327 Delete a given name in the tdb and remove the temporary malloc'ed data struct
329 *****************************************************************************/
331 bool remove_name_from_wins_namelist(struct name_record
*namerec
)
340 key
= name_to_key(&namerec
->name
);
341 ret
= tdb_delete(wins_tdb
, key
);
343 DLIST_REMOVE(wins_server_subnet
->namelist
, namerec
);
345 /* namerec must be freed by the caller */
347 return (ret
== 0) ? True
: False
;
350 /****************************************************************************
351 Dump out the complete namelist.
352 *****************************************************************************/
354 static int traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
356 struct name_record
*namerec
= NULL
;
357 XFILE
*fp
= (XFILE
*)state
;
359 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
363 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
368 dump_name_record(namerec
, fp
);
370 SAFE_FREE(namerec
->data
.ip
);
375 void dump_wins_subnet_namelist(XFILE
*fp
)
377 tdb_traverse(wins_tdb
, traverse_fn
, (void *)fp
);
380 /****************************************************************************
381 Change the wins owner address in the record.
382 *****************************************************************************/
384 static void update_wins_owner(struct name_record
*namerec
, struct in_addr wins_ip
)
386 namerec
->data
.wins_ip
=wins_ip
;
389 /****************************************************************************
390 Create the wins flags based on the nb flags and the input value.
391 *****************************************************************************/
393 static void update_wins_flag(struct name_record
*namerec
, int flags
)
395 namerec
->data
.wins_flags
=0x0;
397 /* if it's a group, it can be a normal or a special one */
398 if (namerec
->data
.nb_flags
& NB_GROUP
) {
399 if (namerec
->name
.name_type
==0x1C) {
400 namerec
->data
.wins_flags
|=WINS_SGROUP
;
402 if (namerec
->data
.num_ips
>1) {
403 namerec
->data
.wins_flags
|=WINS_SGROUP
;
405 namerec
->data
.wins_flags
|=WINS_NGROUP
;
409 /* can be unique or multi-homed */
410 if (namerec
->data
.num_ips
>1) {
411 namerec
->data
.wins_flags
|=WINS_MHOMED
;
413 namerec
->data
.wins_flags
|=WINS_UNIQUE
;
417 /* the node type are the same bits */
418 namerec
->data
.wins_flags
|=namerec
->data
.nb_flags
&NB_NODETYPEMASK
;
420 /* the static bit is elsewhere */
421 if (namerec
->data
.death_time
== PERMANENT_TTL
) {
422 namerec
->data
.wins_flags
|=WINS_STATIC
;
425 /* and add the given bits */
426 namerec
->data
.wins_flags
|=flags
;
428 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: %d, flags: 0x%x, winsflags: 0x%x\n",
429 namerec
->data
.nb_flags
, (int)namerec
->data
.death_time
, flags
, namerec
->data
.wins_flags
));
432 /****************************************************************************
433 Return the general ID value and increase it if requested.
434 *****************************************************************************/
436 static void get_global_id_and_update(uint64_t *current_id
, bool update
)
439 * it's kept as a static here, to prevent people from messing
440 * with the value directly
443 static uint64_t general_id
= 1;
445 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id
));
447 *current_id
= general_id
;
454 /****************************************************************************
455 Possibly call the WINS hook external program when a WINS change is made.
456 Also stores the changed record back in the wins_tdb.
457 *****************************************************************************/
459 static void wins_hook(const char *operation
, struct name_record
*namerec
, int ttl
)
461 char *command
= NULL
;
462 char *cmd
= lp_wins_hook();
465 TALLOC_CTX
*ctx
= talloc_tos();
467 wins_store_changed_namerec(namerec
);
473 for (p
=namerec
->name
.name
; *p
; p
++) {
474 if (!(isalnum((int)*p
) || strchr_m("._-",*p
))) {
475 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec
->name
)));
480 /* Use the name without the nametype (and scope) appended */
482 namestr
= nmb_namestr(&namerec
->name
);
483 if ((p
= strchr(namestr
, '<'))) {
487 command
= talloc_asprintf(ctx
,
492 namerec
->name
.name_type
,
498 for (i
=0;i
<namerec
->data
.num_ips
;i
++) {
499 command
= talloc_asprintf_append(command
,
501 inet_ntoa(namerec
->data
.ip
[i
]));
507 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec
->name
)));
508 smbrun(command
, NULL
);
509 TALLOC_FREE(command
);
512 /****************************************************************************
513 Determine if this packet should be allocated to the WINS server.
514 *****************************************************************************/
516 bool packet_is_for_wins_server(struct packet_struct
*packet
)
518 struct nmb_packet
*nmb
= &packet
->packet
.nmb
;
520 /* Only unicast packets go to a WINS server. */
521 if((wins_server_subnet
== NULL
) || (nmb
->header
.nm_flags
.bcast
== True
)) {
522 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
526 /* Check for node status requests. */
527 if (nmb
->question
.question_type
!= QUESTION_TYPE_NB_QUERY
) {
531 switch(nmb
->header
.opcode
) {
533 * A WINS server issues WACKS, not receives them.
535 case NMB_WACK_OPCODE
:
536 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
539 * A WINS server only processes registration and
540 * release requests, not responses.
542 case NMB_NAME_REG_OPCODE
:
543 case NMB_NAME_MULTIHOMED_REG_OPCODE
:
544 case NMB_NAME_REFRESH_OPCODE_8
: /* ambiguity in rfc1002 about which is correct. */
545 case NMB_NAME_REFRESH_OPCODE_9
: /* WinNT uses 8 by default. */
546 if(nmb
->header
.response
) {
547 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
552 case NMB_NAME_RELEASE_OPCODE
:
553 if(nmb
->header
.response
) {
554 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
560 * Only process unicast name queries with rd = 1.
562 case NMB_NAME_QUERY_OPCODE
:
563 if(!nmb
->header
.response
&& !nmb
->header
.nm_flags
.recursion_desired
) {
564 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
573 /****************************************************************************
574 Utility function to decide what ttl to give a register/refresh request.
575 *****************************************************************************/
577 static int get_ttl_from_packet(struct nmb_packet
*nmb
)
579 int ttl
= nmb
->additional
->ttl
;
581 if (ttl
< lp_min_wins_ttl()) {
582 ttl
= lp_min_wins_ttl();
585 if (ttl
> lp_max_wins_ttl()) {
586 ttl
= lp_max_wins_ttl();
592 /****************************************************************************
593 Load or create the WINS database.
594 *****************************************************************************/
596 bool initialise_wins(void)
598 time_t time_now
= time(NULL
);
602 if(!lp_we_are_a_wins_server()) {
606 /* Open the wins.tdb. */
607 wins_tdb
= tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT
|TDB_CLEAR_IF_FIRST
, O_CREAT
|O_RDWR
, 0600);
609 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
614 tdb_store_int32(wins_tdb
, "WINSDB_VERSION", WINSDB_VERSION
);
616 add_samba_names_to_subnet(wins_server_subnet
);
618 if((fp
= x_fopen(state_path(WINS_LIST
),O_RDONLY
,0)) == NULL
) {
619 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
620 WINS_LIST
, strerror(errno
) ));
624 while (!x_feof(fp
)) {
625 char *name_str
= NULL
;
627 char *ttl_str
= NULL
, *nb_flags_str
= NULL
;
628 unsigned int num_ips
;
630 struct in_addr
*ip_list
= NULL
;
641 TALLOC_CTX
*frame
= NULL
;
643 /* Read a line from the wins.dat file. Strips whitespace
644 from the beginning and end of the line. */
645 if (!fgets_slash(line
,sizeof(line
),fp
)) {
653 if (strncmp(line
,"VERSION ", 8) == 0) {
654 if (sscanf(line
,"VERSION %d %u", &version
, &hash
) != 2 ||
655 version
!= WINS_VERSION
) {
656 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line
));
666 * Now we handle multiple IP addresses per name we need
667 * to iterate over the line twice. The first time to
668 * determine how many IP addresses there are, the second
669 * time to actually parse them into the ip_list array.
672 frame
= talloc_stackframe();
673 if (!next_token_talloc(frame
,&ptr
,&name_str
,NULL
)) {
674 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line
));
679 if (!next_token_talloc(frame
,&ptr
,&ttl_str
,NULL
)) {
680 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line
));
686 * Determine the number of IP addresses per line.
690 got_token
= next_token_talloc(frame
,&ptr
,&ip_str
,NULL
);
693 if(got_token
&& strchr(ip_str
, '.')) {
697 } while(got_token
&& was_ip
);
700 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line
));
706 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line
));
711 /* Allocate the space for the ip_list. */
712 if((ip_list
= SMB_MALLOC_ARRAY( struct in_addr
, num_ips
)) == NULL
) {
713 DEBUG(0,("initialise_wins: Malloc fail !\n"));
719 /* Reset and re-parse the line. */
721 next_token_talloc(frame
,&ptr
,&name_str
,NULL
);
722 next_token_talloc(frame
,&ptr
,&ttl_str
,NULL
);
723 for(i
= 0; i
< num_ips
; i
++) {
724 next_token_talloc(frame
,&ptr
, &ip_str
, NULL
);
725 ip_list
[i
] = interpret_addr2(ip_str
);
727 next_token_talloc(frame
,&ptr
,&nb_flags_str
,NULL
);
730 * Deal with SELF or REGISTER name encoding. Default is REGISTER
731 * for compatibility with old nmbds.
734 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'S') {
735 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line
));
741 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'R') {
742 nb_flags_str
[strlen(nb_flags_str
)-1] = '\0';
745 /* Netbios name. # divides the name from the type (hex): netbios#xx */
748 if((p
= strchr(name
,'#')) != NULL
) {
750 sscanf(p
+1,"%x",&type
);
753 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
754 sscanf(nb_flags_str
,"%x",&nb_flags
);
755 sscanf(ttl_str
,"%d",&ttl
);
757 /* add all entries that have 60 seconds or more to live */
758 if ((ttl
- 60) > time_now
|| ttl
== PERMANENT_TTL
) {
759 if(ttl
!= PERMANENT_TTL
) {
763 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
764 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
766 (void)add_name_to_subnet( wins_server_subnet
, name
, type
, nb_flags
,
767 ttl
, REGISTER_NAME
, num_ips
, ip_list
);
769 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
770 "%s#%02x ttl = %d first IP %s flags = %2x\n",
771 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
782 /****************************************************************************
783 Send a WINS WACK (Wait ACKnowledgement) response.
784 **************************************************************************/
786 static void send_wins_wack_response(int ttl
, struct packet_struct
*p
)
788 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
789 unsigned char rdata
[2];
791 rdata
[0] = rdata
[1] = 0;
793 /* Taken from nmblib.c - we need to send back almost
794 identical bytes from the requesting packet header. */
796 rdata
[0] = (nmb
->header
.opcode
& 0xF) << 3;
797 if (nmb
->header
.nm_flags
.authoritative
&& nmb
->header
.response
) {
800 if (nmb
->header
.nm_flags
.trunc
) {
803 if (nmb
->header
.nm_flags
.recursion_desired
) {
806 if (nmb
->header
.nm_flags
.recursion_available
&& nmb
->header
.response
) {
809 if (nmb
->header
.nm_flags
.bcast
) {
813 reply_netbios_packet(p
, /* Packet to reply to. */
814 0, /* Result code. */
815 NMB_WAIT_ACK
, /* nmbd type code. */
816 NMB_WACK_OPCODE
, /* opcode. */
818 (char *)rdata
, /* data to send. */
819 2); /* data length. */
822 /****************************************************************************
823 Send a WINS name registration response.
824 **************************************************************************/
826 static void send_wins_name_registration_response(int rcode
, int ttl
, struct packet_struct
*p
)
828 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
831 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
833 reply_netbios_packet(p
, /* Packet to reply to. */
834 rcode
, /* Result code. */
835 WINS_REG
, /* nmbd type code. */
836 NMB_NAME_REG_OPCODE
, /* opcode. */
838 rdata
, /* data to send. */
839 6); /* data length. */
842 /***********************************************************************
843 Deal with a name refresh request to a WINS server.
844 ************************************************************************/
846 void wins_process_name_refresh_request( struct subnet_record
*subrec
,
847 struct packet_struct
*p
)
849 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
850 struct nmb_name
*question
= &nmb
->question
.question_name
;
851 bool bcast
= nmb
->header
.nm_flags
.bcast
;
852 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
853 bool group
= (nb_flags
& NB_GROUP
) ? True
: False
;
854 struct name_record
*namerec
= NULL
;
855 int ttl
= get_ttl_from_packet(nmb
);
856 struct in_addr from_ip
;
857 struct in_addr our_fake_ip
;
859 our_fake_ip
= interpret_addr2("0.0.0.0");
860 putip( (char *)&from_ip
, &nmb
->additional
->rdata
[2] );
864 * We should only get unicast name refresh packets here.
865 * Anyone trying to refresh broadcast should not be going
866 * to a WINS server. Log an error here.
868 if( DEBUGLVL( 0 ) ) {
869 dbgtext( "wins_process_name_refresh_request: " );
870 dbgtext( "Broadcast name refresh request received " );
871 dbgtext( "for name %s ", nmb_namestr(question
) );
872 dbgtext( "from IP %s ", inet_ntoa(from_ip
) );
873 dbgtext( "on subnet %s. ", subrec
->subnet_name
);
874 dbgtext( "Error - Broadcasts should not be sent " );
875 dbgtext( "to a WINS server\n" );
880 if( DEBUGLVL( 3 ) ) {
881 dbgtext( "wins_process_name_refresh_request: " );
882 dbgtext( "Name refresh for name %s IP %s\n",
883 nmb_namestr(question
), inet_ntoa(from_ip
) );
887 * See if the name already exists.
888 * If not, handle it as a name registration and return.
890 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
893 * If this is a refresh request and the name doesn't exist then
894 * treat it like a registration request. This allows us to recover
895 * from errors (tridge)
897 if(namerec
== NULL
) {
898 if( DEBUGLVL( 3 ) ) {
899 dbgtext( "wins_process_name_refresh_request: " );
900 dbgtext( "Name refresh for name %s ",
901 nmb_namestr( question
) );
902 dbgtext( "and the name does not exist. Treating " );
903 dbgtext( "as registration.\n" );
905 wins_process_name_registration_request(subrec
,p
);
910 * if the name is present but not active, simply remove it
911 * and treat the refresh request as a registration & return.
913 if (namerec
!= NULL
&& !WINS_STATE_ACTIVE(namerec
)) {
914 if( DEBUGLVL( 5 ) ) {
915 dbgtext( "wins_process_name_refresh_request: " );
916 dbgtext( "Name (%s) in WINS ", nmb_namestr(question
) );
917 dbgtext( "was not active - removing it.\n" );
919 remove_name_from_namelist( subrec
, namerec
);
921 wins_process_name_registration_request( subrec
, p
);
926 * Check that the group bits for the refreshing name and the
927 * name in our database match. If not, refuse the refresh.
928 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
930 if( (namerec
!= NULL
) &&
931 ( (group
&& !NAME_GROUP(namerec
))
932 || (!group
&& NAME_GROUP(namerec
)) ) ) {
933 if( DEBUGLVL( 3 ) ) {
934 dbgtext( "wins_process_name_refresh_request: " );
935 dbgtext( "Name %s ", nmb_namestr(question
) );
936 dbgtext( "group bit = %s does not match ",
937 group
? "True" : "False" );
938 dbgtext( "group bit in WINS for this name.\n" );
940 send_wins_name_registration_response(RFS_ERR
, 0, p
);
945 * For a unique name check that the person refreshing the name is
946 * one of the registered IP addresses. If not - fail the refresh.
947 * Do the same for group names with a type of 0x1c.
948 * Just return success for unique 0x1d refreshes. For normal group
949 * names update the ttl and return success.
951 if( (!group
|| (group
&& (question
->name_type
== 0x1c)))
952 && find_ip_in_name_record(namerec
, from_ip
) ) {
956 update_name_ttl(namerec
, ttl
);
959 * if the record is a replica:
960 * we take ownership and update the version ID.
962 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
963 update_wins_owner(namerec
, our_fake_ip
);
964 get_global_id_and_update(&namerec
->data
.id
, True
);
967 send_wins_name_registration_response(0, ttl
, p
);
968 wins_hook("refresh", namerec
, ttl
);
970 } else if((group
&& (question
->name_type
== 0x1c))) {
972 * Added by crh for bug #1079.
973 * Fix from Bert Driehuis
975 if( DEBUGLVL( 3 ) ) {
976 dbgtext( "wins_process_name_refresh_request: " );
977 dbgtext( "Name refresh for name %s, ",
978 nmb_namestr(question
) );
979 dbgtext( "but IP address %s ", inet_ntoa(from_ip
) );
980 dbgtext( "is not yet associated with " );
981 dbgtext( "that name. Treating as registration.\n" );
983 wins_process_name_registration_request(subrec
,p
);
987 * Normal groups are all registered with an IP address of
988 * 255.255.255.255 so we can't search for the IP address.
990 update_name_ttl(namerec
, ttl
);
991 wins_hook("refresh", namerec
, ttl
);
992 send_wins_name_registration_response(0, ttl
, p
);
994 } else if(!group
&& (question
->name_type
== 0x1d)) {
996 * Special name type - just pretend the refresh succeeded.
998 send_wins_name_registration_response(0, ttl
, p
);
1004 if( DEBUGLVL( 3 ) ) {
1005 dbgtext( "wins_process_name_refresh_request: " );
1006 dbgtext( "Name refresh for name %s with IP %s ",
1007 nmb_namestr(question
), inet_ntoa(from_ip
) );
1008 dbgtext( "and is IP is not known to the name.\n" );
1010 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1015 /***********************************************************************
1016 Deal with a name registration request query success to a client that
1019 We have a locked pointer to the original packet stashed away in the
1020 userdata pointer. The success here is actually a failure as it means
1021 the client we queried wants to keep the name, so we must return
1022 a registration failure to the original requestor.
1023 ************************************************************************/
1025 static void wins_register_query_success(struct subnet_record
*subrec
,
1026 struct userdata_struct
*userdata
,
1027 struct nmb_name
*question_name
,
1029 struct res_rec
*answers
)
1031 struct packet_struct
*orig_reg_packet
;
1033 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1035 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1036 name %s. Rejecting registration request.\n", inet_ntoa(ip
), nmb_namestr(question_name
) ));
1038 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1040 orig_reg_packet
->locked
= False
;
1041 free_packet(orig_reg_packet
);
1044 /***********************************************************************
1045 Deal with a name registration request query failure to a client that
1048 We have a locked pointer to the original packet stashed away in the
1049 userdata pointer. The failure here is actually a success as it means
1050 the client we queried didn't want to keep the name, so we can remove
1051 the old name record and then successfully add the new name.
1052 ************************************************************************/
1054 static void wins_register_query_fail(struct subnet_record
*subrec
,
1055 struct response_record
*rrec
,
1056 struct nmb_name
*question_name
,
1059 struct userdata_struct
*userdata
= rrec
->userdata
;
1060 struct packet_struct
*orig_reg_packet
;
1061 struct name_record
*namerec
= NULL
;
1063 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1066 * We want to just add the name, as we now know the original owner
1067 * didn't want it. But we can't just do that as an arbitary
1068 * amount of time may have taken place between the name query
1069 * request and this timeout/error response. So we check that
1070 * the name still exists and is in the same state - if so
1071 * we remove it and call wins_process_name_registration_request()
1072 * as we know it will do the right thing now.
1075 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1077 if ((namerec
!= NULL
) && (namerec
->data
.source
== REGISTER_NAME
) &&
1078 ip_equal_v4(rrec
->packet
->ip
, *namerec
->data
.ip
)) {
1079 remove_name_from_namelist( subrec
, namerec
);
1083 if(namerec
== NULL
) {
1084 wins_process_name_registration_request(subrec
, orig_reg_packet
);
1086 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1087 "querying for name %s in order to replace it and this reply.\n",
1088 nmb_namestr(question_name
) ));
1091 orig_reg_packet
->locked
= False
;
1092 free_packet(orig_reg_packet
);
1095 /***********************************************************************
1096 Deal with a name registration request to a WINS server.
1098 Use the following pseudocode :
1103 +--------name exists
1106 | +--- existing name is group
1109 | | +--- add name (return).
1112 | +--- exiting name is unique
1115 | +--- query existing owner (return).
1118 +--------name doesn't exist
1121 +--- add name (return).
1126 +--------name exists
1129 | +--- existing name is group
1132 | | +--- fail add (return).
1135 | +--- exiting name is unique
1138 | +--- query existing owner (return).
1141 +--------name doesn't exist
1144 +--- add name (return).
1146 As can be seen from the above, the two cases may be collapsed onto each
1147 other with the exception of the case where the name already exists and
1148 is a group name. This case we handle with an if statement.
1150 ************************************************************************/
1152 void wins_process_name_registration_request(struct subnet_record
*subrec
,
1153 struct packet_struct
*p
)
1156 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1157 struct nmb_name
*question
= &nmb
->question
.question_name
;
1158 bool bcast
= nmb
->header
.nm_flags
.bcast
;
1159 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1160 int ttl
= get_ttl_from_packet(nmb
);
1161 struct name_record
*namerec
= NULL
;
1162 struct in_addr from_ip
;
1163 bool registering_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;
1164 struct in_addr our_fake_ip
;
1166 our_fake_ip
= interpret_addr2("0.0.0.0");
1167 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1171 * We should only get unicast name registration packets here.
1172 * Anyone trying to register broadcast should not be going to a WINS
1173 * server. Log an error here.
1176 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1177 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1178 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1182 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1183 IP %s\n", registering_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1186 * See if the name already exists.
1189 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1192 * if the record exists but NOT in active state,
1195 if ( (namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1196 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1197 not active - removing it.\n", nmb_namestr(question
) ));
1198 remove_name_from_namelist( subrec
, namerec
);
1203 * Deal with the case where the name found was a dns entry.
1204 * Remove it as we now have a NetBIOS client registering the
1208 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1209 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1210 a dns lookup - removing it.\n", nmb_namestr(question
) ));
1211 remove_name_from_namelist( subrec
, namerec
);
1216 * Reject if the name exists and is not a REGISTER_NAME.
1217 * (ie. Don't allow any static names to be overwritten.
1220 if((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) {
1221 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1222 to register name %s. Name already exists in WINS with source type %d.\n",
1223 nmb_namestr(question
), namerec
->data
.source
));
1224 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1229 * Special policy decisions based on MS documentation.
1230 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1231 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1235 * A group name is always added as the local broadcast address, except
1236 * for group names ending in 0x1c.
1237 * Group names with type 0x1c are registered with individual IP addresses.
1240 if(registering_group_name
&& (question
->name_type
!= 0x1c)) {
1241 from_ip
= interpret_addr2("255.255.255.255");
1245 * Ignore all attempts to register a unique 0x1d name, although return success.
1248 if(!registering_group_name
&& (question
->name_type
== 0x1d)) {
1249 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1250 to register name %s from IP %s.\n", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1251 send_wins_name_registration_response(0, ttl
, p
);
1256 * Next two cases are the 'if statement' mentioned above.
1259 if((namerec
!= NULL
) && NAME_GROUP(namerec
)) {
1260 if(registering_group_name
) {
1262 * If we are adding a group name, the name exists and is also a group entry just add this
1263 * IP address to it and update the ttl.
1266 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1267 inet_ntoa(from_ip
), nmb_namestr(question
) ));
1270 * Check the ip address is not already in the group.
1273 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1275 * Need to emulate the behaviour of Windows, as
1277 * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1278 * (is there an MS reference for this
1279 * somewhere?) because if the 1c list gets over
1280 * 86 entries, the reply packet is too big
1281 * (rdata>576 bytes) so no reply is sent.
1283 * Keep only the "latest" 25 records, while
1284 * ensuring that the PDC (0x1b) is never removed
1285 * We do this by removing the first entry that
1286 * isn't the 1b entry for the same name,
1287 * on the grounds that insertion is at the end
1288 * of the list, so the oldest entries are at
1292 while(namerec
->data
.num_ips
>=25) {
1293 struct name_record
*name1brec
= NULL
;
1295 /* We only do this for 1c types. */
1296 if (namerec
->name
.name_type
!= 0x1c) {
1299 DEBUG(3,("wins_process_name_registration_request: "
1300 "More than 25 IPs already in "
1301 "the list. Looking for a 1b "
1304 /* Ensure we have all the active 1b
1305 * names on the list. */
1306 wins_delete_all_1b_in_memory_records();
1307 fetch_all_active_wins_1b_names();
1309 /* Per the above, find the 1b record,
1310 and then remove the first IP that isn't the same */
1311 for(name1brec
= subrec
->namelist
;
1313 name1brec
= name1brec
->next
) {
1314 if( WINS_STATE_ACTIVE(name1brec
) &&
1315 name1brec
->name
.name_type
== 0x1b) {
1316 DEBUG(3,("wins_process_name_registration_request: "
1317 "Found the #1b record "
1319 inet_ntoa(name1brec
->data
.ip
[0])));
1324 DEBUG(3,("wins_process_name_registration_request: "
1325 "Didn't find a #1b name record. "
1326 "Removing the first available "
1328 inet_ntoa(namerec
->data
.ip
[0])));
1329 remove_ip_from_name_record(namerec
, namerec
->data
.ip
[0]);
1330 wins_hook("delete", namerec
, 0);
1333 for(i
=0; i
<namerec
->data
.num_ips
; i
++) {
1334 /* The name1brec should only have
1335 * the single IP address in it,
1336 * so we only check against the first one*/
1337 if(!ip_equal_v4( namerec
->data
.ip
[i
], name1brec
->data
.ip
[0])) {
1338 /* The i'th entry isn't the 1b address; delete it */
1339 DEBUG(3,("wins_process_name_registration_request: "
1340 "Entry at %d is not the #1b address. "
1341 "About to remove it\n",
1343 remove_ip_from_name_record(namerec
, namerec
->data
.ip
[i
]);
1344 wins_hook("delete", namerec
, 0);
1350 /* The list is guaranteed to be < 25 entries now
1351 * - safe to add a new one */
1352 add_ip_to_name_record(namerec
, from_ip
);
1353 /* we need to update the record for replication */
1354 get_global_id_and_update(&namerec
->data
.id
, True
);
1357 * if the record is a replica, we must change
1358 * the wins owner to us to make the replication updates
1359 * it on the other wins servers.
1360 * And when the partner will receive this record,
1361 * it will update its own record.
1364 update_wins_owner(namerec
, our_fake_ip
);
1366 update_name_ttl(namerec
, ttl
);
1367 wins_hook("refresh", namerec
, ttl
);
1368 send_wins_name_registration_response(0, ttl
, p
);
1373 * If we are adding a unique name, the name exists in the WINS db
1374 * and is a group name then reject the registration.
1376 * explanation: groups have a higher priority than unique names.
1379 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1380 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1381 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1387 * From here on down we know that if the name exists in the WINS db it is
1388 * a unique name, not a group name.
1392 * If the name exists and is one of our names then check the
1393 * registering IP address. If it's not one of ours then automatically
1394 * reject without doing the query - we know we will reject it.
1397 if ( namerec
!= NULL
) {
1398 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
1399 if( is_myname(name
) ) {
1400 if(!ismyip_v4(from_ip
)) {
1401 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1402 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1403 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1407 * It's one of our names and one of our IP's - update the ttl.
1409 update_name_ttl(namerec
, ttl
);
1410 wins_hook("refresh", namerec
, ttl
);
1411 send_wins_name_registration_response(0, ttl
, p
);
1420 * If the name exists and it is a unique registration and the registering IP
1421 * is the same as the (single) already registered IP then just update the ttl.
1423 * But not if the record is an active replica. IF it's a replica, it means it can be
1424 * the same client which has moved and not yet expired. So we don't update
1425 * the ttl in this case and go beyond to do a WACK and query the old client
1428 if( !registering_group_name
1429 && (namerec
!= NULL
)
1430 && (namerec
->data
.num_ips
== 1)
1431 && ip_equal_v4( namerec
->data
.ip
[0], from_ip
)
1432 && ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
) ) {
1433 update_name_ttl( namerec
, ttl
);
1434 wins_hook("refresh", namerec
, ttl
);
1435 send_wins_name_registration_response( 0, ttl
, p
);
1440 * Finally if the name exists do a query to the registering machine
1441 * to see if they still claim to have the name.
1444 if( namerec
!= NULL
) {
1445 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1446 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1449 * First send a WACK to the registering machine.
1452 send_wins_wack_response(60, p
);
1455 * When the reply comes back we need the original packet.
1456 * Lock this so it won't be freed and then put it into
1457 * the userdata structure.
1462 userdata
= (struct userdata_struct
*)ud
;
1464 userdata
->copy_fn
= NULL
;
1465 userdata
->free_fn
= NULL
;
1466 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1467 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1470 * Use the new call to send a query directly to an IP address.
1471 * This sends the query directly to the IP address, and ensures
1472 * the recursion desired flag is not set (you were right Luke :-).
1473 * This function should *only* be called from the WINS server
1477 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1478 query_name_from_wins_server( *namerec
->data
.ip
,
1480 question
->name_type
,
1481 wins_register_query_success
,
1482 wins_register_query_fail
,
1488 * Name did not exist - add it.
1491 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1492 add_name_to_subnet( subrec
, name
, question
->name_type
,
1493 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1495 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1496 get_global_id_and_update(&namerec
->data
.id
, True
);
1497 update_wins_owner(namerec
, our_fake_ip
);
1498 update_wins_flag(namerec
, WINS_ACTIVE
);
1499 wins_hook("add", namerec
, ttl
);
1502 send_wins_name_registration_response(0, ttl
, p
);
1505 /***********************************************************************
1506 Deal with a mutihomed name query success to the machine that
1507 requested the multihomed name registration.
1509 We have a locked pointer to the original packet stashed away in the
1511 ************************************************************************/
1513 static void wins_multihomed_register_query_success(struct subnet_record
*subrec
,
1514 struct userdata_struct
*userdata
,
1515 struct nmb_name
*question_name
,
1517 struct res_rec
*answers
)
1519 struct packet_struct
*orig_reg_packet
;
1520 struct nmb_packet
*nmb
;
1521 struct name_record
*namerec
= NULL
;
1522 struct in_addr from_ip
;
1524 struct in_addr our_fake_ip
;
1526 our_fake_ip
= interpret_addr2("0.0.0.0");
1527 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1529 nmb
= &orig_reg_packet
->packet
.nmb
;
1531 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1532 ttl
= get_ttl_from_packet(nmb
);
1535 * We want to just add the new IP, as we now know the requesting
1536 * machine claims to own it. But we can't just do that as an arbitary
1537 * amount of time may have taken place between the name query
1538 * request and this response. So we check that
1539 * the name still exists and is in the same state - if so
1540 * we just add the extra IP and update the ttl.
1543 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1545 if( (namerec
== NULL
) || (namerec
->data
.source
!= REGISTER_NAME
) || !WINS_STATE_ACTIVE(namerec
) ) {
1546 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1547 a subsequent IP address.\n", nmb_namestr(question_name
) ));
1548 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1550 orig_reg_packet
->locked
= False
;
1551 free_packet(orig_reg_packet
);
1556 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1557 add_ip_to_name_record(namerec
, from_ip
);
1560 get_global_id_and_update(&namerec
->data
.id
, True
);
1561 update_wins_owner(namerec
, our_fake_ip
);
1562 update_wins_flag(namerec
, WINS_ACTIVE
);
1563 update_name_ttl(namerec
, ttl
);
1564 wins_hook("add", namerec
, ttl
);
1565 send_wins_name_registration_response(0, ttl
, orig_reg_packet
);
1567 orig_reg_packet
->locked
= False
;
1568 free_packet(orig_reg_packet
);
1571 /***********************************************************************
1572 Deal with a name registration request query failure to a client that
1575 We have a locked pointer to the original packet stashed away in the
1577 ************************************************************************/
1579 static void wins_multihomed_register_query_fail(struct subnet_record
*subrec
,
1580 struct response_record
*rrec
,
1581 struct nmb_name
*question_name
,
1584 struct userdata_struct
*userdata
= rrec
->userdata
;
1585 struct packet_struct
*orig_reg_packet
;
1587 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1589 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1590 query successfully for name %s.\n", inet_ntoa(orig_reg_packet
->ip
), nmb_namestr(question_name
) ));
1591 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1593 orig_reg_packet
->locked
= False
;
1594 free_packet(orig_reg_packet
);
1598 /***********************************************************************
1599 Deal with a multihomed name registration request to a WINS server.
1600 These cannot be group name registrations.
1601 ***********************************************************************/
1603 void wins_process_multihomed_name_registration_request( struct subnet_record
*subrec
,
1604 struct packet_struct
*p
)
1606 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1607 struct nmb_name
*question
= &nmb
->question
.question_name
;
1608 bool bcast
= nmb
->header
.nm_flags
.bcast
;
1609 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1610 int ttl
= get_ttl_from_packet(nmb
);
1611 struct name_record
*namerec
= NULL
;
1612 struct in_addr from_ip
;
1613 bool group
= (nb_flags
& NB_GROUP
) ? True
: False
;
1614 struct in_addr our_fake_ip
;
1617 our_fake_ip
= interpret_addr2("0.0.0.0");
1618 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1622 * We should only get unicast name registration packets here.
1623 * Anyone trying to register broadcast should not be going to a WINS
1624 * server. Log an error here.
1627 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1628 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1629 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1634 * Only unique names should be registered multihomed.
1638 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1639 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1640 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1644 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1645 IP %s\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1648 * Deal with policy regarding 0x1d names.
1651 if(question
->name_type
== 0x1d) {
1652 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1653 to register name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1654 send_wins_name_registration_response(0, ttl
, p
);
1659 * See if the name already exists.
1662 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1665 * if the record exists but NOT in active state,
1669 if ((namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1670 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question
)));
1671 remove_name_from_namelist(subrec
, namerec
);
1676 * Deal with the case where the name found was a dns entry.
1677 * Remove it as we now have a NetBIOS client registering the
1681 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1682 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1683 - removing it.\n", nmb_namestr(question
) ));
1684 remove_name_from_namelist( subrec
, namerec
);
1689 * Reject if the name exists and is not a REGISTER_NAME.
1690 * (ie. Don't allow any static names to be overwritten.
1693 if( (namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
) ) {
1694 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1695 to register name %s. Name already exists in WINS with source type %d.\n",
1696 nmb_namestr(question
), namerec
->data
.source
));
1697 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1702 * Reject if the name exists and is a GROUP name and is active.
1705 if((namerec
!= NULL
) && NAME_GROUP(namerec
) && WINS_STATE_ACTIVE(namerec
)) {
1706 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1707 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1708 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1713 * From here on down we know that if the name exists in the WINS db it is
1714 * a unique name, not a group name.
1718 * If the name exists and is one of our names then check the
1719 * registering IP address. If it's not one of ours then automatically
1720 * reject without doing the query - we know we will reject it.
1723 if((namerec
!= NULL
) && (is_myname(namerec
->name
.name
)) ) {
1724 if(!ismyip_v4(from_ip
)) {
1725 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1726 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1727 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1731 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1732 * update the ttl. Update the version ID to force replication.
1734 update_name_ttl(namerec
, ttl
);
1736 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1737 get_global_id_and_update(&namerec
->data
.id
, True
);
1738 update_wins_owner(namerec
, our_fake_ip
);
1739 update_wins_flag(namerec
, WINS_ACTIVE
);
1741 add_ip_to_name_record(namerec
, from_ip
);
1744 wins_hook("refresh", namerec
, ttl
);
1745 send_wins_name_registration_response(0, ttl
, p
);
1751 * If the name exists and is active, check if the IP address is already registered
1752 * to that name. If so then update the ttl and reply success.
1755 if((namerec
!= NULL
) && find_ip_in_name_record(namerec
, from_ip
) && WINS_STATE_ACTIVE(namerec
)) {
1756 update_name_ttl(namerec
, ttl
);
1759 * If it's a replica, we need to become the wins owner
1760 * to force the replication
1762 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
1763 get_global_id_and_update(&namerec
->data
.id
, True
);
1764 update_wins_owner(namerec
, our_fake_ip
);
1765 update_wins_flag(namerec
, WINS_ACTIVE
);
1768 wins_hook("refresh", namerec
, ttl
);
1769 send_wins_name_registration_response(0, ttl
, p
);
1774 * If the name exists do a query to the owner
1775 * to see if they still want the name.
1778 if(namerec
!= NULL
) {
1779 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1780 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1783 * First send a WACK to the registering machine.
1786 send_wins_wack_response(60, p
);
1789 * When the reply comes back we need the original packet.
1790 * Lock this so it won't be freed and then put it into
1791 * the userdata structure.
1796 userdata
= (struct userdata_struct
*)ud
;
1798 userdata
->copy_fn
= NULL
;
1799 userdata
->free_fn
= NULL
;
1800 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1801 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1804 * Use the new call to send a query directly to an IP address.
1805 * This sends the query directly to the IP address, and ensures
1806 * the recursion desired flag is not set (you were right Luke :-).
1807 * This function should *only* be called from the WINS server
1810 * Note that this packet is sent to the current owner of the name,
1811 * not the person who sent the packet
1814 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1815 query_name_from_wins_server( namerec
->data
.ip
[0],
1817 question
->name_type
,
1818 wins_multihomed_register_query_success
,
1819 wins_multihomed_register_query_fail
,
1826 * Name did not exist - add it.
1829 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1830 add_name_to_subnet( subrec
, qname
, question
->name_type
,
1831 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1833 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1834 get_global_id_and_update(&namerec
->data
.id
, True
);
1835 update_wins_owner(namerec
, our_fake_ip
);
1836 update_wins_flag(namerec
, WINS_ACTIVE
);
1837 wins_hook("add", namerec
, ttl
);
1840 send_wins_name_registration_response(0, ttl
, p
);
1843 /***********************************************************************
1844 Fetch all *<1b> names from the WINS db and store on the namelist.
1845 ***********************************************************************/
1847 static int fetch_1b_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
1849 struct name_record
*namerec
= NULL
;
1851 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
1855 /* Filter out all non-1b names. */
1856 if (kbuf
.dptr
[sizeof(unstring
)] != 0x1b) {
1860 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
1865 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
1869 void fetch_all_active_wins_1b_names(void)
1871 tdb_traverse(wins_tdb
, fetch_1b_traverse_fn
, NULL
);
1874 /***********************************************************************
1875 Deal with the special name query for *<1b>.
1876 ***********************************************************************/
1878 static void process_wins_dmb_query_request(struct subnet_record
*subrec
,
1879 struct packet_struct
*p
)
1881 struct name_record
*namerec
= NULL
;
1886 * Go through all the ACTIVE names in the WINS db looking for those
1887 * ending in <1b>. Use this to calculate the number of IP
1888 * addresses we need to return.
1893 /* First, clear the in memory list - we're going to re-populate
1894 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1896 wins_delete_all_tmp_in_memory_records();
1898 fetch_all_active_wins_1b_names();
1900 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1901 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1902 num_ips
+= namerec
->data
.num_ips
;
1908 * There are no 0x1b names registered. Return name query fail.
1910 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1914 if((prdata
= (char *)SMB_MALLOC( num_ips
* 6 )) == NULL
) {
1915 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1920 * Go through all the names again in the WINS db looking for those
1921 * ending in <1b>. Add their IP addresses into the list we will
1926 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1927 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1929 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1930 set_nb_flags(&prdata
[num_ips
* 6],namerec
->data
.nb_flags
);
1931 putip((char *)&prdata
[(num_ips
* 6) + 2], &namerec
->data
.ip
[i
]);
1938 * Send back the reply containing the IP list.
1941 reply_netbios_packet(p
, /* Packet to reply to. */
1942 0, /* Result code. */
1943 WINS_QUERY
, /* nmbd type code. */
1944 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1945 lp_min_wins_ttl(), /* ttl. */
1946 prdata
, /* data to send. */
1947 num_ips
*6); /* data length. */
1952 /****************************************************************************
1953 Send a WINS name query response.
1954 **************************************************************************/
1956 void send_wins_name_query_response(int rcode
, struct packet_struct
*p
,
1957 struct name_record
*namerec
)
1960 char *prdata
= rdata
;
1961 int reply_data_len
= 0;
1965 memset(rdata
,'\0',6);
1971 ttl
= (namerec
->data
.death_time
!= PERMANENT_TTL
) ? namerec
->data
.death_time
- p
->timestamp
: lp_max_wins_ttl();
1973 /* The netbios reply packet data section is limited to 576 bytes. In theory
1974 * this should give us space for 96 addresses, but in practice, 86 appears
1975 * to be the max (don't know why). If we send any more than that,
1976 * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
1977 * overflow. Keep the count to 85 and it will be ok */
1978 ip_count
=namerec
->data
.num_ips
;
1983 /* Copy all known ip addresses into the return data. */
1984 /* Optimise for the common case of one IP address so we don't need a malloc. */
1986 if( ip_count
== 1 ) {
1989 if((prdata
= (char *)SMB_MALLOC( ip_count
* 6 )) == NULL
) {
1990 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1995 for(i
= 0; i
< ip_count
; i
++) {
1996 set_nb_flags(&prdata
[i
*6],namerec
->data
.nb_flags
);
1997 putip((char *)&prdata
[2+(i
*6)], &namerec
->data
.ip
[i
]);
2000 sort_query_replies(prdata
, i
, p
->ip
);
2001 reply_data_len
= ip_count
* 6;
2004 reply_netbios_packet(p
, /* Packet to reply to. */
2005 rcode
, /* Result code. */
2006 WINS_QUERY
, /* nmbd type code. */
2007 NMB_NAME_QUERY_OPCODE
, /* opcode. */
2009 prdata
, /* data to send. */
2010 reply_data_len
); /* data length. */
2012 if(prdata
!= rdata
) {
2017 /***********************************************************************
2018 Deal with a name query.
2019 ***********************************************************************/
2021 void wins_process_name_query_request(struct subnet_record
*subrec
,
2022 struct packet_struct
*p
)
2024 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2025 struct nmb_name
*question
= &nmb
->question
.question_name
;
2026 struct name_record
*namerec
= NULL
;
2029 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
2030 nmb_namestr(question
), inet_ntoa(p
->ip
) ));
2033 * Special name code. If the queried name is *<1b> then search
2034 * the entire WINS database and return a list of all the IP addresses
2035 * registered to any <1b> name. This is to allow domain master browsers
2036 * to discover other domains that may not have a presence on their subnet.
2039 pull_ascii_nstring(qname
, sizeof(qname
), question
->name
);
2040 if(strequal( qname
, "*") && (question
->name_type
== 0x1b)) {
2041 process_wins_dmb_query_request( subrec
, p
);
2045 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
2047 if(namerec
!= NULL
) {
2049 * If the name is not anymore in active state then reply not found.
2050 * it's fair even if we keep it in the cache for days.
2052 if (!WINS_STATE_ACTIVE(namerec
)) {
2053 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2054 nmb_namestr(question
) ));
2055 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2060 * If it's a DNSFAIL_NAME then reply name not found.
2063 if( namerec
->data
.source
== DNSFAIL_NAME
) {
2064 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2065 nmb_namestr(question
) ));
2066 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2071 * If the name has expired then reply name not found.
2074 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< p
->timestamp
) ) {
2075 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2076 nmb_namestr(question
) ));
2077 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2081 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2082 nmb_namestr(question
), inet_ntoa(namerec
->data
.ip
[0]) ));
2084 send_wins_name_query_response(0, p
, namerec
);
2089 * Name not found in WINS - try a dns query if it's a 0x20 name.
2092 if(lp_dns_proxy() && ((question
->name_type
== 0x20) || question
->name_type
== 0)) {
2093 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2094 nmb_namestr(question
) ));
2096 queue_dns_query(p
, question
);
2101 * Name not found - return error.
2104 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
2107 /****************************************************************************
2108 Send a WINS name release response.
2109 **************************************************************************/
2111 static void send_wins_name_release_response(int rcode
, struct packet_struct
*p
)
2113 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2116 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
2118 reply_netbios_packet(p
, /* Packet to reply to. */
2119 rcode
, /* Result code. */
2120 NMB_REL
, /* nmbd type code. */
2121 NMB_NAME_RELEASE_OPCODE
, /* opcode. */
2123 rdata
, /* data to send. */
2124 6); /* data length. */
2127 /***********************************************************************
2128 Deal with a name release.
2129 ***********************************************************************/
2131 void wins_process_name_release_request(struct subnet_record
*subrec
,
2132 struct packet_struct
*p
)
2134 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2135 struct nmb_name
*question
= &nmb
->question
.question_name
;
2136 bool bcast
= nmb
->header
.nm_flags
.bcast
;
2137 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
2138 struct name_record
*namerec
= NULL
;
2139 struct in_addr from_ip
;
2140 bool releasing_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;;
2142 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
2146 * We should only get unicast name registration packets here.
2147 * Anyone trying to register broadcast should not be going to a WINS
2148 * server. Log an error here.
2151 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2152 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2153 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
2157 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2158 IP %s\n", releasing_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
2161 * Deal with policy regarding 0x1d names.
2164 if(!releasing_group_name
&& (question
->name_type
== 0x1d)) {
2165 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2166 to release name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
2167 send_wins_name_release_response(0, p
);
2172 * See if the name already exists.
2175 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
2177 if( (namerec
== NULL
) || ((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) ) {
2178 send_wins_name_release_response(NAM_ERR
, p
);
2183 * Check that the sending machine has permission to release this name.
2184 * If it's a group name not ending in 0x1c then just say yes and let
2185 * the group time out.
2188 if(releasing_group_name
&& (question
->name_type
!= 0x1c)) {
2189 send_wins_name_release_response(0, p
);
2194 * Check that the releasing node is on the list of IP addresses
2195 * for this name. Disallow the release if not.
2198 if(!find_ip_in_name_record(namerec
, from_ip
)) {
2199 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2200 release name %s as IP %s is not one of the known IP's for this name.\n",
2201 nmb_namestr(question
), inet_ntoa(from_ip
) ));
2202 send_wins_name_release_response(NAM_ERR
, p
);
2207 * Check if the record is active. IF it's already released
2208 * or tombstoned, refuse the release.
2211 if (!WINS_STATE_ACTIVE(namerec
)) {
2212 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2213 release name %s as this record is not active anymore.\n", nmb_namestr(question
) ));
2214 send_wins_name_release_response(NAM_ERR
, p
);
2219 * Check if the record is a 0x1c group
2220 * and has more then one ip
2221 * remove only this address.
2224 if(releasing_group_name
&& (question
->name_type
== 0x1c) && (namerec
->data
.num_ips
> 1)) {
2225 remove_ip_from_name_record(namerec
, from_ip
);
2226 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2227 inet_ntoa(from_ip
),nmb_namestr(question
)));
2228 wins_hook("delete", namerec
, 0);
2229 send_wins_name_release_response(0, p
);
2234 * Send a release response.
2235 * Flag the name as released and update the ttl
2238 namerec
->data
.wins_flags
|= WINS_RELEASED
;
2239 update_name_ttl(namerec
, EXTINCTION_INTERVAL
);
2241 wins_hook("delete", namerec
, 0);
2242 send_wins_name_release_response(0, p
);
2245 /*******************************************************************
2246 WINS time dependent processing.
2247 ******************************************************************/
2249 static int wins_processing_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2251 time_t t
= *(time_t *)state
;
2252 bool store_record
= False
;
2253 struct name_record
*namerec
= NULL
;
2254 struct in_addr our_fake_ip
;
2256 our_fake_ip
= interpret_addr2("0.0.0.0");
2257 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2261 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2266 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< t
) ) {
2267 if( namerec
->data
.source
== SELF_NAME
) {
2268 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2269 wins_server_subnet
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
2270 namerec
->data
.death_time
+= 300;
2271 store_record
= True
;
2273 } else if (namerec
->data
.source
== DNS_NAME
|| namerec
->data
.source
== DNSFAIL_NAME
) {
2274 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2275 nmb_namestr(&namerec
->name
)));
2276 remove_name_from_wins_namelist(namerec
);
2280 /* handle records, samba is the wins owner */
2281 if (ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
2282 switch (namerec
->data
.wins_flags
& WINS_STATE_MASK
) {
2284 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2285 namerec
->data
.wins_flags
|=WINS_RELEASED
;
2286 namerec
->data
.death_time
= t
+ EXTINCTION_INTERVAL
;
2287 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2288 nmb_namestr(&namerec
->name
)));
2289 store_record
= True
;
2292 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2293 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2294 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2295 get_global_id_and_update(&namerec
->data
.id
, True
);
2296 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2297 nmb_namestr(&namerec
->name
)));
2298 store_record
= True
;
2300 case WINS_TOMBSTONED
:
2301 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2302 nmb_namestr(&namerec
->name
)));
2303 remove_name_from_wins_namelist(namerec
);
2307 switch (namerec
->data
.wins_flags
& WINS_STATE_MASK
) {
2309 /* that's not as MS says it should be */
2310 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2311 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2312 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2313 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2314 nmb_namestr(&namerec
->name
)));
2315 store_record
= True
;
2317 case WINS_TOMBSTONED
:
2318 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2319 nmb_namestr(&namerec
->name
)));
2320 remove_name_from_wins_namelist(namerec
);
2323 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2324 we are not the wins owner !\n", nmb_namestr(&namerec
->name
)));
2333 wins_store_changed_namerec(namerec
);
2336 SAFE_FREE(namerec
->data
.ip
);
2342 /*******************************************************************
2343 Time dependent wins processing.
2344 ******************************************************************/
2346 void initiate_wins_processing(time_t t
)
2348 static time_t lasttime
= 0;
2353 if (t
- lasttime
< 20) {
2357 if(!lp_we_are_a_wins_server()) {
2362 tdb_traverse(wins_tdb
, wins_processing_traverse_fn
, &t
);
2364 wins_delete_all_tmp_in_memory_records();
2366 wins_write_database(t
, True
);
2371 /*******************************************************************
2372 Write out one record.
2373 ******************************************************************/
2375 void wins_write_name_record(struct name_record
*namerec
, XFILE
*fp
)
2380 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec
->name
) ));
2382 if( namerec
->data
.death_time
!= PERMANENT_TTL
) {
2385 tm
= localtime(&namerec
->data
.death_time
);
2393 nl
= strrchr( ts
, '\n' );
2397 DEBUGADD(4,("TTL = %s ", ts
));
2399 DEBUGADD(4,("TTL = PERMANENT "));
2402 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
2403 DEBUGADD(4,("%15s ", inet_ntoa(namerec
->data
.ip
[i
]) ));
2405 DEBUGADD(4,("%2x\n", namerec
->data
.nb_flags
));
2407 if( namerec
->data
.source
== REGISTER_NAME
) {
2409 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
2410 x_fprintf(fp
, "\"%s#%02x\" %d ", name
,namerec
->name
.name_type
, /* Ignore scope. */
2411 (int)namerec
->data
.death_time
);
2413 for (i
= 0; i
< namerec
->data
.num_ips
; i
++)
2414 x_fprintf( fp
, "%s ", inet_ntoa( namerec
->data
.ip
[i
] ) );
2415 x_fprintf( fp
, "%2xR\n", namerec
->data
.nb_flags
);
2419 /*******************************************************************
2420 Write out the current WINS database.
2421 ******************************************************************/
2423 static int wins_writedb_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2425 struct name_record
*namerec
= NULL
;
2426 XFILE
*fp
= (XFILE
*)state
;
2428 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2432 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2437 wins_write_name_record(namerec
, fp
);
2439 SAFE_FREE(namerec
->data
.ip
);
2445 void wins_write_database(time_t t
, bool background
)
2447 static time_t last_write_time
= 0;
2449 char *fnamenew
= NULL
;
2454 if (!last_write_time
) {
2455 last_write_time
= t
;
2457 if (t
- last_write_time
< 120) {
2463 if(!lp_we_are_a_wins_server()) {
2467 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2473 if (tdb_reopen(wins_tdb
)) {
2474 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2481 if (!(fname
= state_path(WINS_LIST
))) {
2484 /* This is safe as the 0 length means "don't expand". */
2485 all_string_sub(fname
,"//", "/", 0);
2487 if (asprintf(&fnamenew
, "%s.%u", fname
, (unsigned int)sys_getpid()) < 0) {
2491 if((fp
= x_fopen(fnamenew
,O_WRONLY
|O_CREAT
,0644)) == NULL
) {
2492 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew
, strerror(errno
)));
2496 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2498 x_fprintf(fp
,"VERSION %d %u\n", WINS_VERSION
, 0);
2500 tdb_traverse(wins_tdb
, wins_writedb_traverse_fn
, fp
);
2503 chmod(fnamenew
,0644);
2505 rename(fnamenew
,fname
);
2509 SAFE_FREE(fnamenew
);
2518 Until winsrepl is done
.
2519 /****************************************************************************
2520 Process a internal Samba message receiving a wins record.
2521 ***************************************************************************/
2523 void nmbd_wins_new_entry(struct messaging_context
*msg
,
2526 struct server_id server_id
,
2529 WINS_RECORD
*record
;
2530 struct name_record
*namerec
= NULL
;
2531 struct name_record
*new_namerec
= NULL
;
2532 struct nmb_name question
;
2533 bool overwrite
=False
;
2534 struct in_addr our_fake_ip
;
2537 our_fake_ip
= interpret_addr2("0.0.0.0");
2542 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2543 record
=(WINS_RECORD
*)buf
;
2545 make_nmb_name(&question
, record
->name
, record
->type
);
2547 namerec
= find_name_on_subnet(wins_server_subnet
, &question
, FIND_ANY_NAME
);
2549 /* record doesn't exist, add it */
2550 if (namerec
== NULL
) {
2551 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2552 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2554 new_namerec
=add_name_to_subnet( wins_server_subnet
,
2558 EXTINCTION_INTERVAL
,
2563 if (new_namerec
!=NULL
) {
2564 update_wins_owner(new_namerec
, record
->wins_ip
);
2565 update_wins_flag(new_namerec
, record
->wins_flags
);
2566 new_namerec
->data
.id
=record
->id
;
2568 wins_server_subnet
->namelist_changed
= True
;
2572 /* check if we have a conflict */
2573 if (namerec
!= NULL
) {
2574 /* both records are UNIQUE */
2575 if (namerec
->data
.wins_flags
&WINS_UNIQUE
&& record
->wins_flags
&WINS_UNIQUE
) {
2577 /* the database record is a replica */
2578 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
2579 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
) {
2580 if (ip_equal_v4(namerec
->data
.wins_ip
, record
->wins_ip
))
2585 /* we are the wins owner of the database record */
2586 /* the 2 records have the same IP address */
2587 if (ip_equal_v4(namerec
->data
.ip
[0], record
->ip
[0])) {
2588 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
)
2589 get_global_id_and_update(&namerec
->data
.id
, True
);
2594 /* the 2 records have different IP address */
2595 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2596 if (record
->wins_flags
&WINS_TOMBSTONED
)
2597 get_global_id_and_update(&namerec
->data
.id
, True
);
2598 if (record
->wins_flags
&WINS_ACTIVE
)
2599 /* send conflict challenge to the replica node */
2608 /* the replica is a standard group */
2609 if (record
->wins_flags
&WINS_NGROUP
|| record
->wins_flags
&WINS_SGROUP
) {
2610 /* if the database record is unique and active force a name release */
2611 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2612 /* send a release name to the unique node */
2618 /* the replica is a special group */
2619 if (record
->wins_flags
&WINS_SGROUP
&& namerec
->data
.wins_flags
&WINS_SGROUP
) {
2620 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2621 for (i
=0; i
<record
->num_ips
; i
++)
2622 if(!find_ip_in_name_record(namerec
, record
->ip
[i
]))
2623 add_ip_to_name_record(namerec
, record
->ip
[i
]);
2629 /* the replica is a multihomed host */
2631 /* I'm giving up on multi homed. Too much complex to understand */
2633 if (record
->wins_flags
&WINS_MHOMED
) {
2634 if (! (namerec
->data
.wins_flags
&WINS_ACTIVE
)) {
2635 if ( !(namerec
->data
.wins_flags
&WINS_RELEASED
) && !(namerec
->data
.wins_flags
&WINS_NGROUP
))
2639 if (ip_equal_v4(record
->wins_ip
, namerec
->data
.wins_ip
))
2642 if (ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
))
2643 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2644 get_global_id_and_update(&namerec
->data
.id
, True
);
2648 if (record
->wins_flags
&WINS_ACTIVE
&& namerec
->data
.wins_flags
&WINS_ACTIVE
)
2649 if (namerec
->data
.wins_flags
&WINS_UNIQUE
||
2650 namerec
->data
.wins_flags
&WINS_MHOMED
)
2651 if (ip_equal_v4(record
->wins_ip
, namerec
->data
.wins_ip
))
2656 if (overwrite
== False
)
2657 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2658 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2660 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2661 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2663 /* remove the old record and add a new one */
2664 remove_name_from_namelist( wins_server_subnet
, namerec
);
2665 new_namerec
=add_name_to_subnet( wins_server_subnet
, record
->name
, record
->type
, record
->nb_flags
,
2666 EXTINCTION_INTERVAL
, REGISTER_NAME
, record
->num_ips
, record
->ip
);
2667 if (new_namerec
!=NULL
) {
2668 update_wins_owner(new_namerec
, record
->wins_ip
);
2669 update_wins_flag(new_namerec
, record
->wins_flags
);
2670 new_namerec
->data
.id
=record
->id
;
2672 wins_server_subnet
->namelist_changed
= True
;
2675 wins_server_subnet
->namelist_changed
= True
;