2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 Change the wins owner address in the record.
30 *****************************************************************************/
32 static void update_wins_owner(struct name_record
*namerec
, struct in_addr wins_ip
)
36 namerec
->data
.wins_ip
=wins_ip
;
39 /****************************************************************************
40 Create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
43 static void update_wins_flag(struct name_record
*namerec
, int flags
)
48 namerec
->data
.wins_flags
=0x0;
50 /* if it's a group, it can be a normal or a special one */
51 if (namerec
->data
.nb_flags
& NB_GROUP
) {
52 if (namerec
->name
.name_type
==0x1C)
53 namerec
->data
.wins_flags
|=WINS_SGROUP
;
55 if (namerec
->data
.num_ips
>1)
56 namerec
->data
.wins_flags
|=WINS_SGROUP
;
58 namerec
->data
.wins_flags
|=WINS_NGROUP
;
60 /* can be unique or multi-homed */
61 if (namerec
->data
.num_ips
>1)
62 namerec
->data
.wins_flags
|=WINS_MHOMED
;
64 namerec
->data
.wins_flags
|=WINS_UNIQUE
;
67 /* the node type are the same bits */
68 namerec
->data
.wins_flags
|=namerec
->data
.nb_flags
&NB_NODETYPEMASK
;
70 /* the static bit is elsewhere */
71 if (namerec
->data
.death_time
== PERMANENT_TTL
)
72 namerec
->data
.wins_flags
|=WINS_STATIC
;
74 /* and add the given bits */
75 namerec
->data
.wins_flags
|=flags
;
77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
78 namerec
->data
.nb_flags
, (int)namerec
->data
.death_time
, flags
, namerec
->data
.wins_flags
));
81 /****************************************************************************
82 Return the general ID value and increase it if requested.
83 *****************************************************************************/
85 static void get_global_id_and_update(SMB_BIG_UINT
*current_id
, BOOL update
)
88 * it's kept as a static here, to prevent people from messing
89 * with the value directly
92 static SMB_BIG_UINT general_id
= 1;
94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id
));
96 *current_id
= general_id
;
102 /****************************************************************************
103 Possibly call the WINS hook external program when a WINS change is made.
104 *****************************************************************************/
106 static void wins_hook(const char *operation
, struct name_record
*namerec
, int ttl
)
109 char *cmd
= lp_wins_hook();
113 if (!cmd
|| !*cmd
) return;
115 for (p
=namerec
->name
.name
; *p
; p
++) {
116 if (!(isalnum((int)*p
) || strchr_m("._-",*p
))) {
117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec
->name
)));
123 p
+= slprintf(p
, sizeof(command
)-1, "%s %s %s %02x %d",
126 nmb_namestr(&namerec
->name
),
127 namerec
->name
.name_type
,
130 for (i
=0;i
<namerec
->data
.num_ips
;i
++) {
131 p
+= slprintf(p
, sizeof(command
) - (p
-command
) -1, " %s", inet_ntoa(namerec
->data
.ip
[i
]));
134 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec
->name
)));
135 smbrun(command
, NULL
);
139 /****************************************************************************
140 Determine if this packet should be allocated to the WINS server.
141 *****************************************************************************/
143 BOOL
packet_is_for_wins_server(struct packet_struct
*packet
)
145 struct nmb_packet
*nmb
= &packet
->packet
.nmb
;
147 /* Only unicast packets go to a WINS server. */
148 if((wins_server_subnet
== NULL
) || (nmb
->header
.nm_flags
.bcast
== True
)) {
149 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
153 /* Check for node status requests. */
154 if (nmb
->question
.question_type
!= QUESTION_TYPE_NB_QUERY
)
157 switch(nmb
->header
.opcode
) {
159 * A WINS server issues WACKS, not receives them.
161 case NMB_WACK_OPCODE
:
162 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
165 * A WINS server only processes registration and
166 * release requests, not responses.
168 case NMB_NAME_REG_OPCODE
:
169 case NMB_NAME_MULTIHOMED_REG_OPCODE
:
170 case NMB_NAME_REFRESH_OPCODE_8
: /* ambiguity in rfc1002 about which is correct. */
171 case NMB_NAME_REFRESH_OPCODE_9
: /* WinNT uses 8 by default. */
172 if(nmb
->header
.response
) {
173 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
178 case NMB_NAME_RELEASE_OPCODE
:
179 if(nmb
->header
.response
) {
180 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
186 * Only process unicast name queries with rd = 1.
188 case NMB_NAME_QUERY_OPCODE
:
189 if(!nmb
->header
.response
&& !nmb
->header
.nm_flags
.recursion_desired
) {
190 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
199 /****************************************************************************
200 Utility function to decide what ttl to give a register/refresh request.
201 *****************************************************************************/
203 static int get_ttl_from_packet(struct nmb_packet
*nmb
)
205 int ttl
= nmb
->additional
->ttl
;
207 if(ttl
< lp_min_wins_ttl() )
208 ttl
= lp_min_wins_ttl();
210 if(ttl
> lp_max_wins_ttl() )
211 ttl
= lp_max_wins_ttl();
216 /****************************************************************************
217 Load or create the WINS database.
218 *****************************************************************************/
220 BOOL
initialise_wins(void)
222 time_t time_now
= time(NULL
);
226 if(!lp_we_are_a_wins_server())
229 add_samba_names_to_subnet(wins_server_subnet
);
231 if((fp
= x_fopen(lock_path(WINS_LIST
),O_RDONLY
,0)) == NULL
) {
232 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
233 WINS_LIST
, strerror(errno
) ));
237 while (!x_feof(fp
)) {
238 pstring name_str
, ip_str
, ttl_str
, nb_flags_str
;
239 unsigned int num_ips
;
241 struct in_addr
*ip_list
;
253 /* Read a line from the wins.dat file. Strips whitespace
254 from the beginning and end of the line. */
255 if (!fgets_slash(line
,sizeof(pstring
),fp
))
261 if (strncmp(line
,"VERSION ", 8) == 0) {
262 if (sscanf(line
,"VERSION %d %u", &version
, &hash
) != 2 ||
263 version
!= WINS_VERSION
) {
264 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line
));
274 * Now we handle multiple IP addresses per name we need
275 * to iterate over the line twice. The first time to
276 * determine how many IP addresses there are, the second
277 * time to actually parse them into the ip_list array.
280 if (!next_token(&ptr
,name_str
,NULL
,sizeof(name_str
))) {
281 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line
));
285 if (!next_token(&ptr
,ttl_str
,NULL
,sizeof(ttl_str
))) {
286 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line
));
291 * Determine the number of IP addresses per line.
295 got_token
= next_token(&ptr
,ip_str
,NULL
,sizeof(ip_str
));
298 if(got_token
&& strchr(ip_str
, '.')) {
302 } while( got_token
&& was_ip
);
305 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line
));
310 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line
));
314 /* Allocate the space for the ip_list. */
315 if((ip_list
= (struct in_addr
*)malloc( num_ips
* sizeof(struct in_addr
))) == NULL
) {
316 DEBUG(0,("initialise_wins: Malloc fail !\n"));
320 /* Reset and re-parse the line. */
322 next_token(&ptr
,name_str
,NULL
,sizeof(name_str
));
323 next_token(&ptr
,ttl_str
,NULL
,sizeof(ttl_str
));
324 for(i
= 0; i
< num_ips
; i
++) {
325 next_token(&ptr
, ip_str
, NULL
, sizeof(ip_str
));
326 ip_list
[i
] = *interpret_addr2(ip_str
);
328 next_token(&ptr
,nb_flags_str
,NULL
, sizeof(nb_flags_str
));
331 * Deal with SELF or REGISTER name encoding. Default is REGISTER
332 * for compatibility with old nmbds.
335 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'S') {
336 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line
));
341 if(nb_flags_str
[strlen(nb_flags_str
)-1] == 'R')
342 nb_flags_str
[strlen(nb_flags_str
)-1] = '\0';
344 /* Netbios name. # divides the name from the type (hex): netbios#xx */
345 pstrcpy(name
,name_str
);
347 if((p
= strchr(name
,'#')) != NULL
) {
349 sscanf(p
+1,"%x",&type
);
352 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
353 sscanf(nb_flags_str
,"%x",&nb_flags
);
354 sscanf(ttl_str
,"%d",&ttl
);
356 /* add all entries that have 60 seconds or more to live */
357 if ((ttl
- 60) > time_now
|| ttl
== PERMANENT_TTL
) {
358 if(ttl
!= PERMANENT_TTL
)
361 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
362 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
364 (void)add_name_to_subnet( wins_server_subnet
, name
, type
, nb_flags
,
365 ttl
, REGISTER_NAME
, num_ips
, ip_list
);
367 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
368 name
, type
, ttl
, inet_ntoa(ip_list
[0]), nb_flags
));
378 /****************************************************************************
379 Send a WINS WACK (Wait ACKnowledgement) response.
380 **************************************************************************/
382 static void send_wins_wack_response(int ttl
, struct packet_struct
*p
)
384 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
385 unsigned char rdata
[2];
387 rdata
[0] = rdata
[1] = 0;
389 /* Taken from nmblib.c - we need to send back almost
390 identical bytes from the requesting packet header. */
392 rdata
[0] = (nmb
->header
.opcode
& 0xF) << 3;
393 if (nmb
->header
.nm_flags
.authoritative
&& nmb
->header
.response
)
395 if (nmb
->header
.nm_flags
.trunc
)
397 if (nmb
->header
.nm_flags
.recursion_desired
)
399 if (nmb
->header
.nm_flags
.recursion_available
&& nmb
->header
.response
)
401 if (nmb
->header
.nm_flags
.bcast
)
404 reply_netbios_packet(p
, /* Packet to reply to. */
405 0, /* Result code. */
406 NMB_WAIT_ACK
, /* nmbd type code. */
407 NMB_WACK_OPCODE
, /* opcode. */
409 (char *)rdata
, /* data to send. */
410 2); /* data length. */
413 /****************************************************************************
414 Send a WINS name registration response.
415 **************************************************************************/
417 static void send_wins_name_registration_response(int rcode
, int ttl
, struct packet_struct
*p
)
419 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
422 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
424 reply_netbios_packet(p
, /* Packet to reply to. */
425 rcode
, /* Result code. */
426 WINS_REG
, /* nmbd type code. */
427 NMB_NAME_REG_OPCODE
, /* opcode. */
429 rdata
, /* data to send. */
430 6); /* data length. */
433 /***********************************************************************
434 Deal with a name refresh request to a WINS server.
435 ************************************************************************/
437 void wins_process_name_refresh_request(struct subnet_record
*subrec
,
438 struct packet_struct
*p
)
440 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
441 struct nmb_name
*question
= &nmb
->question
.question_name
;
442 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
443 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
444 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
445 struct name_record
*namerec
= NULL
;
446 int ttl
= get_ttl_from_packet(nmb
);
447 struct in_addr from_ip
;
448 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
450 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
454 * We should only get unicast name refresh packets here.
455 * Anyone trying to refresh broadcast should not be going to a WINS
456 * server. Log an error here.
459 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
460 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
461 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
465 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
466 IP %s\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
469 * See if the name already exists.
472 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
475 * If this is a refresh request and the name doesn't exist then
476 * treat it like a registration request. This allows us to recover
477 * from errors (tridge)
480 if(namerec
== NULL
) {
481 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
482 the name does not exist. Treating as registration.\n", nmb_namestr(question
) ));
483 wins_process_name_registration_request(subrec
,p
);
488 * if the name is present but not active,
489 * simply remove it and treat the request
492 if (namerec
!= NULL
&& !WINS_STATE_ACTIVE(namerec
)) {
493 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
494 not active - removing it.\n", nmb_namestr(question
) ));
495 remove_name_from_namelist( subrec
, namerec
);
497 wins_process_name_registration_request(subrec
,p
);
502 * Check that the group bits for the refreshing name and the
503 * name in our database match.
506 if((namerec
!= NULL
) && ((group
&& !NAME_GROUP(namerec
)) || (!group
&& NAME_GROUP(namerec
))) ) {
507 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
508 does not match group bit in WINS for this name.\n", nmb_namestr(question
), group
? "True" : "False" ));
509 send_wins_name_registration_response(RFS_ERR
, 0, p
);
514 * For a unique name check that the person refreshing the name is one of the registered IP
515 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
516 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
517 * and return success.
520 if((!group
|| (group
&& (question
->name_type
== 0x1c))) && find_ip_in_name_record(namerec
, from_ip
)) {
524 update_name_ttl(namerec
, ttl
);
527 * if the record is a replica:
528 * we take ownership and update the version ID.
530 if (!ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
531 update_wins_owner(namerec
, our_fake_ip
);
532 get_global_id_and_update(&namerec
->data
.id
, True
);
535 send_wins_name_registration_response(0, ttl
, p
);
536 wins_hook("refresh", namerec
, ttl
);
540 * Normal groups are all registered with an IP address of 255.255.255.255
541 * so we can't search for the IP address.
543 update_name_ttl(namerec
, ttl
);
544 send_wins_name_registration_response(0, ttl
, p
);
546 } else if(!group
&& (question
->name_type
== 0x1d)) {
548 * Special name type - just pretend the refresh succeeded.
550 send_wins_name_registration_response(0, ttl
, p
);
557 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
558 is IP is not known to the name.\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
559 send_wins_name_registration_response(RFS_ERR
, 0, p
);
564 /***********************************************************************
565 Deal with a name registration request query success to a client that
568 We have a locked pointer to the original packet stashed away in the
569 userdata pointer. The success here is actually a failure as it means
570 the client we queried wants to keep the name, so we must return
571 a registration failure to the original requestor.
572 ************************************************************************/
574 static void wins_register_query_success(struct subnet_record
*subrec
,
575 struct userdata_struct
*userdata
,
576 struct nmb_name
*question_name
,
578 struct res_rec
*answers
)
580 struct packet_struct
*orig_reg_packet
;
582 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
584 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
585 name %s. Rejecting registration request.\n", inet_ntoa(ip
), nmb_namestr(question_name
) ));
587 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
589 orig_reg_packet
->locked
= False
;
590 free_packet(orig_reg_packet
);
593 /***********************************************************************
594 Deal with a name registration request query failure to a client that
597 We have a locked pointer to the original packet stashed away in the
598 userdata pointer. The failure here is actually a success as it means
599 the client we queried didn't want to keep the name, so we can remove
600 the old name record and then successfully add the new name.
601 ************************************************************************/
603 static void wins_register_query_fail(struct subnet_record
*subrec
,
604 struct response_record
*rrec
,
605 struct nmb_name
*question_name
,
608 struct userdata_struct
*userdata
= rrec
->userdata
;
609 struct packet_struct
*orig_reg_packet
;
610 struct name_record
*namerec
= NULL
;
612 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
615 * We want to just add the name, as we now know the original owner
616 * didn't want it. But we can't just do that as an arbitary
617 * amount of time may have taken place between the name query
618 * request and this timeout/error response. So we check that
619 * the name still exists and is in the same state - if so
620 * we remove it and call wins_process_name_registration_request()
621 * as we know it will do the right thing now.
624 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
626 if( (namerec
!= NULL
) && (namerec
->data
.source
== REGISTER_NAME
) && ip_equal(rrec
->packet
->ip
, *namerec
->data
.ip
) ) {
627 remove_name_from_namelist( subrec
, namerec
);
632 wins_process_name_registration_request(subrec
, orig_reg_packet
);
634 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
635 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name
) ));
637 orig_reg_packet
->locked
= False
;
638 free_packet(orig_reg_packet
);
641 /***********************************************************************
642 Deal with a name registration request to a WINS server.
644 Use the following pseudocode :
652 | +--- existing name is group
655 | | +--- add name (return).
658 | +--- exiting name is unique
661 | +--- query existing owner (return).
664 +--------name doesn't exist
667 +--- add name (return).
675 | +--- existing name is group
678 | | +--- fail add (return).
681 | +--- exiting name is unique
684 | +--- query existing owner (return).
687 +--------name doesn't exist
690 +--- add name (return).
692 As can be seen from the above, the two cases may be collapsed onto each
693 other with the exception of the case where the name already exists and
694 is a group name. This case we handle with an if statement.
696 ************************************************************************/
698 void wins_process_name_registration_request(struct subnet_record
*subrec
,
699 struct packet_struct
*p
)
702 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
703 struct nmb_name
*question
= &nmb
->question
.question_name
;
704 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
705 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
706 int ttl
= get_ttl_from_packet(nmb
);
707 struct name_record
*namerec
= NULL
;
708 struct in_addr from_ip
;
709 BOOL registering_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;
710 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
712 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
716 * We should only get unicast name registration packets here.
717 * Anyone trying to register broadcast should not be going to a WINS
718 * server. Log an error here.
721 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
722 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
723 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
727 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
728 IP %s\n", registering_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
731 * See if the name already exists.
734 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
737 * if the record exists but NOT in active state,
740 if ( (namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
741 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
742 not active - removing it.\n", nmb_namestr(question
) ));
743 remove_name_from_namelist( subrec
, namerec
);
748 * Deal with the case where the name found was a dns entry.
749 * Remove it as we now have a NetBIOS client registering the
753 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
754 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
755 a dns lookup - removing it.\n", nmb_namestr(question
) ));
756 remove_name_from_namelist( subrec
, namerec
);
761 * Reject if the name exists and is not a REGISTER_NAME.
762 * (ie. Don't allow any static names to be overwritten.
765 if((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) {
766 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
767 to register name %s. Name already exists in WINS with source type %d.\n",
768 nmb_namestr(question
), namerec
->data
.source
));
769 send_wins_name_registration_response(RFS_ERR
, 0, p
);
774 * Special policy decisions based on MS documentation.
775 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
776 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
780 * A group name is always added as the local broadcast address, except
781 * for group names ending in 0x1c.
782 * Group names with type 0x1c are registered with individual IP addresses.
785 if(registering_group_name
&& (question
->name_type
!= 0x1c))
786 from_ip
= *interpret_addr2("255.255.255.255");
789 * Ignore all attempts to register a unique 0x1d name, although return success.
792 if(!registering_group_name
&& (question
->name_type
== 0x1d)) {
793 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
794 to register name %s from IP %s.\n", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
795 send_wins_name_registration_response(0, ttl
, p
);
800 * Next two cases are the 'if statement' mentioned above.
803 if((namerec
!= NULL
) && NAME_GROUP(namerec
)) {
804 if(registering_group_name
) {
806 * If we are adding a group name, the name exists and is also a group entry just add this
807 * IP address to it and update the ttl.
810 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
811 inet_ntoa(from_ip
), nmb_namestr(question
) ));
814 * Check the ip address is not already in the group.
817 if(!find_ip_in_name_record(namerec
, from_ip
)) {
818 add_ip_to_name_record(namerec
, from_ip
);
819 /* we need to update the record for replication */
820 get_global_id_and_update(&namerec
->data
.id
, True
);
823 * if the record is a replica, we must change
824 * the wins owner to us to make the replication updates
825 * it on the other wins servers.
826 * And when the partner will receive this record,
827 * it will update its own record.
830 update_wins_owner(namerec
, our_fake_ip
);
832 update_name_ttl(namerec
, ttl
);
833 send_wins_name_registration_response(0, ttl
, p
);
838 * If we are adding a unique name, the name exists in the WINS db
839 * and is a group name then reject the registration.
841 * explanation: groups have a higher priority than unique names.
844 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
845 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
846 send_wins_name_registration_response(RFS_ERR
, 0, p
);
852 * From here on down we know that if the name exists in the WINS db it is
853 * a unique name, not a group name.
857 * If the name exists and is one of our names then check the
858 * registering IP address. If it's not one of ours then automatically
859 * reject without doing the query - we know we will reject it.
862 if ( namerec
!= NULL
)
863 pull_ascii_nstring(name
, namerec
->name
.name
);
865 if( is_myname(name
) ) {
866 if(!ismyip(from_ip
)) {
867 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
868 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
869 send_wins_name_registration_response(RFS_ERR
, 0, p
);
873 * It's one of our names and one of our IP's - update the ttl.
875 update_name_ttl(namerec
, ttl
);
876 send_wins_name_registration_response(0, ttl
, p
);
877 wins_hook("refresh", namerec
, ttl
);
883 * If the name exists and it is a unique registration and the registering IP
884 * is the same as the (single) already registered IP then just update the ttl.
886 * But not if the record is an active replica. IF it's a replica, it means it can be
887 * the same client which has moved and not yet expired. So we don't update
888 * the ttl in this case and go beyond to do a WACK and query the old client
891 if( !registering_group_name
893 && (namerec
->data
.num_ips
== 1)
894 && ip_equal( namerec
->data
.ip
[0], from_ip
)
895 && ip_equal(namerec
->data
.wins_ip
, our_fake_ip
) ) {
896 update_name_ttl( namerec
, ttl
);
897 send_wins_name_registration_response( 0, ttl
, p
);
898 wins_hook("refresh", namerec
, ttl
);
903 * Finally if the name exists do a query to the registering machine
904 * to see if they still claim to have the name.
907 if( namerec
!= NULL
) {
908 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
909 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
912 * First send a WACK to the registering machine.
915 send_wins_wack_response(60, p
);
918 * When the reply comes back we need the original packet.
919 * Lock this so it won't be freed and then put it into
920 * the userdata structure.
925 userdata
= (struct userdata_struct
*)ud
;
927 userdata
->copy_fn
= NULL
;
928 userdata
->free_fn
= NULL
;
929 userdata
->userdata_len
= sizeof(struct packet_struct
*);
930 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
933 * Use the new call to send a query directly to an IP address.
934 * This sends the query directly to the IP address, and ensures
935 * the recursion desired flag is not set (you were right Luke :-).
936 * This function should *only* be called from the WINS server
940 pull_ascii_nstring(name
, question
->name
);
941 query_name_from_wins_server( *namerec
->data
.ip
,
944 wins_register_query_success
,
945 wins_register_query_fail
,
951 * Name did not exist - add it.
954 pull_ascii_nstring(name
, question
->name
);
955 add_name_to_subnet( subrec
, name
, question
->name_type
,
956 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
958 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
959 get_global_id_and_update(&namerec
->data
.id
, True
);
960 update_wins_owner(namerec
, our_fake_ip
);
961 update_wins_flag(namerec
, WINS_ACTIVE
);
962 wins_hook("add", namerec
, ttl
);
965 send_wins_name_registration_response(0, ttl
, p
);
968 /***********************************************************************
969 Deal with a mutihomed name query success to the machine that
970 requested the multihomed name registration.
972 We have a locked pointer to the original packet stashed away in the
974 ************************************************************************/
976 static void wins_multihomed_register_query_success(struct subnet_record
*subrec
,
977 struct userdata_struct
*userdata
,
978 struct nmb_name
*question_name
,
980 struct res_rec
*answers
)
982 struct packet_struct
*orig_reg_packet
;
983 struct nmb_packet
*nmb
;
984 struct name_record
*namerec
= NULL
;
985 struct in_addr from_ip
;
987 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
989 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
991 nmb
= &orig_reg_packet
->packet
.nmb
;
993 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
994 ttl
= get_ttl_from_packet(nmb
);
997 * We want to just add the new IP, as we now know the requesting
998 * machine claims to own it. But we can't just do that as an arbitary
999 * amount of time may have taken place between the name query
1000 * request and this response. So we check that
1001 * the name still exists and is in the same state - if so
1002 * we just add the extra IP and update the ttl.
1005 namerec
= find_name_on_subnet(subrec
, question_name
, FIND_ANY_NAME
);
1007 if( (namerec
== NULL
) || (namerec
->data
.source
!= REGISTER_NAME
) || !WINS_STATE_ACTIVE(namerec
) ) {
1008 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1009 a subsequent IP address.\n", nmb_namestr(question_name
) ));
1010 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1012 orig_reg_packet
->locked
= False
;
1013 free_packet(orig_reg_packet
);
1018 if(!find_ip_in_name_record(namerec
, from_ip
))
1019 add_ip_to_name_record(namerec
, from_ip
);
1021 get_global_id_and_update(&namerec
->data
.id
, True
);
1022 update_wins_owner(namerec
, our_fake_ip
);
1023 update_wins_flag(namerec
, WINS_ACTIVE
);
1024 update_name_ttl(namerec
, ttl
);
1025 send_wins_name_registration_response(0, ttl
, orig_reg_packet
);
1026 wins_hook("add", namerec
, ttl
);
1028 orig_reg_packet
->locked
= False
;
1029 free_packet(orig_reg_packet
);
1032 /***********************************************************************
1033 Deal with a name registration request query failure to a client that
1036 We have a locked pointer to the original packet stashed away in the
1038 ************************************************************************/
1040 static void wins_multihomed_register_query_fail(struct subnet_record
*subrec
,
1041 struct response_record
*rrec
,
1042 struct nmb_name
*question_name
,
1045 struct userdata_struct
*userdata
= rrec
->userdata
;
1046 struct packet_struct
*orig_reg_packet
;
1048 memcpy((char *)&orig_reg_packet
, userdata
->data
, sizeof(struct packet_struct
*));
1050 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1051 query successfully for name %s.\n", inet_ntoa(orig_reg_packet
->ip
), nmb_namestr(question_name
) ));
1052 send_wins_name_registration_response(RFS_ERR
, 0, orig_reg_packet
);
1054 orig_reg_packet
->locked
= False
;
1055 free_packet(orig_reg_packet
);
1059 /***********************************************************************
1060 Deal with a multihomed name registration request to a WINS server.
1061 These cannot be group name registrations.
1062 ***********************************************************************/
1064 void wins_process_multihomed_name_registration_request( struct subnet_record
*subrec
,
1065 struct packet_struct
*p
)
1067 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1068 struct nmb_name
*question
= &nmb
->question
.question_name
;
1069 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
1070 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1071 int ttl
= get_ttl_from_packet(nmb
);
1072 struct name_record
*namerec
= NULL
;
1073 struct in_addr from_ip
;
1074 BOOL group
= (nb_flags
& NB_GROUP
) ? True
: False
;
1075 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
1078 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1082 * We should only get unicast name registration packets here.
1083 * Anyone trying to register broadcast should not be going to a WINS
1084 * server. Log an error here.
1087 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1088 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1089 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1094 * Only unique names should be registered multihomed.
1098 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1099 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1100 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1104 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1105 IP %s\n", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1108 * Deal with policy regarding 0x1d names.
1111 if(question
->name_type
== 0x1d) {
1112 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1113 to register name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1114 send_wins_name_registration_response(0, ttl
, p
);
1119 * See if the name already exists.
1122 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1125 * if the record exists but NOT in active state,
1129 if ((namerec
!= NULL
) && !WINS_STATE_ACTIVE(namerec
)) {
1130 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question
)));
1131 remove_name_from_namelist(subrec
, namerec
);
1136 * Deal with the case where the name found was a dns entry.
1137 * Remove it as we now have a NetBIOS client registering the
1141 if( (namerec
!= NULL
) && ( (namerec
->data
.source
== DNS_NAME
) || (namerec
->data
.source
== DNSFAIL_NAME
) ) ) {
1142 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1143 - removing it.\n", nmb_namestr(question
) ));
1144 remove_name_from_namelist( subrec
, namerec
);
1149 * Reject if the name exists and is not a REGISTER_NAME.
1150 * (ie. Don't allow any static names to be overwritten.
1153 if( (namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
) ) {
1154 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1155 to register name %s. Name already exists in WINS with source type %d.\n",
1156 nmb_namestr(question
), namerec
->data
.source
));
1157 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1162 * Reject if the name exists and is a GROUP name and is active.
1165 if((namerec
!= NULL
) && NAME_GROUP(namerec
) && WINS_STATE_ACTIVE(namerec
)) {
1166 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1167 already exists in WINS as a GROUP name.\n", nmb_namestr(question
) ));
1168 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1173 * From here on down we know that if the name exists in the WINS db it is
1174 * a unique name, not a group name.
1178 * If the name exists and is one of our names then check the
1179 * registering IP address. If it's not one of ours then automatically
1180 * reject without doing the query - we know we will reject it.
1183 if((namerec
!= NULL
) && (is_myname(namerec
->name
.name
)) ) {
1184 if(!ismyip(from_ip
)) {
1185 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1186 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question
) ));
1187 send_wins_name_registration_response(RFS_ERR
, 0, p
);
1191 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1192 * update the ttl. Update the version ID to force replication.
1194 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1195 get_global_id_and_update(&namerec
->data
.id
, True
);
1196 update_wins_owner(namerec
, our_fake_ip
);
1197 update_wins_flag(namerec
, WINS_ACTIVE
);
1199 add_ip_to_name_record(namerec
, from_ip
);
1200 wins_hook("add", namerec
, ttl
);
1202 wins_hook("refresh", namerec
, ttl
);
1205 update_name_ttl(namerec
, ttl
);
1206 send_wins_name_registration_response(0, ttl
, p
);
1212 * If the name exists and is active, check if the IP address is already registered
1213 * to that name. If so then update the ttl and reply success.
1216 if((namerec
!= NULL
) && find_ip_in_name_record(namerec
, from_ip
) && WINS_STATE_ACTIVE(namerec
)) {
1217 update_name_ttl(namerec
, ttl
);
1220 * If it's a replica, we need to become the wins owner
1221 * to force the replication
1223 if (!ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
1224 get_global_id_and_update(&namerec
->data
.id
, True
);
1225 update_wins_owner(namerec
, our_fake_ip
);
1226 update_wins_flag(namerec
, WINS_ACTIVE
);
1229 send_wins_name_registration_response(0, ttl
, p
);
1230 wins_hook("refresh", namerec
, ttl
);
1235 * If the name exists do a query to the owner
1236 * to see if they still want the name.
1239 if(namerec
!= NULL
) {
1240 long *ud
[(sizeof(struct userdata_struct
) + sizeof(struct packet_struct
*))/sizeof(long *) + 1];
1241 struct userdata_struct
*userdata
= (struct userdata_struct
*)ud
;
1244 * First send a WACK to the registering machine.
1247 send_wins_wack_response(60, p
);
1250 * When the reply comes back we need the original packet.
1251 * Lock this so it won't be freed and then put it into
1252 * the userdata structure.
1257 userdata
= (struct userdata_struct
*)ud
;
1259 userdata
->copy_fn
= NULL
;
1260 userdata
->free_fn
= NULL
;
1261 userdata
->userdata_len
= sizeof(struct packet_struct
*);
1262 memcpy(userdata
->data
, (char *)&p
, sizeof(struct packet_struct
*) );
1265 * Use the new call to send a query directly to an IP address.
1266 * This sends the query directly to the IP address, and ensures
1267 * the recursion desired flag is not set (you were right Luke :-).
1268 * This function should *only* be called from the WINS server
1271 * Note that this packet is sent to the current owner of the name,
1272 * not the person who sent the packet
1275 pull_ascii_nstring( qname
, question
->name
);
1276 query_name_from_wins_server( namerec
->data
.ip
[0],
1278 question
->name_type
,
1279 wins_multihomed_register_query_success
,
1280 wins_multihomed_register_query_fail
,
1287 * Name did not exist - add it.
1290 pull_ascii_nstring( qname
, question
->name
);
1291 add_name_to_subnet( subrec
, qname
, question
->name_type
,
1292 nb_flags
, ttl
, REGISTER_NAME
, 1, &from_ip
);
1294 if ((namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
))) {
1295 get_global_id_and_update(&namerec
->data
.id
, True
);
1296 update_wins_owner(namerec
, our_fake_ip
);
1297 update_wins_flag(namerec
, WINS_ACTIVE
);
1298 wins_hook("add", namerec
, ttl
);
1301 send_wins_name_registration_response(0, ttl
, p
);
1304 /***********************************************************************
1305 Deal with the special name query for *<1b>.
1306 ***********************************************************************/
1308 static void process_wins_dmb_query_request(struct subnet_record
*subrec
,
1309 struct packet_struct
*p
)
1311 struct name_record
*namerec
= NULL
;
1316 * Go through all the ACTIVE names in the WINS db looking for those
1317 * ending in <1b>. Use this to calculate the number of IP
1318 * addresses we need to return.
1322 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
1323 namerec
; namerec
= (struct name_record
*)ubi_trNext( namerec
) ) {
1324 if(WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b )
1325 num_ips
+= namerec
->data
.num_ips
;
1330 * There are no 0x1b names registered. Return name query fail.
1332 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1336 if((prdata
= (char *)malloc( num_ips
* 6 )) == NULL
) {
1337 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1342 * Go through all the names again in the WINS db looking for those
1343 * ending in <1b>. Add their IP addresses into the list we will
1348 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
1349 namerec
; namerec
= (struct name_record
*)ubi_trNext( namerec
) ) {
1350 if(WINS_STATE_ACTIVE(namerec
) && namerec
->name
.name_type
== 0x1b) {
1352 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1353 set_nb_flags(&prdata
[num_ips
* 6],namerec
->data
.nb_flags
);
1354 putip((char *)&prdata
[(num_ips
* 6) + 2], &namerec
->data
.ip
[i
]);
1361 * Send back the reply containing the IP list.
1364 reply_netbios_packet(p
, /* Packet to reply to. */
1365 0, /* Result code. */
1366 WINS_QUERY
, /* nmbd type code. */
1367 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1368 lp_min_wins_ttl(), /* ttl. */
1369 prdata
, /* data to send. */
1370 num_ips
*6); /* data length. */
1375 /****************************************************************************
1376 Send a WINS name query response.
1377 **************************************************************************/
1379 void send_wins_name_query_response(int rcode
, struct packet_struct
*p
,
1380 struct name_record
*namerec
)
1383 char *prdata
= rdata
;
1384 int reply_data_len
= 0;
1388 memset(rdata
,'\0',6);
1391 ttl
= (namerec
->data
.death_time
!= PERMANENT_TTL
) ? namerec
->data
.death_time
- p
->timestamp
: lp_max_wins_ttl();
1393 /* Copy all known ip addresses into the return data. */
1394 /* Optimise for the common case of one IP address so we don't need a malloc. */
1396 if( namerec
->data
.num_ips
== 1 ) {
1399 if((prdata
= (char *)malloc( namerec
->data
.num_ips
* 6 )) == NULL
) {
1400 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1405 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
1406 set_nb_flags(&prdata
[i
*6],namerec
->data
.nb_flags
);
1407 putip((char *)&prdata
[2+(i
*6)], &namerec
->data
.ip
[i
]);
1410 sort_query_replies(prdata
, i
, p
->ip
);
1411 reply_data_len
= namerec
->data
.num_ips
* 6;
1414 reply_netbios_packet(p
, /* Packet to reply to. */
1415 rcode
, /* Result code. */
1416 WINS_QUERY
, /* nmbd type code. */
1417 NMB_NAME_QUERY_OPCODE
, /* opcode. */
1419 prdata
, /* data to send. */
1420 reply_data_len
); /* data length. */
1426 /***********************************************************************
1427 Deal with a name query.
1428 ***********************************************************************/
1430 void wins_process_name_query_request(struct subnet_record
*subrec
,
1431 struct packet_struct
*p
)
1433 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1434 struct nmb_name
*question
= &nmb
->question
.question_name
;
1435 struct name_record
*namerec
= NULL
;
1438 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1439 nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1442 * Special name code. If the queried name is *<1b> then search
1443 * the entire WINS database and return a list of all the IP addresses
1444 * registered to any <1b> name. This is to allow domain master browsers
1445 * to discover other domains that may not have a presence on their subnet.
1448 pull_ascii_nstring(qname
, question
->name
);
1449 if(strequal( qname
, "*") && (question
->name_type
== 0x1b)) {
1450 process_wins_dmb_query_request( subrec
, p
);
1454 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1456 if(namerec
!= NULL
) {
1458 * If the name is not anymore in active state then reply not found.
1459 * it's fair even if we keep it in the cache for days.
1461 if (!WINS_STATE_ACTIVE(namerec
)) {
1462 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1463 nmb_namestr(question
) ));
1464 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1469 * If it's a DNSFAIL_NAME then reply name not found.
1472 if( namerec
->data
.source
== DNSFAIL_NAME
) {
1473 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1474 nmb_namestr(question
) ));
1475 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1480 * If the name has expired then reply name not found.
1483 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< p
->timestamp
) ) {
1484 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1485 nmb_namestr(question
) ));
1486 send_wins_name_query_response(NAM_ERR
, p
, namerec
);
1490 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1491 nmb_namestr(question
), inet_ntoa(namerec
->data
.ip
[0]) ));
1493 send_wins_name_query_response(0, p
, namerec
);
1498 * Name not found in WINS - try a dns query if it's a 0x20 name.
1501 if(lp_dns_proxy() && ((question
->name_type
== 0x20) || question
->name_type
== 0)) {
1502 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1503 nmb_namestr(question
) ));
1505 queue_dns_query(p
, question
, &namerec
);
1510 * Name not found - return error.
1513 send_wins_name_query_response(NAM_ERR
, p
, NULL
);
1516 /****************************************************************************
1517 Send a WINS name release response.
1518 **************************************************************************/
1520 static void send_wins_name_release_response(int rcode
, struct packet_struct
*p
)
1522 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1525 memcpy(&rdata
[0], &nmb
->additional
->rdata
[0], 6);
1527 reply_netbios_packet(p
, /* Packet to reply to. */
1528 rcode
, /* Result code. */
1529 NMB_REL
, /* nmbd type code. */
1530 NMB_NAME_RELEASE_OPCODE
, /* opcode. */
1532 rdata
, /* data to send. */
1533 6); /* data length. */
1536 /***********************************************************************
1537 Deal with a name release.
1538 ***********************************************************************/
1540 void wins_process_name_release_request(struct subnet_record
*subrec
,
1541 struct packet_struct
*p
)
1543 struct nmb_packet
*nmb
= &p
->packet
.nmb
;
1544 struct nmb_name
*question
= &nmb
->question
.question_name
;
1545 BOOL bcast
= nmb
->header
.nm_flags
.bcast
;
1546 uint16 nb_flags
= get_nb_flags(nmb
->additional
->rdata
);
1547 struct name_record
*namerec
= NULL
;
1548 struct in_addr from_ip
;
1549 BOOL releasing_group_name
= (nb_flags
& NB_GROUP
) ? True
: False
;;
1551 putip((char *)&from_ip
,&nmb
->additional
->rdata
[2]);
1555 * We should only get unicast name registration packets here.
1556 * Anyone trying to register broadcast should not be going to a WINS
1557 * server. Log an error here.
1560 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1561 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1562 nmb_namestr(question
), inet_ntoa(from_ip
), subrec
->subnet_name
));
1566 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1567 IP %s\n", releasing_group_name
? "Group" : "Unique", nmb_namestr(question
), inet_ntoa(from_ip
) ));
1570 * Deal with policy regarding 0x1d names.
1573 if(!releasing_group_name
&& (question
->name_type
== 0x1d)) {
1574 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1575 to release name %s from IP %s.", nmb_namestr(question
), inet_ntoa(p
->ip
) ));
1576 send_wins_name_release_response(0, p
);
1581 * See if the name already exists.
1584 namerec
= find_name_on_subnet(subrec
, question
, FIND_ANY_NAME
);
1586 if( (namerec
== NULL
) || ((namerec
!= NULL
) && (namerec
->data
.source
!= REGISTER_NAME
)) ) {
1587 send_wins_name_release_response(NAM_ERR
, p
);
1592 * Check that the sending machine has permission to release this name.
1593 * If it's a group name not ending in 0x1c then just say yes and let
1594 * the group time out.
1597 if(releasing_group_name
&& (question
->name_type
!= 0x1c)) {
1598 send_wins_name_release_response(0, p
);
1603 * Check that the releasing node is on the list of IP addresses
1604 * for this name. Disallow the release if not.
1607 if(!find_ip_in_name_record(namerec
, from_ip
)) {
1608 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1609 release name %s as IP %s is not one of the known IP's for this name.\n",
1610 nmb_namestr(question
), inet_ntoa(from_ip
) ));
1611 send_wins_name_release_response(NAM_ERR
, p
);
1616 * Check if the record is active. IF it's already released
1617 * or tombstoned, refuse the release.
1620 if (!WINS_STATE_ACTIVE(namerec
)) {
1621 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1622 release name %s as this record is not active anymore.\n", nmb_namestr(question
) ));
1623 send_wins_name_release_response(NAM_ERR
, p
);
1628 * Check if the record is a 0x1c group
1629 * and has more then one ip
1630 * remove only this address.
1633 if(releasing_group_name
&& (question
->name_type
== 0x1c) && (namerec
->data
.num_ips
> 1)) {
1634 remove_ip_from_name_record(namerec
, from_ip
);
1635 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1636 inet_ntoa(from_ip
),nmb_namestr(question
)));
1637 send_wins_name_release_response(0, p
);
1642 * Send a release response.
1643 * Flag the name as released and update the ttl
1646 send_wins_name_release_response(0, p
);
1648 namerec
->data
.wins_flags
|= WINS_RELEASED
;
1649 update_name_ttl(namerec
, EXTINCTION_INTERVAL
);
1651 wins_hook("delete", namerec
, 0);
1654 /*******************************************************************
1655 WINS time dependent processing.
1656 ******************************************************************/
1658 void initiate_wins_processing(time_t t
)
1660 static time_t lasttime
= 0;
1661 struct name_record
*namerec
;
1662 struct name_record
*next_namerec
;
1663 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
1667 if (t
- lasttime
< 20)
1672 if(!lp_we_are_a_wins_server())
1675 for( namerec
= (struct name_record
*)ubi_trFirst( wins_server_subnet
->namelist
);
1677 namerec
= next_namerec
) {
1678 next_namerec
= (struct name_record
*)ubi_trNext( namerec
);
1680 if( (namerec
->data
.death_time
!= PERMANENT_TTL
)
1681 && (namerec
->data
.death_time
< t
) ) {
1683 if( namerec
->data
.source
== SELF_NAME
) {
1684 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1685 wins_server_subnet
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
1686 namerec
->data
.death_time
+= 300;
1687 namerec
->subnet
->namelist_changed
= True
;
1691 /* handle records, samba is the wins owner */
1692 if (ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
1693 switch (namerec
->data
.wins_flags
| WINS_STATE_MASK
) {
1695 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
1696 namerec
->data
.wins_flags
|=WINS_RELEASED
;
1697 namerec
->data
.death_time
= t
+ EXTINCTION_INTERVAL
;
1698 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec
->name
)));
1701 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
1702 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
1703 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
1704 get_global_id_and_update(&namerec
->data
.id
, True
);
1705 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec
->name
)));
1707 case WINS_TOMBSTONED
:
1708 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec
->name
)));
1709 remove_name_from_namelist( wins_server_subnet
, namerec
);
1713 switch (namerec
->data
.wins_flags
| WINS_STATE_MASK
) {
1715 /* that's not as MS says it should be */
1716 namerec
->data
.wins_flags
&=~WINS_STATE_MASK
;
1717 namerec
->data
.wins_flags
|=WINS_TOMBSTONED
;
1718 namerec
->data
.death_time
= t
+ EXTINCTION_TIMEOUT
;
1719 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec
->name
)));
1720 case WINS_TOMBSTONED
:
1721 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec
->name
)));
1722 remove_name_from_namelist( wins_server_subnet
, namerec
);
1725 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1726 we are not the wins owner !\n", nmb_namestr(&namerec
->name
)));
1734 if(wins_server_subnet
->namelist_changed
)
1735 wins_write_database(True
);
1737 wins_server_subnet
->namelist_changed
= False
;
1740 /*******************************************************************
1741 Write out the current WINS database.
1742 ******************************************************************/
1744 void wins_write_database(BOOL background
)
1746 struct name_record
*namerec
;
1747 pstring fname
, fnamenew
;
1751 if(!lp_we_are_a_wins_server())
1754 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1762 slprintf(fname
,sizeof(fname
)-1,"%s/%s", lp_lockdir(), WINS_LIST
);
1763 all_string_sub(fname
,"//", "/", 0);
1764 slprintf(fnamenew
,sizeof(fnamenew
)-1,"%s.%u", fname
, (unsigned int)sys_getpid());
1766 if((fp
= x_fopen(fnamenew
,O_WRONLY
|O_CREAT
,0644)) == NULL
) {
1767 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew
, strerror(errno
)));
1774 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1776 x_fprintf(fp
,"VERSION %d %u\n", WINS_VERSION
, 0);
1778 for( namerec
= (struct name_record
*)ubi_trFirst( wins_server_subnet
->namelist
); namerec
; namerec
= (struct name_record
*)ubi_trNext( namerec
) ) {
1782 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec
->name
) ));
1784 if( namerec
->data
.death_time
!= PERMANENT_TTL
) {
1787 tm
= LocalTime(&namerec
->data
.death_time
);
1789 nl
= strrchr( ts
, '\n' );
1792 DEBUGADD(4,("TTL = %s ", ts
));
1794 DEBUGADD(4,("TTL = PERMANENT "));
1797 for (i
= 0; i
< namerec
->data
.num_ips
; i
++)
1798 DEBUGADD(4,("%15s ", inet_ntoa(namerec
->data
.ip
[i
]) ));
1799 DEBUGADD(4,("%2x\n", namerec
->data
.nb_flags
));
1801 if( namerec
->data
.source
== REGISTER_NAME
) {
1803 pull_ascii_nstring(name
, namerec
->name
.name
);
1804 x_fprintf(fp
, "\"%s#%02x\" %d ", name
,namerec
->name
.name_type
, /* Ignore scope. */
1805 (int)namerec
->data
.death_time
);
1807 for (i
= 0; i
< namerec
->data
.num_ips
; i
++)
1808 x_fprintf( fp
, "%s ", inet_ntoa( namerec
->data
.ip
[i
] ) );
1809 x_fprintf( fp
, "%2xR\n", namerec
->data
.nb_flags
);
1814 chmod(fnamenew
,0644);
1816 rename(fnamenew
,fname
);
1822 /****************************************************************************
1823 Process a internal Samba message receiving a wins record.
1824 ***************************************************************************/
1826 void nmbd_wins_new_entry(int msg_type
, pid_t src
, void *buf
, size_t len
)
1828 WINS_RECORD
*record
;
1829 struct name_record
*namerec
= NULL
;
1830 struct name_record
*new_namerec
= NULL
;
1831 struct nmb_name question
;
1832 BOOL overwrite
=False
;
1833 struct in_addr our_fake_ip
= *interpret_addr2("0.0.0.0");
1839 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1840 record
=(WINS_RECORD
*)buf
;
1842 make_nmb_name(&question
, record
->name
, record
->type
);
1844 namerec
= find_name_on_subnet(wins_server_subnet
, &question
, FIND_ANY_NAME
);
1846 /* record doesn't exist, add it */
1847 if (namerec
== NULL
) {
1848 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1849 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
1851 new_namerec
=add_name_to_subnet( wins_server_subnet
, record
->name
, record
->type
, record
->nb_flags
,
1852 EXTINCTION_INTERVAL
, REGISTER_NAME
, record
->num_ips
, record
->ip
);
1853 if (new_namerec
!=NULL
) {
1854 update_wins_owner(new_namerec
, record
->wins_ip
);
1855 update_wins_flag(new_namerec
, record
->wins_flags
);
1856 new_namerec
->data
.id
=record
->id
;
1858 wins_server_subnet
->namelist_changed
= True
;
1862 /* check if we have a conflict */
1863 if (namerec
!= NULL
) {
1864 /* both records are UNIQUE */
1865 if (namerec
->data
.wins_flags
&WINS_UNIQUE
&& record
->wins_flags
&WINS_UNIQUE
) {
1867 /* the database record is a replica */
1868 if (!ip_equal(namerec
->data
.wins_ip
, our_fake_ip
)) {
1869 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
) {
1870 if (ip_equal(namerec
->data
.wins_ip
, record
->wins_ip
))
1875 /* we are the wins owner of the database record */
1876 /* the 2 records have the same IP address */
1877 if (ip_equal(namerec
->data
.ip
[0], record
->ip
[0])) {
1878 if (namerec
->data
.wins_flags
&WINS_ACTIVE
&& record
->wins_flags
&WINS_TOMBSTONED
)
1879 get_global_id_and_update(&namerec
->data
.id
, True
);
1884 /* the 2 records have different IP address */
1885 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
1886 if (record
->wins_flags
&WINS_TOMBSTONED
)
1887 get_global_id_and_update(&namerec
->data
.id
, True
);
1888 if (record
->wins_flags
&WINS_ACTIVE
)
1889 /* send conflict challenge to the replica node */
1898 /* the replica is a standard group */
1899 if (record
->wins_flags
&WINS_NGROUP
|| record
->wins_flags
&WINS_SGROUP
) {
1900 /* if the database record is unique and active force a name release */
1901 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
1902 /* send a release name to the unique node */
1908 /* the replica is a special group */
1909 if (record
->wins_flags
&WINS_SGROUP
&& namerec
->data
.wins_flags
&WINS_SGROUP
) {
1910 if (namerec
->data
.wins_flags
&WINS_ACTIVE
) {
1911 for (i
=0; i
<record
->num_ips
; i
++)
1912 if(!find_ip_in_name_record(namerec
, record
->ip
[i
]))
1913 add_ip_to_name_record(namerec
, record
->ip
[i
]);
1919 /* the replica is a multihomed host */
1921 /* I'm giving up on multi homed. Too much complex to understand */
1923 if (record
->wins_flags
&WINS_MHOMED
) {
1924 if (! (namerec
->data
.wins_flags
&WINS_ACTIVE
)) {
1925 if ( !(namerec
->data
.wins_flags
&WINS_RELEASED
) && !(namerec
->data
.wins_flags
&WINS_NGROUP
))
1929 if (ip_equal(record
->wins_ip
, namerec
->data
.wins_ip
))
1932 if (ip_equal(namerec
->data
.wins_ip
, our_fake_ip
))
1933 if (namerec
->data
.wins_flags
&WINS_UNIQUE
)
1934 get_global_id_and_update(&namerec
->data
.id
, True
);
1938 if (record
->wins_flags
&WINS_ACTIVE
&& namerec
->data
.wins_flags
&WINS_ACTIVE
)
1939 if (namerec
->data
.wins_flags
&WINS_UNIQUE
||
1940 namerec
->data
.wins_flags
&WINS_MHOMED
)
1941 if (ip_equal(record
->wins_ip
, namerec
->data
.wins_ip
))
1946 if (overwrite
== False
)
1947 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1948 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
1950 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1951 record
->name
, record
->type
, inet_ntoa(record
->wins_ip
)));
1953 /* remove the old record and add a new one */
1954 remove_name_from_namelist( wins_server_subnet
, namerec
);
1955 new_namerec
=add_name_to_subnet( wins_server_subnet
, record
->name
, record
->type
, record
->nb_flags
,
1956 EXTINCTION_INTERVAL
, REGISTER_NAME
, record
->num_ips
, record
->ip
);
1957 if (new_namerec
!=NULL
) {
1958 update_wins_owner(new_namerec
, record
->wins_ip
);
1959 update_wins_flag(new_namerec
, record
->wins_flags
);
1960 new_namerec
->data
.id
=record
->id
;
1962 wins_server_subnet
->namelist_changed
= True
;
1965 wins_server_subnet
->namelist_changed
= True
;