2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Converted to store WINS data in a tdb. Dec 2005. JRA.
24 #include "system/filesys.h"
25 #include "nmbd/nmbd.h"
28 #define WINS_LIST "wins.dat"
29 #define WINS_VERSION 1
30 #define WINSDB_VERSION 1
32 /****************************************************************************
33 We don't store the NetBIOS scope in the wins.tdb. We key off the (utf8) netbios
34 name (65 bytes with the last byte being the name type).
35 *****************************************************************************/
37 TDB_CONTEXT
*wins_tdb
;
39 /****************************************************************************
40 Delete all the temporary name records on the in-memory linked list.
41 *****************************************************************************/
43 static void wins_delete_all_tmp_in_memory_records(void)
45 struct name_record
*nr
= NULL
;
46 struct name_record
*nrnext
= NULL
;
48 /* Delete all temporary name records on the wins subnet linked list. */
49 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nrnext
) {
51 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
52 SAFE_FREE(nr
->data
.ip
);
57 /****************************************************************************
58 Delete all the temporary 1b name records on the in-memory linked list.
59 *****************************************************************************/
61 static void wins_delete_all_1b_in_memory_records(void)
63 struct name_record
*nr
= NULL
;
64 struct name_record
*nrnext
= NULL
;
66 /* Delete all temporary 1b name records on the wins subnet linked list. */
67 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nrnext
) {
69 if (nr
->name
.name_type
== 0x1b) {
70 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
71 SAFE_FREE(nr
->data
.ip
);
77 /****************************************************************************
78 Convert a wins.tdb record to a struct name_record. Add in our global_scope().
79 *****************************************************************************/
81 static struct name_record
*wins_record_to_name_record(TDB_DATA key
, TDB_DATA data
)
83 struct name_record
*namerec
= NULL
;
86 uint32 death_time
, refresh_time
;
87 uint32 id_low
, id_high
;
94 if (data
.dptr
== NULL
|| data
.dsize
== 0) {
98 /* Min size is "wbddddddd" + 1 ip address (4). */
99 if (data
.dsize
< 2 + 1 + (7*4) + 4) {
103 len
= tdb_unpack(data
.dptr
, data
.dsize
,
115 namerec
= SMB_MALLOC_P(struct name_record
);
119 ZERO_STRUCTP(namerec
);
121 namerec
->data
.ip
= SMB_MALLOC_ARRAY(struct in_addr
, num_ips
);
122 if (!namerec
->data
.ip
) {
127 namerec
->subnet
= wins_server_subnet
;
128 push_ascii_nstring(namerec
->name
.name
, (const char *)key
.dptr
);
129 namerec
->name
.name_type
= key
.dptr
[sizeof(unstring
)];
131 push_ascii(namerec
->name
.scope
, global_scope(), 64, STR_TERMINATE
);
133 /* We're using a byte-by-byte compare, so we must be sure that
134 * unused space doesn't have garbage in it.
137 for( i
= strlen( namerec
->name
.name
); i
< sizeof( namerec
->name
.name
); i
++ ) {
138 namerec
->name
.name
[i
] = '\0';
140 for( i
= strlen( namerec
->name
.scope
); i
< sizeof( namerec
->name
.scope
); i
++ ) {
141 namerec
->name
.scope
[i
] = '\0';
144 namerec
->data
.nb_flags
= nb_flags
;
145 namerec
->data
.source
= (enum name_source
)nr_src
;
146 namerec
->data
.death_time
= (time_t)death_time
;
147 namerec
->data
.refresh_time
= (time_t)refresh_time
;
148 namerec
->data
.id
= id_low
;
149 #if defined(HAVE_LONGLONG)
150 namerec
->data
.id
|= ((uint64_t)id_high
<< 32);
152 namerec
->data
.wins_ip
.s_addr
= saddr
;
153 namerec
->data
.wins_flags
= wins_flags
,
154 namerec
->data
.num_ips
= num_ips
;
156 for (i
= 0; i
< num_ips
; i
++) {
157 namerec
->data
.ip
[i
].s_addr
= IVAL(data
.dptr
, len
+ (i
*4));
163 /****************************************************************************
164 Convert a struct name_record to a wins.tdb record. Ignore the scope.
165 *****************************************************************************/
167 static TDB_DATA
name_record_to_wins_record(const struct name_record
*namerec
)
172 uint32 id_low
= (namerec
->data
.id
& 0xFFFFFFFF);
173 #if defined(HAVE_LONGLONG)
174 uint32 id_high
= (namerec
->data
.id
>> 32) & 0xFFFFFFFF;
181 len
= (2 + 1 + (7*4)); /* "wbddddddd" */
182 len
+= (namerec
->data
.num_ips
* 4);
184 data
.dptr
= (uint8
*)SMB_MALLOC(len
);
190 len
= tdb_pack(data
.dptr
, data
.dsize
, "wbddddddd",
191 namerec
->data
.nb_flags
,
192 (unsigned char)namerec
->data
.source
,
193 (uint32
)namerec
->data
.death_time
,
194 (uint32
)namerec
->data
.refresh_time
,
197 (uint32
)namerec
->data
.wins_ip
.s_addr
,
198 (uint32
)namerec
->data
.wins_flags
,
199 (uint32
)namerec
->data
.num_ips
);
201 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
202 SIVAL(data
.dptr
, len
+ (i
*4), namerec
->data
.ip
[i
].s_addr
);
208 /****************************************************************************
209 Create key. Key is UNIX codepage namestring (usually utf8 64 byte len) with 1 byte type.
210 *****************************************************************************/
212 static TDB_DATA
name_to_key(const struct nmb_name
*nmbname
)
214 static char keydata
[sizeof(unstring
) + 1];
217 memset(keydata
, '\0', sizeof(keydata
));
219 pull_ascii_nstring(keydata
, sizeof(unstring
), nmbname
->name
);
221 keydata
[sizeof(unstring
)] = nmbname
->name_type
;
222 key
.dptr
= (uint8
*)keydata
;
223 key
.dsize
= sizeof(keydata
);
228 /****************************************************************************
229 Lookup a given name in the wins.tdb and create a temporary malloc'ed data struct
230 on the linked list. We will free this later in XXXX().
231 *****************************************************************************/
233 struct name_record
*find_name_on_wins_subnet(const struct nmb_name
*nmbname
, bool self_only
)
236 struct name_record
*nr
= NULL
;
237 struct name_record
*namerec
= NULL
;
243 key
= name_to_key(nmbname
);
244 data
= tdb_fetch(wins_tdb
, key
);
246 if (data
.dsize
== 0) {
250 namerec
= wins_record_to_name_record(key
, data
);
252 /* done with the this */
254 SAFE_FREE( data
.dptr
);
260 /* Self names only - these include permanent names. */
261 if( self_only
&& (namerec
->data
.source
!= SELF_NAME
) && (namerec
->data
.source
!= PERMANENT_NAME
) ) {
262 DEBUG( 9, ( "find_name_on_wins_subnet: self name %s NOT FOUND\n", nmb_namestr(nmbname
) ) );
263 SAFE_FREE(namerec
->data
.ip
);
268 /* Search for this name record on the list. Replace it if found. */
270 for( nr
= wins_server_subnet
->namelist
; nr
; nr
= nr
->next
) {
271 if (memcmp(nmbname
->name
, nr
->name
.name
, 16) == 0) {
273 DLIST_REMOVE(wins_server_subnet
->namelist
, nr
);
274 SAFE_FREE(nr
->data
.ip
);
280 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
284 /****************************************************************************
285 Overwrite or add a given name in the wins.tdb.
286 *****************************************************************************/
288 static bool store_or_replace_wins_namerec(const struct name_record
*namerec
, int tdb_flag
)
297 key
= name_to_key(&namerec
->name
);
298 data
= name_record_to_wins_record(namerec
);
300 if (data
.dptr
== NULL
) {
304 ret
= tdb_store(wins_tdb
, key
, data
, tdb_flag
);
306 SAFE_FREE(data
.dptr
);
307 return (ret
== 0) ? True
: False
;
310 /****************************************************************************
311 Overwrite a given name in the wins.tdb.
312 *****************************************************************************/
314 bool wins_store_changed_namerec(const struct name_record
*namerec
)
316 return store_or_replace_wins_namerec(namerec
, TDB_REPLACE
);
319 /****************************************************************************
320 Primary interface into creating and overwriting records in the wins.tdb.
321 *****************************************************************************/
323 bool add_name_to_wins_subnet(const struct name_record
*namerec
)
325 return store_or_replace_wins_namerec(namerec
, TDB_INSERT
);
328 /****************************************************************************
329 Delete a given name in the tdb and remove the temporary malloc'ed data struct
331 *****************************************************************************/
333 bool remove_name_from_wins_namelist(struct name_record
*namerec
)
342 key
= name_to_key(&namerec
->name
);
343 ret
= tdb_delete(wins_tdb
, key
);
345 DLIST_REMOVE(wins_server_subnet
->namelist
, namerec
);
347 /* namerec must be freed by the caller */
349 return (ret
== 0) ? True
: False
;
352 /****************************************************************************
353 Dump out the complete namelist.
354 *****************************************************************************/
356 static int traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
358 struct name_record
*namerec
= NULL
;
359 XFILE
*fp
= (XFILE
*)state
;
361 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
365 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
370 dump_name_record(namerec
, fp
);
372 SAFE_FREE(namerec
->data
.ip
);
377 void dump_wins_subnet_namelist(XFILE
*fp
)
379 tdb_traverse(wins_tdb
, traverse_fn
, (void *)fp
);
382 /****************************************************************************
383 Change the wins owner address in the record.
384 *****************************************************************************/
386 static void update_wins_owner(struct name_record
*namerec
, struct in_addr wins_ip
)
388 namerec
->data
.wins_ip
=wins_ip
;
391 /****************************************************************************
392 Create the wins flags based on the nb flags and the input value.
393 *****************************************************************************/
395 static void update_wins_flag(struct name_record
*namerec
, int flags
)
397 namerec
->data
.wins_flags
=0x0;
399 /* if it's a group, it can be a normal or a special one */
400 if (namerec
->data
.nb_flags
& NB_GROUP
) {
401 if (namerec
->name
.name_type
==0x1C) {
402 namerec
->data
.wins_flags
|=WINS_SGROUP
;
404 if (namerec
->data
.num_ips
>1) {
405 namerec
->data
.wins_flags
|=WINS_SGROUP
;
407 namerec
->data
.wins_flags
|=WINS_NGROUP
;
411 /* can be unique or multi-homed */
412 if (namerec
->data
.num_ips
>1) {
413 namerec
->data
.wins_flags
|=WINS_MHOMED
;
415 namerec
->data
.wins_flags
|=WINS_UNIQUE
;
419 /* the node type are the same bits */
420 namerec
->data
.wins_flags
|=namerec
->data
.nb_flags
&NB_NODETYPEMASK
;
422 /* the static bit is elsewhere */
423 if (namerec
->data
.death_time
== PERMANENT_TTL
) {
424 namerec
->data
.wins_flags
|=WINS_STATIC
;
427 /* and add the given bits */
428 namerec
->data
.wins_flags
|=flags
;
430 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: %d, flags: 0x%x, winsflags: 0x%x\n",
431 namerec
->data
.nb_flags
, (int)namerec
->data
.death_time
, flags
, namerec
->data
.wins_flags
));
434 /****************************************************************************
435 Return the general ID value and increase it if requested.
436 *****************************************************************************/
438 static void get_global_id_and_update(uint64_t *current_id
, bool update
)
441 * it's kept as a static here, to prevent people from messing
442 * with the value directly
445 static uint64_t general_id
= 1;
447 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id
));
449 *current_id
= general_id
;
456 /****************************************************************************
457 Possibly call the WINS hook external program when a WINS change is made.
458 Also stores the changed record back in the wins_tdb.
459 *****************************************************************************/
461 static void wins_hook(const char *operation
, struct name_record
*namerec
, int ttl
)
463 char *command
= NULL
;
464 char *cmd
= lp_wins_hook();
467 TALLOC_CTX
*ctx
= talloc_tos();
469 wins_store_changed_namerec(namerec
);
475 for (p
=namerec
->name
.name
; *p
; p
++) {
476 if (!(isalnum((int)*p
) || strchr_m("._-",*p
))) {
477 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec
->name
)));
482 /* Use the name without the nametype (and scope) appended */
484 namestr
= nmb_namestr(&namerec
->name
);
485 if ((p
= strchr(namestr
, '<'))) {
489 command
= talloc_asprintf(ctx
,
494 namerec
->name
.name_type
,
500 for (i
=0;i
<namerec
->data
.num_ips
;i
++) {
501 command
= talloc_asprintf_append(command
,
503 inet_ntoa(namerec
->data
.ip
[i
]));
509 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec
->name
)));
510 smbrun(command
, NULL
);
511 TALLOC_FREE(command
);
514 /****************************************************************************
515 Determine if this packet should be allocated to the WINS server.
516 *****************************************************************************/
518 bool packet_is_for_wins_server(struct packet_struct
*packet
)
520 struct nmb_packet
*nmb
= &packet
->packet
.nmb
;
522 /* Only unicast packets go to a WINS server. */
523 if((wins_server_subnet
== NULL
) || (nmb
->header
.nm_flags
.bcast
== True
)) {
524 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
528 /* Check for node status requests. */
529 if (nmb
->question
.question_type
!= QUESTION_TYPE_NB_QUERY
) {
533 switch(nmb
->header
.opcode
) {
535 * A WINS server issues WACKS, not receives them.
537 case NMB_WACK_OPCODE
:
538 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
541 * A WINS server only processes registration and
542 * release requests, not responses.
544 case NMB_NAME_REG_OPCODE
:
545 case NMB_NAME_MULTIHOMED_REG_OPCODE
:
546 case NMB_NAME_REFRESH_OPCODE_8
: /* ambiguity in rfc1002 about which is correct. */
547 case NMB_NAME_REFRESH_OPCODE_9
: /* WinNT uses 8 by default. */
548 if(nmb
->header
.response
) {
549 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
554 case NMB_NAME_RELEASE_OPCODE
:
555 if(nmb
->header
.response
) {
556 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
562 * Only process unicast name queries with rd = 1.
564 case NMB_NAME_QUERY_OPCODE
:
565 if(!nmb
->header
.response
&& !nmb
->header
.nm_flags
.recursion_desired
) {
566 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
575 /****************************************************************************
576 Utility function to decide what ttl to give a register/refresh request.
577 *****************************************************************************/
579 static int get_ttl_from_packet(struct nmb_packet
*nmb
)
581 int ttl
= nmb
->additional
->ttl
;
583 if (ttl
< lp_min_wins_ttl()) {
584 ttl
= lp_min_wins_ttl();
587 if (ttl
> lp_max_wins_ttl()) {
588 ttl
= lp_max_wins_ttl();
594 /****************************************************************************
595 Load or create the WINS database.
596 *****************************************************************************/
598 bool initialise_wins(void)
600 time_t time_now
= time(NULL
);
604 if(!lp_we_are_a_wins_server()) {
608 /* Open the wins.tdb. */
609 wins_tdb
= tdb_open_log(state_path("wins.tdb"), 0, TDB_DEFAULT
|TDB_CLEAR_IF_FIRST
|TDB_INCOMPATIBLE_HASH
,
610 O_CREAT
|O_RDWR
, 0600);
612 DEBUG(0,("initialise_wins: failed to open wins.tdb. Error was %s\n",
617 tdb_store_int32(wins_tdb
, "WINSDB_VERSION", WINSDB_VERSION
);
619 add_samba_names_to_subnet(wins_server_subnet
);
621 if((fp
= x_fopen(state_path(WINS_LIST
),O_RDONLY
,0)) == NULL
) {
622 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
623 WINS_LIST
, strerror(errno
) ));
627 while (!x_feof(fp
)) {
628 char *name_str
= NULL
;
630 char *ttl_str
= NULL
, *nb_flags_str
= NULL
;
631 unsigned int num_ips
;
633 struct in_addr
*ip_list
= NULL
;
644 TALLOC_CTX
*frame
= NULL
;
646 /* Read a line from the wins.dat file. Strips whitespace
647 from the beginning and end of the line. */
648 if (!fgets_slash(line
,sizeof(line
),fp
)) {
656 if (strncmp(line
,"VERSION ", 8) == 0) {
657 if (sscanf(line
,"VERSION %d %u", &version
, &hash
) != 2 ||
658 version
!= WINS_VERSION
) {
659 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line
));
669 * Now we handle multiple IP addresses per name we need
670 * to iterate over the line twice. The first time to
671 * determine how many IP addresses there are, the second
672 * time to actually parse them into the ip_list array.
675 frame
= talloc_stackframe();
676 if (!next_token_talloc(frame
,&ptr
,&name_str
,NULL
)) {
677 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line
));
682 if (!next_token_talloc(frame
,&ptr
,&ttl_str
,NULL
)) {
683 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line
));
689 * Determine the number of IP addresses per line.
693 got_token
= next_token_talloc(frame
,&ptr
,&ip_str
,NULL
);
696 if(got_token
&& strchr(ip_str
, '.')) {
700 } while(got_token
&& was_ip
);
703 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line
));
709 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line
));
714 /* Allocate the space for the ip_list. */
715 if((ip_list
= SMB_MALLOC_ARRAY( struct in_addr
, num_ips
)) == NULL
) {
716 DEBUG(0,("initialise_wins: Malloc fail !\n"));
722 /* Reset and re-parse the line. */
724 next_token_talloc(frame
,&ptr
,&name_str
,NULL
);
725 next_token_talloc(frame
,&ptr
,&ttl_str
,NULL
);
726 for(i
= 0; i
< num_ips
; i
++) {
727 next_token_talloc(frame
,&ptr
, &ip_str
, NULL
);
728 ip_list
[i
] = interpret_addr2(ip_str
);
730 next_token_talloc(frame
,&ptr
,&nb_flags_str
,NULL
);
733 * Deal with SELF or REGISTER name encoding. Default is REGISTER
734 * for compatibility with old nmbds.
737 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'S') {
738 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line
));
744 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'R') {
745 nb_flags_str
[strlen(nb_flags_str
)-1] = '\0';
748 /* Netbios name. # divides the name from the type (hex): netbios#xx */
751 if((p
= strchr(name
,'#')) != NULL
) {
753 sscanf(p
+1,"%x",&type
);
756 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
757 sscanf(nb_flags_str
,"%x",&nb_flags
);
758 sscanf(ttl_str
,"%d",&ttl
);
760 /* add all entries that have 60 seconds or more to live */
761 if ((ttl
- 60) > time_now
|| ttl
== PERMANENT_TTL
) {
762 if(ttl
!= PERMANENT_TTL
) {
766 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
767 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
769 (void)add_name_to_subnet( wins_server_subnet
, name
, type
, nb_flags
,
770 ttl
, REGISTER_NAME
, num_ips
, ip_list
);
772 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
773 "%s#%02x ttl = %d first IP %s flags = %2x\n",
774 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
785 /****************************************************************************
786 Send a WINS WACK (Wait ACKnowledgement) response.
787 **************************************************************************/
789 static void send_wins_wack_response(int ttl
, struct packet_struct
*p
)
791 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
792 unsigned char rdata
[2];
794 rdata
[0] = rdata
[1] = 0;
796 /* Taken from nmblib.c - we need to send back almost
797 identical bytes from the requesting packet header. */
799 rdata
[0] = (nmb
->header
.opcode
& 0xF) << 3;
800 if (nmb
->header
.nm_flags
.authoritative
&& nmb
->header
.response
) {
803 if (nmb
->header
.nm_flags
.trunc
) {
806 if (nmb
->header
.nm_flags
.recursion_desired
) {
809 if (nmb
->header
.nm_flags
.recursion_available
&& nmb
->header
.response
) {
812 if (nmb
->header
.nm_flags
.bcast
) {
816 reply_netbios_packet(p
, /* Packet to reply to. */
817 0, /* Result code. */
818 NMB_WAIT_ACK
, /* nmbd type code. */
819 NMB_WACK_OPCODE
, /* opcode. */
821 (char *)rdata
, /* data to send. */
822 2); /* data length. */
825 /****************************************************************************
826 Send a WINS name registration response.
827 **************************************************************************/
829 static void send_wins_name_registration_response(int rcode
, int ttl
, struct packet_struct
*p
)
831 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
834 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
836 reply_netbios_packet(p
, /* Packet to reply to. */
837 rcode
, /* Result code. */
838 WINS_REG
, /* nmbd type code. */
839 NMB_NAME_REG_OPCODE
, /* opcode. */
841 rdata
, /* data to send. */
842 6); /* data length. */
845 /***********************************************************************
846 Deal with a name refresh request to a WINS server.
847 ************************************************************************/
849 void wins_process_name_refresh_request( struct subnet_record
*subrec
,
850 struct packet_struct
*p
)
852 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
853 struct nmb_name
*question
= &nmb
->question
.question_name
;
854 bool bcast
= nmb
->header
.nm_flags
.bcast
;
855 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
856 bool group
= (nb_flags
& NB_GROUP
) ? True
: False
;
857 struct name_record
*namerec
= NULL
;
858 int ttl
= get_ttl_from_packet(nmb
);
859 struct in_addr from_ip
;
860 struct in_addr our_fake_ip
;
862 our_fake_ip
= interpret_addr2("0.0.0.0");
863 putip( (char *)&from_ip
, &nmb
->additional
->rdata
[2] );
867 * We should only get unicast name refresh packets here.
868 * Anyone trying to refresh broadcast should not be going
869 * to a WINS server. Log an error here.
871 if( DEBUGLVL( 0 ) ) {
872 dbgtext( "wins_process_name_refresh_request: " );
873 dbgtext( "Broadcast name refresh request received " );
874 dbgtext( "for name %s ", nmb_namestr(question
) );
875 dbgtext( "from IP %s ", inet_ntoa(from_ip
) );
876 dbgtext( "on subnet %s. ", subrec
->subnet_name
);
877 dbgtext( "Error - Broadcasts should not be sent " );
878 dbgtext( "to a WINS server\n" );
883 if( DEBUGLVL( 3 ) ) {
884 dbgtext( "wins_process_name_refresh_request: " );
885 dbgtext( "Name refresh for name %s IP %s\n",
886 nmb_namestr(question
), inet_ntoa(from_ip
) );
890 * See if the name already exists.
891 * If not, handle it as a name registration and return.
893 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
896 * If this is a refresh request and the name doesn't exist then
897 * treat it like a registration request. This allows us to recover
898 * from errors (tridge)
900 if(namerec
== NULL
) {
901 if( DEBUGLVL( 3 ) ) {
902 dbgtext( "wins_process_name_refresh_request: " );
903 dbgtext( "Name refresh for name %s ",
904 nmb_namestr( question
) );
905 dbgtext( "and the name does not exist. Treating " );
906 dbgtext( "as registration.\n" );
908 wins_process_name_registration_request(subrec
,p
);
913 * if the name is present but not active, simply remove it
914 * and treat the refresh request as a registration & return.
916 if (namerec
!= NULL
&& !WINS_STATE_ACTIVE(namerec
)) {
917 if( DEBUGLVL( 5 ) ) {
918 dbgtext( "wins_process_name_refresh_request: " );
919 dbgtext( "Name (%s) in WINS ", nmb_namestr(question
) );
920 dbgtext( "was not active - removing it.\n" );
922 remove_name_from_namelist( subrec
, namerec
);
924 wins_process_name_registration_request( subrec
, p
);
929 * Check that the group bits for the refreshing name and the
930 * name in our database match. If not, refuse the refresh.
931 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
933 if( (namerec
!= NULL
) &&
934 ( (group
&& !NAME_GROUP(namerec
))
935 || (!group
&& NAME_GROUP(namerec
)) ) ) {
936 if( DEBUGLVL( 3 ) ) {
937 dbgtext( "wins_process_name_refresh_request: " );
938 dbgtext( "Name %s ", nmb_namestr(question
) );
939 dbgtext( "group bit = %s does not match ",
940 group
? "True" : "False" );
941 dbgtext( "group bit in WINS for this name.\n" );
943 send_wins_name_registration_response(RFS_ERR
, 0, p
);
948 * For a unique name check that the person refreshing the name is
949 * one of the registered IP addresses. If not - fail the refresh.
950 * Do the same for group names with a type of 0x1c.
951 * Just return success for unique 0x1d refreshes. For normal group
952 * names update the ttl and return success.
954 if( (!group
|| (group
&& (question
->name_type
== 0x1c)))
955 && find_ip_in_name_record(namerec
, from_ip
) ) {
959 update_name_ttl(namerec
, ttl
);
962 * if the record is a replica:
963 * we take ownership and update the version ID.
965 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
966 update_wins_owner(namerec
, our_fake_ip
);
967 get_global_id_and_update(&namerec
->data
.id
, True
);
970 send_wins_name_registration_response(0, ttl
, p
);
971 wins_hook("refresh", namerec
, ttl
);
973 } else if((group
&& (question
->name_type
== 0x1c))) {
975 * Added by crh for bug #1079.
976 * Fix from Bert Driehuis
978 if( DEBUGLVL( 3 ) ) {
979 dbgtext( "wins_process_name_refresh_request: " );
980 dbgtext( "Name refresh for name %s, ",
981 nmb_namestr(question
) );
982 dbgtext( "but IP address %s ", inet_ntoa(from_ip
) );
983 dbgtext( "is not yet associated with " );
984 dbgtext( "that name. Treating as registration.\n" );
986 wins_process_name_registration_request(subrec
,p
);
990 * Normal groups are all registered with an IP address of
991 * 255.255.255.255 so we can't search for the IP address.
993 update_name_ttl(namerec
, ttl
);
994 wins_hook("refresh", namerec
, ttl
);
995 send_wins_name_registration_response(0, ttl
, p
);
997 } else if(!group
&& (question
->name_type
== 0x1d)) {
999 * Special name type - just pretend the refresh succeeded.
1001 send_wins_name_registration_response(0, ttl
, p
);
1007 if( DEBUGLVL( 3 ) ) {
1008 dbgtext( "wins_process_name_refresh_request: " );
1009 dbgtext( "Name refresh for name %s with IP %s ",
1010 nmb_namestr(question
), inet_ntoa(from_ip
) );
1011 dbgtext( "and is IP is not known to the name.\n" );
1013 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1018 /***********************************************************************
1019 Deal with a name registration request query success to a client that
1022 We have a locked pointer to the original packet stashed away in the
1023 userdata pointer. The success here is actually a failure as it means
1024 the client we queried wants to keep the name, so we must return
1025 a registration failure to the original requestor.
1026 ************************************************************************/
1028 static void wins_register_query_success(struct subnet_record
*subrec
,
1029 struct userdata_struct
*userdata
,
1030 struct nmb_name
*question_name
,
1032 struct res_rec
*answers
)
1034 struct packet_struct
*orig_reg_packet
;
1036 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1038 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
1039 name %s. Rejecting registration request.\n", inet_ntoa(ip
), nmb_namestr(question_name
) ));
1041 send_wins_name_registration_response(ACT_ERR
, 0, orig_reg_packet
);
1043 orig_reg_packet
->locked
= False
;
1044 free_packet(orig_reg_packet
);
1047 /***********************************************************************
1048 Deal with a name registration request query failure to a client that
1051 We have a locked pointer to the original packet stashed away in the
1052 userdata pointer. The failure here is actually a success as it means
1053 the client we queried didn't want to keep the name, so we can remove
1054 the old name record and then successfully add the new name.
1055 ************************************************************************/
1057 static void wins_register_query_fail(struct subnet_record
*subrec
,
1058 struct response_record
*rrec
,
1059 struct nmb_name
*question_name
,
1062 struct userdata_struct
*userdata
= rrec
->userdata
;
1063 struct packet_struct
*orig_reg_packet
;
1064 struct name_record
*namerec
= NULL
;
1066 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1069 * We want to just add the name, as we now know the original owner
1070 * didn't want it. But we can't just do that as an arbitary
1071 * amount of time may have taken place between the name query
1072 * request and this timeout/error response. So we check that
1073 * the name still exists and is in the same state - if so
1074 * we remove it and call wins_process_name_registration_request()
1075 * as we know it will do the right thing now.
1078 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1080 if ((namerec
!= NULL
) && (namerec
->data
.source
== REGISTER_NAME
) &&
1081 ip_equal_v4(rrec
->packet
->ip
, *namerec
->data
.ip
)) {
1082 remove_name_from_namelist( subrec
, namerec
);
1086 if(namerec
== NULL
) {
1087 wins_process_name_registration_request(subrec
, orig_reg_packet
);
1089 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
1090 "querying for name %s in order to replace it and this reply.\n",
1091 nmb_namestr(question_name
) ));
1094 orig_reg_packet
->locked
= False
;
1095 free_packet(orig_reg_packet
);
1098 /***********************************************************************
1099 Deal with a name registration request to a WINS server.
1101 Use the following pseudocode :
1106 +--------name exists
1109 | +--- existing name is group
1112 | | +--- add name (return).
1115 | +--- exiting name is unique
1118 | +--- query existing owner (return).
1121 +--------name doesn't exist
1124 +--- add name (return).
1129 +--------name exists
1132 | +--- existing name is group
1135 | | +--- fail add (return).
1138 | +--- exiting name is unique
1141 | +--- query existing owner (return).
1144 +--------name doesn't exist
1147 +--- add name (return).
1149 As can be seen from the above, the two cases may be collapsed onto each
1150 other with the exception of the case where the name already exists and
1151 is a group name. This case we handle with an if statement.
1153 ************************************************************************/
1155 void wins_process_name_registration_request(struct subnet_record
*subrec
,
1156 struct packet_struct
*p
)
1159 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1160 struct nmb_name
*question
= &nmb
->question
.question_name
;
1161 bool bcast
= nmb
->header
.nm_flags
.bcast
;
1162 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1163 int ttl
= get_ttl_from_packet(nmb
);
1164 struct name_record
*namerec
= NULL
;
1165 struct in_addr from_ip
;
1166 bool registering_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;
1167 struct in_addr our_fake_ip
;
1169 our_fake_ip
= interpret_addr2("0.0.0.0");
1170 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1174 * We should only get unicast name registration packets here.
1175 * Anyone trying to register broadcast should not be going to a WINS
1176 * server. Log an error here.
1179 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
1180 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1181 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1185 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
1186 IP %s\n", registering_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1189 * See if the name already exists.
1192 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1195 * if the record exists but NOT in active state,
1198 if ( (namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1199 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1200 not active - removing it.\n", nmb_namestr(question
) ));
1201 remove_name_from_namelist( subrec
, namerec
);
1206 * Deal with the case where the name found was a dns entry.
1207 * Remove it as we now have a NetBIOS client registering the
1211 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1212 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
1213 a dns lookup - removing it.\n", nmb_namestr(question
) ));
1214 remove_name_from_namelist( subrec
, namerec
);
1219 * Reject if the name exists and is not a REGISTER_NAME.
1220 * (ie. Don't allow any static names to be overwritten.
1223 if((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) {
1224 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
1225 to register name %s. Name already exists in WINS with source type %d.\n",
1226 nmb_namestr(question
), namerec
->data
.source
));
1227 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1232 * Special policy decisions based on MS documentation.
1233 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
1234 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
1238 * A group name is always added as the local broadcast address, except
1239 * for group names ending in 0x1c.
1240 * Group names with type 0x1c are registered with individual IP addresses.
1243 if(registering_group_name
&& (question
->name_type
!= 0x1c)) {
1244 from_ip
= interpret_addr2("255.255.255.255");
1248 * Ignore all attempts to register a unique 0x1d name, although return success.
1251 if(!registering_group_name
&& (question
->name_type
== 0x1d)) {
1252 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
1253 to register name %s from IP %s.\n", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1254 send_wins_name_registration_response(0, ttl
, p
);
1259 * Next two cases are the 'if statement' mentioned above.
1262 if((namerec
!= NULL
) && NAME_GROUP(namerec
)) {
1263 if(registering_group_name
) {
1265 * If we are adding a group name, the name exists and is also a group entry just add this
1266 * IP address to it and update the ttl.
1269 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
1270 inet_ntoa(from_ip
), nmb_namestr(question
) ));
1273 * Check the ip address is not already in the group.
1276 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1278 * Need to emulate the behaviour of Windows, as
1280 * http://lists.samba.org/archive/samba-technical/2001-October/016236.html
1281 * (is there an MS reference for this
1282 * somewhere?) because if the 1c list gets over
1283 * 86 entries, the reply packet is too big
1284 * (rdata>576 bytes) so no reply is sent.
1286 * Keep only the "latest" 25 records, while
1287 * ensuring that the PDC (0x1b) is never removed
1288 * We do this by removing the first entry that
1289 * isn't the 1b entry for the same name,
1290 * on the grounds that insertion is at the end
1291 * of the list, so the oldest entries are at
1295 while(namerec
->data
.num_ips
>=25) {
1296 struct name_record
*name1brec
= NULL
;
1298 /* We only do this for 1c types. */
1299 if (namerec
->name
.name_type
!= 0x1c) {
1302 DEBUG(3,("wins_process_name_registration_request: "
1303 "More than 25 IPs already in "
1304 "the list. Looking for a 1b "
1307 /* Ensure we have all the active 1b
1308 * names on the list. */
1309 wins_delete_all_1b_in_memory_records();
1310 fetch_all_active_wins_1b_names();
1312 /* Per the above, find the 1b record,
1313 and then remove the first IP that isn't the same */
1314 for(name1brec
= subrec
->namelist
;
1316 name1brec
= name1brec
->next
) {
1317 if( WINS_STATE_ACTIVE(name1brec
) &&
1318 name1brec
->name
.name_type
== 0x1b) {
1319 DEBUG(3,("wins_process_name_registration_request: "
1320 "Found the #1b record "
1322 inet_ntoa(name1brec
->data
.ip
[0])));
1327 DEBUG(3,("wins_process_name_registration_request: "
1328 "Didn't find a #1b name record. "
1329 "Removing the first available "
1331 inet_ntoa(namerec
->data
.ip
[0])));
1332 remove_ip_from_name_record(namerec
, namerec
->data
.ip
[0]);
1333 wins_hook("delete", namerec
, 0);
1336 for(i
=0; i
<namerec
->data
.num_ips
; i
++) {
1337 /* The name1brec should only have
1338 * the single IP address in it,
1339 * so we only check against the first one*/
1340 if(!ip_equal_v4( namerec
->data
.ip
[i
], name1brec
->data
.ip
[0])) {
1341 /* The i'th entry isn't the 1b address; delete it */
1342 DEBUG(3,("wins_process_name_registration_request: "
1343 "Entry at %d is not the #1b address. "
1344 "About to remove it\n",
1346 remove_ip_from_name_record(namerec
, namerec
->data
.ip
[i
]);
1347 wins_hook("delete", namerec
, 0);
1353 /* The list is guaranteed to be < 25 entries now
1354 * - safe to add a new one */
1355 add_ip_to_name_record(namerec
, from_ip
);
1356 /* we need to update the record for replication */
1357 get_global_id_and_update(&namerec
->data
.id
, True
);
1360 * if the record is a replica, we must change
1361 * the wins owner to us to make the replication updates
1362 * it on the other wins servers.
1363 * And when the partner will receive this record,
1364 * it will update its own record.
1367 update_wins_owner(namerec
, our_fake_ip
);
1369 update_name_ttl(namerec
, ttl
);
1370 wins_hook("refresh", namerec
, ttl
);
1371 send_wins_name_registration_response(0, ttl
, p
);
1376 * If we are adding a unique name, the name exists in the WINS db
1377 * and is a group name then reject the registration.
1379 * explanation: groups have a higher priority than unique names.
1382 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1383 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1384 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1390 * From here on down we know that if the name exists in the WINS db it is
1391 * a unique name, not a group name.
1395 * If the name exists and is one of our names then check the
1396 * registering IP address. If it's not one of ours then automatically
1397 * reject without doing the query - we know we will reject it.
1400 if ( namerec
!= NULL
) {
1401 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
1402 if( is_myname(name
) ) {
1403 if(!ismyip_v4(from_ip
)) {
1404 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
1405 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1406 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1410 * It's one of our names and one of our IP's - update the ttl.
1412 update_name_ttl(namerec
, ttl
);
1413 wins_hook("refresh", namerec
, ttl
);
1414 send_wins_name_registration_response(0, ttl
, p
);
1423 * If the name exists and it is a unique registration and the registering IP
1424 * is the same as the (single) already registered IP then just update the ttl.
1426 * But not if the record is an active replica. IF it's a replica, it means it can be
1427 * the same client which has moved and not yet expired. So we don't update
1428 * the ttl in this case and go beyond to do a WACK and query the old client
1431 if( !registering_group_name
1432 && (namerec
!= NULL
)
1433 && (namerec
->data
.num_ips
== 1)
1434 && ip_equal_v4( namerec
->data
.ip
[0], from_ip
)
1435 && ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
) ) {
1436 update_name_ttl( namerec
, ttl
);
1437 wins_hook("refresh", namerec
, ttl
);
1438 send_wins_name_registration_response( 0, ttl
, p
);
1443 * Finally if the name exists do a query to the registering machine
1444 * to see if they still claim to have the name.
1447 if( namerec
!= NULL
) {
1448 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1449 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1452 * First send a WACK to the registering machine.
1455 send_wins_wack_response(60, p
);
1458 * When the reply comes back we need the original packet.
1459 * Lock this so it won't be freed and then put it into
1460 * the userdata structure.
1465 userdata
= (struct userdata_struct
*)ud
;
1467 userdata
->copy_fn
= NULL
;
1468 userdata
->free_fn
= NULL
;
1469 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1470 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1473 * Use the new call to send a query directly to an IP address.
1474 * This sends the query directly to the IP address, and ensures
1475 * the recursion desired flag is not set (you were right Luke :-).
1476 * This function should *only* be called from the WINS server
1480 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1481 query_name_from_wins_server( *namerec
->data
.ip
,
1483 question
->name_type
,
1484 wins_register_query_success
,
1485 wins_register_query_fail
,
1491 * Name did not exist - add it.
1494 pull_ascii_nstring(name
, sizeof(name
), question
->name
);
1495 add_name_to_subnet( subrec
, name
, question
->name_type
,
1496 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1498 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1499 get_global_id_and_update(&namerec
->data
.id
, True
);
1500 update_wins_owner(namerec
, our_fake_ip
);
1501 update_wins_flag(namerec
, WINS_ACTIVE
);
1502 wins_hook("add", namerec
, ttl
);
1505 send_wins_name_registration_response(0, ttl
, p
);
1508 /***********************************************************************
1509 Deal with a mutihomed name query success to the machine that
1510 requested the multihomed name registration.
1512 We have a locked pointer to the original packet stashed away in the
1514 ************************************************************************/
1516 static void wins_multihomed_register_query_success(struct subnet_record
*subrec
,
1517 struct userdata_struct
*userdata
,
1518 struct nmb_name
*question_name
,
1520 struct res_rec
*answers
)
1522 struct packet_struct
*orig_reg_packet
;
1523 struct nmb_packet
*nmb
;
1524 struct name_record
*namerec
= NULL
;
1525 struct in_addr from_ip
;
1527 struct in_addr our_fake_ip
;
1529 our_fake_ip
= interpret_addr2("0.0.0.0");
1530 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1532 nmb
= &orig_reg_packet
->packet
.nmb
;
1534 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1535 ttl
= get_ttl_from_packet(nmb
);
1538 * We want to just add the new IP, as we now know the requesting
1539 * machine claims to own it. But we can't just do that as an arbitary
1540 * amount of time may have taken place between the name query
1541 * request and this response. So we check that
1542 * the name still exists and is in the same state - if so
1543 * we just add the extra IP and update the ttl.
1546 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1548 if( (namerec
== NULL
) || (namerec
->data
.source
!= REGISTER_NAME
) || !WINS_STATE_ACTIVE(namerec
) ) {
1549 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1550 a subsequent IP address.\n", nmb_namestr(question_name
) ));
1551 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1553 orig_reg_packet
->locked
= False
;
1554 free_packet(orig_reg_packet
);
1559 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1560 add_ip_to_name_record(namerec
, from_ip
);
1563 get_global_id_and_update(&namerec
->data
.id
, True
);
1564 update_wins_owner(namerec
, our_fake_ip
);
1565 update_wins_flag(namerec
, WINS_ACTIVE
);
1566 update_name_ttl(namerec
, ttl
);
1567 wins_hook("add", namerec
, ttl
);
1568 send_wins_name_registration_response(0, ttl
, orig_reg_packet
);
1570 orig_reg_packet
->locked
= False
;
1571 free_packet(orig_reg_packet
);
1574 /***********************************************************************
1575 Deal with a name registration request query failure to a client that
1578 We have a locked pointer to the original packet stashed away in the
1580 ************************************************************************/
1582 static void wins_multihomed_register_query_fail(struct subnet_record
*subrec
,
1583 struct response_record
*rrec
,
1584 struct nmb_name
*question_name
,
1587 struct userdata_struct
*userdata
= rrec
->userdata
;
1588 struct packet_struct
*orig_reg_packet
;
1590 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1592 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1593 query successfully for name %s.\n", inet_ntoa(orig_reg_packet
->ip
), nmb_namestr(question_name
) ));
1594 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1596 orig_reg_packet
->locked
= False
;
1597 free_packet(orig_reg_packet
);
1601 /***********************************************************************
1602 Deal with a multihomed name registration request to a WINS server.
1603 These cannot be group name registrations.
1604 ***********************************************************************/
1606 void wins_process_multihomed_name_registration_request( struct subnet_record
*subrec
,
1607 struct packet_struct
*p
)
1609 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1610 struct nmb_name
*question
= &nmb
->question
.question_name
;
1611 bool bcast
= nmb
->header
.nm_flags
.bcast
;
1612 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1613 int ttl
= get_ttl_from_packet(nmb
);
1614 struct name_record
*namerec
= NULL
;
1615 struct in_addr from_ip
;
1616 bool group
= (nb_flags
& NB_GROUP
) ? True
: False
;
1617 struct in_addr our_fake_ip
;
1620 our_fake_ip
= interpret_addr2("0.0.0.0");
1621 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1625 * We should only get unicast name registration packets here.
1626 * Anyone trying to register broadcast should not be going to a WINS
1627 * server. Log an error here.
1630 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1631 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1632 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1637 * Only unique names should be registered multihomed.
1641 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1642 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1643 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1647 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1648 IP %s\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1651 * Deal with policy regarding 0x1d names.
1654 if(question
->name_type
== 0x1d) {
1655 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1656 to register name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1657 send_wins_name_registration_response(0, ttl
, p
);
1662 * See if the name already exists.
1665 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1668 * if the record exists but NOT in active state,
1672 if ((namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1673 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question
)));
1674 remove_name_from_namelist(subrec
, namerec
);
1679 * Deal with the case where the name found was a dns entry.
1680 * Remove it as we now have a NetBIOS client registering the
1684 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1685 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1686 - removing it.\n", nmb_namestr(question
) ));
1687 remove_name_from_namelist( subrec
, namerec
);
1692 * Reject if the name exists and is not a REGISTER_NAME.
1693 * (ie. Don't allow any static names to be overwritten.
1696 if( (namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
) ) {
1697 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1698 to register name %s. Name already exists in WINS with source type %d.\n",
1699 nmb_namestr(question
), namerec
->data
.source
));
1700 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1705 * Reject if the name exists and is a GROUP name and is active.
1708 if((namerec
!= NULL
) && NAME_GROUP(namerec
) && WINS_STATE_ACTIVE(namerec
)) {
1709 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1710 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1711 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1716 * From here on down we know that if the name exists in the WINS db it is
1717 * a unique name, not a group name.
1721 * If the name exists and is one of our names then check the
1722 * registering IP address. If it's not one of ours then automatically
1723 * reject without doing the query - we know we will reject it.
1726 if((namerec
!= NULL
) && (is_myname(namerec
->name
.name
)) ) {
1727 if(!ismyip_v4(from_ip
)) {
1728 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1729 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1730 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1734 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1735 * update the ttl. Update the version ID to force replication.
1737 update_name_ttl(namerec
, ttl
);
1739 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1740 get_global_id_and_update(&namerec
->data
.id
, True
);
1741 update_wins_owner(namerec
, our_fake_ip
);
1742 update_wins_flag(namerec
, WINS_ACTIVE
);
1744 add_ip_to_name_record(namerec
, from_ip
);
1747 wins_hook("refresh", namerec
, ttl
);
1748 send_wins_name_registration_response(0, ttl
, p
);
1754 * If the name exists and is active, check if the IP address is already registered
1755 * to that name. If so then update the ttl and reply success.
1758 if((namerec
!= NULL
) && find_ip_in_name_record(namerec
, from_ip
) && WINS_STATE_ACTIVE(namerec
)) {
1759 update_name_ttl(namerec
, ttl
);
1762 * If it's a replica, we need to become the wins owner
1763 * to force the replication
1765 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
1766 get_global_id_and_update(&namerec
->data
.id
, True
);
1767 update_wins_owner(namerec
, our_fake_ip
);
1768 update_wins_flag(namerec
, WINS_ACTIVE
);
1771 wins_hook("refresh", namerec
, ttl
);
1772 send_wins_name_registration_response(0, ttl
, p
);
1777 * If the name exists do a query to the owner
1778 * to see if they still want the name.
1781 if(namerec
!= NULL
) {
1782 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1783 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1786 * First send a WACK to the registering machine.
1789 send_wins_wack_response(60, p
);
1792 * When the reply comes back we need the original packet.
1793 * Lock this so it won't be freed and then put it into
1794 * the userdata structure.
1799 userdata
= (struct userdata_struct
*)ud
;
1801 userdata
->copy_fn
= NULL
;
1802 userdata
->free_fn
= NULL
;
1803 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1804 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1807 * Use the new call to send a query directly to an IP address.
1808 * This sends the query directly to the IP address, and ensures
1809 * the recursion desired flag is not set (you were right Luke :-).
1810 * This function should *only* be called from the WINS server
1813 * Note that this packet is sent to the current owner of the name,
1814 * not the person who sent the packet
1817 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1818 query_name_from_wins_server( namerec
->data
.ip
[0],
1820 question
->name_type
,
1821 wins_multihomed_register_query_success
,
1822 wins_multihomed_register_query_fail
,
1829 * Name did not exist - add it.
1832 pull_ascii_nstring( qname
, sizeof(qname
), question
->name
);
1833 add_name_to_subnet( subrec
, qname
, question
->name_type
,
1834 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1836 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1837 get_global_id_and_update(&namerec
->data
.id
, True
);
1838 update_wins_owner(namerec
, our_fake_ip
);
1839 update_wins_flag(namerec
, WINS_ACTIVE
);
1840 wins_hook("add", namerec
, ttl
);
1843 send_wins_name_registration_response(0, ttl
, p
);
1846 /***********************************************************************
1847 Fetch all *<1b> names from the WINS db and store on the namelist.
1848 ***********************************************************************/
1850 static int fetch_1b_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
1852 struct name_record
*namerec
= NULL
;
1854 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
1858 /* Filter out all non-1b names. */
1859 if (kbuf
.dptr
[sizeof(unstring
)] != 0x1b) {
1863 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
1868 DLIST_ADD(wins_server_subnet
->namelist
, namerec
);
1872 void fetch_all_active_wins_1b_names(void)
1874 tdb_traverse(wins_tdb
, fetch_1b_traverse_fn
, NULL
);
1877 /***********************************************************************
1878 Deal with the special name query for *<1b>.
1879 ***********************************************************************/
1881 static void process_wins_dmb_query_request(struct subnet_record
*subrec
,
1882 struct packet_struct
*p
)
1884 struct name_record
*namerec
= NULL
;
1889 * Go through all the ACTIVE names in the WINS db looking for those
1890 * ending in <1b>. Use this to calculate the number of IP
1891 * addresses we need to return.
1896 /* First, clear the in memory list - we're going to re-populate
1897 it with the tdb_traversal in fetch_all_active_wins_1b_names. */
1899 wins_delete_all_tmp_in_memory_records();
1901 fetch_all_active_wins_1b_names();
1903 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1904 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1905 num_ips
+= namerec
->data
.num_ips
;
1911 * There are no 0x1b names registered. Return name query fail.
1913 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1917 if((prdata
= (char *)SMB_MALLOC( num_ips
* 6 )) == NULL
) {
1918 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1923 * Go through all the names again in the WINS db looking for those
1924 * ending in <1b>. Add their IP addresses into the list we will
1929 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
1930 if( WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1932 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1933 set_nb_flags(&prdata
[num_ips
* 6],namerec
->data
.nb_flags
);
1934 putip((char *)&prdata
[(num_ips
* 6) + 2], &namerec
->data
.ip
[i
]);
1941 * Send back the reply containing the IP list.
1944 reply_netbios_packet(p
, /* Packet to reply to. */
1945 0, /* Result code. */
1946 WINS_QUERY
, /* nmbd type code. */
1947 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1948 lp_min_wins_ttl(), /* ttl. */
1949 prdata
, /* data to send. */
1950 num_ips
*6); /* data length. */
1955 /****************************************************************************
1956 Send a WINS name query response.
1957 **************************************************************************/
1959 void send_wins_name_query_response(int rcode
, struct packet_struct
*p
,
1960 struct name_record
*namerec
)
1963 char *prdata
= rdata
;
1964 int reply_data_len
= 0;
1968 memset(rdata
,'\0',6);
1974 ttl
= (namerec
->data
.death_time
!= PERMANENT_TTL
) ? namerec
->data
.death_time
- p
->timestamp
: lp_max_wins_ttl();
1976 /* The netbios reply packet data section is limited to 576 bytes. In theory
1977 * this should give us space for 96 addresses, but in practice, 86 appears
1978 * to be the max (don't know why). If we send any more than that,
1979 * reply_netbios_packet will fail to send a reply to avoid a memcpy buffer
1980 * overflow. Keep the count to 85 and it will be ok */
1981 ip_count
=namerec
->data
.num_ips
;
1986 /* Copy all known ip addresses into the return data. */
1987 /* Optimise for the common case of one IP address so we don't need a malloc. */
1989 if( ip_count
== 1 ) {
1992 if((prdata
= (char *)SMB_MALLOC( ip_count
* 6 )) == NULL
) {
1993 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1998 for(i
= 0; i
< ip_count
; i
++) {
1999 set_nb_flags(&prdata
[i
*6],namerec
->data
.nb_flags
);
2000 putip((char *)&prdata
[2+(i
*6)], &namerec
->data
.ip
[i
]);
2003 sort_query_replies(prdata
, i
, p
->ip
);
2004 reply_data_len
= ip_count
* 6;
2007 reply_netbios_packet(p
, /* Packet to reply to. */
2008 rcode
, /* Result code. */
2009 WINS_QUERY
, /* nmbd type code. */
2010 NMB_NAME_QUERY_OPCODE
, /* opcode. */
2012 prdata
, /* data to send. */
2013 reply_data_len
); /* data length. */
2015 if(prdata
!= rdata
) {
2020 /***********************************************************************
2021 Deal with a name query.
2022 ***********************************************************************/
2024 void wins_process_name_query_request(struct subnet_record
*subrec
,
2025 struct packet_struct
*p
)
2027 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2028 struct nmb_name
*question
= &nmb
->question
.question_name
;
2029 struct name_record
*namerec
= NULL
;
2032 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
2033 nmb_namestr(question
), inet_ntoa(p
->ip
) ));
2036 * Special name code. If the queried name is *<1b> then search
2037 * the entire WINS database and return a list of all the IP addresses
2038 * registered to any <1b> name. This is to allow domain master browsers
2039 * to discover other domains that may not have a presence on their subnet.
2042 pull_ascii_nstring(qname
, sizeof(qname
), question
->name
);
2043 if(strequal( qname
, "*") && (question
->name_type
== 0x1b)) {
2044 process_wins_dmb_query_request( subrec
, p
);
2048 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
2050 if(namerec
!= NULL
) {
2052 * If the name is not anymore in active state then reply not found.
2053 * it's fair even if we keep it in the cache for days.
2055 if (!WINS_STATE_ACTIVE(namerec
)) {
2056 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2057 nmb_namestr(question
) ));
2058 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2063 * If it's a DNSFAIL_NAME then reply name not found.
2066 if( namerec
->data
.source
== DNSFAIL_NAME
) {
2067 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
2068 nmb_namestr(question
) ));
2069 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2074 * If the name has expired then reply name not found.
2077 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< p
->timestamp
) ) {
2078 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
2079 nmb_namestr(question
) ));
2080 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
2084 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
2085 nmb_namestr(question
), inet_ntoa(namerec
->data
.ip
[0]) ));
2087 send_wins_name_query_response(0, p
, namerec
);
2092 * Name not found in WINS - try a dns query if it's a 0x20 name.
2095 if(lp_dns_proxy() && ((question
->name_type
== 0x20) || question
->name_type
== 0)) {
2096 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
2097 nmb_namestr(question
) ));
2099 queue_dns_query(p
, question
);
2104 * Name not found - return error.
2107 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
2110 /****************************************************************************
2111 Send a WINS name release response.
2112 **************************************************************************/
2114 static void send_wins_name_release_response(int rcode
, struct packet_struct
*p
)
2116 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2119 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
2121 reply_netbios_packet(p
, /* Packet to reply to. */
2122 rcode
, /* Result code. */
2123 NMB_REL
, /* nmbd type code. */
2124 NMB_NAME_RELEASE_OPCODE
, /* opcode. */
2126 rdata
, /* data to send. */
2127 6); /* data length. */
2130 /***********************************************************************
2131 Deal with a name release.
2132 ***********************************************************************/
2134 void wins_process_name_release_request(struct subnet_record
*subrec
,
2135 struct packet_struct
*p
)
2137 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
2138 struct nmb_name
*question
= &nmb
->question
.question_name
;
2139 bool bcast
= nmb
->header
.nm_flags
.bcast
;
2140 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
2141 struct name_record
*namerec
= NULL
;
2142 struct in_addr from_ip
;
2143 bool releasing_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;
2145 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
2149 * We should only get unicast name registration packets here.
2150 * Anyone trying to register broadcast should not be going to a WINS
2151 * server. Log an error here.
2154 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
2155 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
2156 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
2160 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
2161 IP %s\n", releasing_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
2164 * Deal with policy regarding 0x1d names.
2167 if(!releasing_group_name
&& (question
->name_type
== 0x1d)) {
2168 DEBUG(3,("wins_process_name_release_request: Ignoring request \
2169 to release name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
2170 send_wins_name_release_response(0, p
);
2175 * See if the name already exists.
2178 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
2180 if( (namerec
== NULL
) || ((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) ) {
2181 send_wins_name_release_response(NAM_ERR
, p
);
2186 * Check that the sending machine has permission to release this name.
2187 * If it's a group name not ending in 0x1c then just say yes and let
2188 * the group time out.
2191 if(releasing_group_name
&& (question
->name_type
!= 0x1c)) {
2192 send_wins_name_release_response(0, p
);
2197 * Check that the releasing node is on the list of IP addresses
2198 * for this name. Disallow the release if not.
2201 if(!find_ip_in_name_record(namerec
, from_ip
)) {
2202 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2203 release name %s as IP %s is not one of the known IP's for this name.\n",
2204 nmb_namestr(question
), inet_ntoa(from_ip
) ));
2205 send_wins_name_release_response(NAM_ERR
, p
);
2210 * Check if the record is active. IF it's already released
2211 * or tombstoned, refuse the release.
2214 if (!WINS_STATE_ACTIVE(namerec
)) {
2215 DEBUG(3,("wins_process_name_release_request: Refusing request to \
2216 release name %s as this record is not active anymore.\n", nmb_namestr(question
) ));
2217 send_wins_name_release_response(NAM_ERR
, p
);
2222 * Check if the record is a 0x1c group
2223 * and has more then one ip
2224 * remove only this address.
2227 if(releasing_group_name
&& (question
->name_type
== 0x1c) && (namerec
->data
.num_ips
> 1)) {
2228 remove_ip_from_name_record(namerec
, from_ip
);
2229 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
2230 inet_ntoa(from_ip
),nmb_namestr(question
)));
2231 wins_hook("delete", namerec
, 0);
2232 send_wins_name_release_response(0, p
);
2237 * Send a release response.
2238 * Flag the name as released and update the ttl
2241 namerec
->data
.wins_flags
|= WINS_RELEASED
;
2242 update_name_ttl(namerec
, EXTINCTION_INTERVAL
);
2244 wins_hook("delete", namerec
, 0);
2245 send_wins_name_release_response(0, p
);
2248 /*******************************************************************
2249 WINS time dependent processing.
2250 ******************************************************************/
2252 static int wins_processing_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2254 time_t t
= *(time_t *)state
;
2255 bool store_record
= False
;
2256 struct name_record
*namerec
= NULL
;
2257 struct in_addr our_fake_ip
;
2259 our_fake_ip
= interpret_addr2("0.0.0.0");
2260 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2264 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2269 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< t
) ) {
2270 if( namerec
->data
.source
== SELF_NAME
) {
2271 DEBUG( 3, ( "wins_processing_traverse_fn: Subnet %s not expiring SELF name %s\n",
2272 wins_server_subnet
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
2273 namerec
->data
.death_time
+= 300;
2274 store_record
= True
;
2276 } else if (namerec
->data
.source
== DNS_NAME
|| namerec
->data
.source
== DNSFAIL_NAME
) {
2277 DEBUG(3,("wins_processing_traverse_fn: deleting timed out DNS name %s\n",
2278 nmb_namestr(&namerec
->name
)));
2279 remove_name_from_wins_namelist(namerec
);
2283 /* handle records, samba is the wins owner */
2284 if (ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
2285 switch (namerec
->data
.wins_flags
& WINS_STATE_MASK
) {
2287 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2288 namerec
->data
.wins_flags
|=WINS_RELEASED
;
2289 namerec
->data
.death_time
= t
+ EXTINCTION_INTERVAL
;
2290 DEBUG(3,("wins_processing_traverse_fn: expiring %s\n",
2291 nmb_namestr(&namerec
->name
)));
2292 store_record
= True
;
2295 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2296 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2297 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2298 get_global_id_and_update(&namerec
->data
.id
, True
);
2299 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2300 nmb_namestr(&namerec
->name
)));
2301 store_record
= True
;
2303 case WINS_TOMBSTONED
:
2304 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2305 nmb_namestr(&namerec
->name
)));
2306 remove_name_from_wins_namelist(namerec
);
2310 switch (namerec
->data
.wins_flags
& WINS_STATE_MASK
) {
2312 /* that's not as MS says it should be */
2313 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
2314 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
2315 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
2316 DEBUG(3,("wins_processing_traverse_fn: tombstoning %s\n",
2317 nmb_namestr(&namerec
->name
)));
2318 store_record
= True
;
2320 case WINS_TOMBSTONED
:
2321 DEBUG(3,("wins_processing_traverse_fn: deleting %s\n",
2322 nmb_namestr(&namerec
->name
)));
2323 remove_name_from_wins_namelist(namerec
);
2326 DEBUG(0,("wins_processing_traverse_fn: %s is in released state and\
2327 we are not the wins owner !\n", nmb_namestr(&namerec
->name
)));
2336 wins_store_changed_namerec(namerec
);
2339 SAFE_FREE(namerec
->data
.ip
);
2345 /*******************************************************************
2346 Time dependent wins processing.
2347 ******************************************************************/
2349 void initiate_wins_processing(time_t t
)
2351 static time_t lasttime
= 0;
2356 if (t
- lasttime
< 20) {
2360 if(!lp_we_are_a_wins_server()) {
2365 tdb_traverse(wins_tdb
, wins_processing_traverse_fn
, &t
);
2367 wins_delete_all_tmp_in_memory_records();
2369 wins_write_database(t
, True
);
2374 /*******************************************************************
2375 Write out one record.
2376 ******************************************************************/
2378 void wins_write_name_record(struct name_record
*namerec
, XFILE
*fp
)
2383 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec
->name
) ));
2385 if( namerec
->data
.death_time
!= PERMANENT_TTL
) {
2388 tm
= localtime(&namerec
->data
.death_time
);
2396 nl
= strrchr( ts
, '\n' );
2400 DEBUGADD(4,("TTL = %s ", ts
));
2402 DEBUGADD(4,("TTL = PERMANENT "));
2405 for (i
= 0; i
< namerec
->data
.num_ips
; i
++) {
2406 DEBUGADD(4,("%15s ", inet_ntoa(namerec
->data
.ip
[i
]) ));
2408 DEBUGADD(4,("%2x\n", namerec
->data
.nb_flags
));
2410 if( namerec
->data
.source
== REGISTER_NAME
) {
2412 pull_ascii_nstring(name
, sizeof(name
), namerec
->name
.name
);
2413 x_fprintf(fp
, "\"%s#%02x\" %d ", name
,namerec
->name
.name_type
, /* Ignore scope. */
2414 (int)namerec
->data
.death_time
);
2416 for (i
= 0; i
< namerec
->data
.num_ips
; i
++)
2417 x_fprintf( fp
, "%s ", inet_ntoa( namerec
->data
.ip
[i
] ) );
2418 x_fprintf( fp
, "%2xR\n", namerec
->data
.nb_flags
);
2422 /*******************************************************************
2423 Write out the current WINS database.
2424 ******************************************************************/
2426 static int wins_writedb_traverse_fn(TDB_CONTEXT
*tdb
, TDB_DATA kbuf
, TDB_DATA dbuf
, void *state
)
2428 struct name_record
*namerec
= NULL
;
2429 XFILE
*fp
= (XFILE
*)state
;
2431 if (kbuf
.dsize
!= sizeof(unstring
) + 1) {
2435 namerec
= wins_record_to_name_record(kbuf
, dbuf
);
2440 wins_write_name_record(namerec
, fp
);
2442 SAFE_FREE(namerec
->data
.ip
);
2448 void wins_write_database(time_t t
, bool background
)
2450 static time_t last_write_time
= 0;
2452 char *fnamenew
= NULL
;
2457 if (!last_write_time
) {
2458 last_write_time
= t
;
2460 if (t
- last_write_time
< 120) {
2466 if(!lp_we_are_a_wins_server()) {
2470 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
2476 if (tdb_reopen(wins_tdb
)) {
2477 DEBUG(0,("wins_write_database: tdb_reopen failed. Error was %s\n",
2484 if (!(fname
= state_path(WINS_LIST
))) {
2487 /* This is safe as the 0 length means "don't expand". */
2488 all_string_sub(fname
,"//", "/", 0);
2490 if (asprintf(&fnamenew
, "%s.%u", fname
, (unsigned int)sys_getpid()) < 0) {
2494 if((fp
= x_fopen(fnamenew
,O_WRONLY
|O_CREAT
,0644)) == NULL
) {
2495 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew
, strerror(errno
)));
2499 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
2501 x_fprintf(fp
,"VERSION %d %u\n", WINS_VERSION
, 0);
2503 tdb_traverse(wins_tdb
, wins_writedb_traverse_fn
, fp
);
2506 chmod(fnamenew
,0644);
2508 rename(fnamenew
,fname
);
2512 SAFE_FREE(fnamenew
);
2521 Until winsrepl is done
.
2522 /****************************************************************************
2523 Process a internal Samba message receiving a wins record.
2524 ***************************************************************************/
2526 void nmbd_wins_new_entry(struct messaging_context
*msg
,
2529 struct server_id server_id
,
2532 WINS_RECORD
*record
;
2533 struct name_record
*namerec
= NULL
;
2534 struct name_record
*new_namerec
= NULL
;
2535 struct nmb_name question
;
2536 bool overwrite
=False
;
2537 struct in_addr our_fake_ip
;
2540 our_fake_ip
= interpret_addr2("0.0.0.0");
2545 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
2546 record
=(WINS_RECORD
*)buf
;
2548 make_nmb_name(&question
, record
->name
, record
->type
);
2550 namerec
= find_name_on_subnet(wins_server_subnet
, &question
, FIND_ANY_NAME
);
2552 /* record doesn't exist, add it */
2553 if (namerec
== NULL
) {
2554 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
2555 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2557 new_namerec
=add_name_to_subnet( wins_server_subnet
,
2561 EXTINCTION_INTERVAL
,
2566 if (new_namerec
!=NULL
) {
2567 update_wins_owner(new_namerec
, record
->wins_ip
);
2568 update_wins_flag(new_namerec
, record
->wins_flags
);
2569 new_namerec
->data
.id
=record
->id
;
2571 wins_server_subnet
->namelist_changed
= True
;
2575 /* check if we have a conflict */
2576 if (namerec
!= NULL
) {
2577 /* both records are UNIQUE */
2578 if (namerec
->data
.wins_flags
&WINS_UNIQUE
&& record
->wins_flags
&WINS_UNIQUE
) {
2580 /* the database record is a replica */
2581 if (!ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
)) {
2582 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
) {
2583 if (ip_equal_v4(namerec
->data
.wins_ip
, record
->wins_ip
))
2588 /* we are the wins owner of the database record */
2589 /* the 2 records have the same IP address */
2590 if (ip_equal_v4(namerec
->data
.ip
[0], record
->ip
[0])) {
2591 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
)
2592 get_global_id_and_update(&namerec
->data
.id
, True
);
2597 /* the 2 records have different IP address */
2598 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2599 if (record
->wins_flags
&WINS_TOMBSTONED
)
2600 get_global_id_and_update(&namerec
->data
.id
, True
);
2601 if (record
->wins_flags
&WINS_ACTIVE
)
2602 /* send conflict challenge to the replica node */
2611 /* the replica is a standard group */
2612 if (record
->wins_flags
&WINS_NGROUP
|| record
->wins_flags
&WINS_SGROUP
) {
2613 /* if the database record is unique and active force a name release */
2614 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2615 /* send a release name to the unique node */
2621 /* the replica is a special group */
2622 if (record
->wins_flags
&WINS_SGROUP
&& namerec
->data
.wins_flags
&WINS_SGROUP
) {
2623 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
2624 for (i
=0; i
<record
->num_ips
; i
++)
2625 if(!find_ip_in_name_record(namerec
, record
->ip
[i
]))
2626 add_ip_to_name_record(namerec
, record
->ip
[i
]);
2632 /* the replica is a multihomed host */
2634 /* I'm giving up on multi homed. Too much complex to understand */
2636 if (record
->wins_flags
&WINS_MHOMED
) {
2637 if (! (namerec
->data
.wins_flags
&WINS_ACTIVE
)) {
2638 if ( !(namerec
->data
.wins_flags
&WINS_RELEASED
) && !(namerec
->data
.wins_flags
&WINS_NGROUP
))
2642 if (ip_equal_v4(record
->wins_ip
, namerec
->data
.wins_ip
))
2645 if (ip_equal_v4(namerec
->data
.wins_ip
, our_fake_ip
))
2646 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
2647 get_global_id_and_update(&namerec
->data
.id
, True
);
2651 if (record
->wins_flags
&WINS_ACTIVE
&& namerec
->data
.wins_flags
&WINS_ACTIVE
)
2652 if (namerec
->data
.wins_flags
&WINS_UNIQUE
||
2653 namerec
->data
.wins_flags
&WINS_MHOMED
)
2654 if (ip_equal_v4(record
->wins_ip
, namerec
->data
.wins_ip
))
2659 if (overwrite
== False
)
2660 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2661 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2663 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2664 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
2666 /* remove the old record and add a new one */
2667 remove_name_from_namelist( wins_server_subnet
, namerec
);
2668 new_namerec
=add_name_to_subnet( wins_server_subnet
, record
->name
, record
->type
, record
->nb_flags
,
2669 EXTINCTION_INTERVAL
, REGISTER_NAME
, record
->num_ips
, record
->ip
);
2670 if (new_namerec
!=NULL
) {
2671 update_wins_owner(new_namerec
, record
->wins_ip
);
2672 update_wins_flag(new_namerec
, record
->wins_flags
);
2673 new_namerec
->data
.id
=record
->id
;
2675 wins_server_subnet
->namelist_changed
= True
;
2678 wins_server_subnet
->namelist_changed
= True
;