2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2005
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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;
62 /* can be unique or multi-homed */
63 if (namerec->data.num_ips>1) {
64 namerec->data.wins_flags|=WINS_MHOMED;
66 namerec->data.wins_flags|=WINS_UNIQUE;
70 /* the node type are the same bits */
71 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
73 /* the static bit is elsewhere */
74 if (namerec->data.death_time == PERMANENT_TTL) {
75 namerec->data.wins_flags|=WINS_STATIC;
78 /* and add the given bits */
79 namerec->data.wins_flags|=flags;
81 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
82 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
85 /****************************************************************************
86 Return the general ID value and increase it if requested.
87 *****************************************************************************/
89 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
92 * it's kept as a static here, to prevent people from messing
93 * with the value directly
96 static SMB_BIG_UINT general_id = 1;
98 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
100 *current_id = general_id;
107 /****************************************************************************
108 Possibly call the WINS hook external program when a WINS change is made.
109 *****************************************************************************/
111 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
114 char *cmd = lp_wins_hook();
118 if (!cmd || !*cmd) return;
120 for (p=namerec->name.name; *p; p++) {
121 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
122 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
127 /* Use the name without the nametype (and scope) appended */
129 namestr = nmb_namestr(&namerec->name);
130 if ((p = strchr(namestr, '<'))) {
135 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
139 namerec->name.name_type,
142 for (i=0;i<namerec->data.num_ips;i++) {
143 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
146 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
147 smbrun(command, NULL);
151 /****************************************************************************
152 Determine if this packet should be allocated to the WINS server.
153 *****************************************************************************/
155 BOOL packet_is_for_wins_server(struct packet_struct *packet)
157 struct nmb_packet *nmb = &packet->packet.nmb;
159 /* Only unicast packets go to a WINS server. */
160 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
161 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
165 /* Check for node status requests. */
166 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) {
170 switch(nmb->header.opcode) {
172 * A WINS server issues WACKS, not receives them.
174 case NMB_WACK_OPCODE:
175 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
178 * A WINS server only processes registration and
179 * release requests, not responses.
181 case NMB_NAME_REG_OPCODE:
182 case NMB_NAME_MULTIHOMED_REG_OPCODE:
183 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
184 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
185 if(nmb->header.response) {
186 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
191 case NMB_NAME_RELEASE_OPCODE:
192 if(nmb->header.response) {
193 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
199 * Only process unicast name queries with rd = 1.
201 case NMB_NAME_QUERY_OPCODE:
202 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
203 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
212 /****************************************************************************
213 Utility function to decide what ttl to give a register/refresh request.
214 *****************************************************************************/
216 static int get_ttl_from_packet(struct nmb_packet *nmb)
218 int ttl = nmb->additional->ttl;
220 if (ttl < lp_min_wins_ttl()) {
221 ttl = lp_min_wins_ttl();
224 if (ttl > lp_max_wins_ttl()) {
225 ttl = lp_max_wins_ttl();
231 /****************************************************************************
232 Load or create the WINS database.
233 *****************************************************************************/
235 BOOL initialise_wins(void)
237 time_t time_now = time(NULL);
241 if(!lp_we_are_a_wins_server()) {
245 add_samba_names_to_subnet(wins_server_subnet);
247 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
248 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
249 WINS_LIST, strerror(errno) ));
253 while (!x_feof(fp)) {
254 pstring name_str, ip_str, ttl_str, nb_flags_str;
255 unsigned int num_ips;
257 struct in_addr *ip_list;
269 /* Read a line from the wins.dat file. Strips whitespace
270 from the beginning and end of the line. */
271 if (!fgets_slash(line,sizeof(pstring),fp))
277 if (strncmp(line,"VERSION ", 8) == 0) {
278 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
279 version != WINS_VERSION) {
280 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
290 * Now we handle multiple IP addresses per name we need
291 * to iterate over the line twice. The first time to
292 * determine how many IP addresses there are, the second
293 * time to actually parse them into the ip_list array.
296 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
297 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
301 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
302 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
307 * Determine the number of IP addresses per line.
311 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
314 if(got_token && strchr(ip_str, '.')) {
318 } while( got_token && was_ip);
321 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
326 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
330 /* Allocate the space for the ip_list. */
331 if((ip_list = SMB_MALLOC_ARRAY( struct in_addr, num_ips)) == NULL) {
332 DEBUG(0,("initialise_wins: Malloc fail !\n"));
336 /* Reset and re-parse the line. */
338 next_token(&ptr,name_str,NULL,sizeof(name_str));
339 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
340 for(i = 0; i < num_ips; i++) {
341 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
342 ip_list[i] = *interpret_addr2(ip_str);
344 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
347 * Deal with SELF or REGISTER name encoding. Default is REGISTER
348 * for compatibility with old nmbds.
351 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
352 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
357 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') {
358 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
361 /* Netbios name. # divides the name from the type (hex): netbios#xx */
362 pstrcpy(name,name_str);
364 if((p = strchr(name,'#')) != NULL) {
366 sscanf(p+1,"%x",&type);
369 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
370 sscanf(nb_flags_str,"%x",&nb_flags);
371 sscanf(ttl_str,"%d",&ttl);
373 /* add all entries that have 60 seconds or more to live */
374 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
375 if(ttl != PERMANENT_TTL) {
379 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
380 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
382 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
383 ttl, REGISTER_NAME, num_ips, ip_list );
385 DEBUG(4, ("initialise_wins: not adding name (ttl problem) "
386 "%s#%02x ttl = %d first IP %s flags = %2x\n",
387 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
397 /****************************************************************************
398 Send a WINS WACK (Wait ACKnowledgement) response.
399 **************************************************************************/
401 static void send_wins_wack_response(int ttl, struct packet_struct *p)
403 struct nmb_packet *nmb = &p->packet.nmb;
404 unsigned char rdata[2];
406 rdata[0] = rdata[1] = 0;
408 /* Taken from nmblib.c - we need to send back almost
409 identical bytes from the requesting packet header. */
411 rdata[0] = (nmb->header.opcode & 0xF) << 3;
412 if (nmb->header.nm_flags.authoritative && nmb->header.response) {
415 if (nmb->header.nm_flags.trunc) {
418 if (nmb->header.nm_flags.recursion_desired) {
421 if (nmb->header.nm_flags.recursion_available && nmb->header.response) {
424 if (nmb->header.nm_flags.bcast) {
428 reply_netbios_packet(p, /* Packet to reply to. */
429 0, /* Result code. */
430 NMB_WAIT_ACK, /* nmbd type code. */
431 NMB_WACK_OPCODE, /* opcode. */
433 (char *)rdata, /* data to send. */
434 2); /* data length. */
437 /****************************************************************************
438 Send a WINS name registration response.
439 **************************************************************************/
441 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
443 struct nmb_packet *nmb = &p->packet.nmb;
446 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
448 reply_netbios_packet(p, /* Packet to reply to. */
449 rcode, /* Result code. */
450 WINS_REG, /* nmbd type code. */
451 NMB_NAME_REG_OPCODE, /* opcode. */
453 rdata, /* data to send. */
454 6); /* data length. */
457 /***********************************************************************
458 Deal with a name refresh request to a WINS server.
459 ************************************************************************/
461 void wins_process_name_refresh_request( struct subnet_record *subrec,
462 struct packet_struct *p )
464 struct nmb_packet *nmb = &p->packet.nmb;
465 struct nmb_name *question = &nmb->question.question_name;
466 BOOL bcast = nmb->header.nm_flags.bcast;
467 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
468 BOOL group = (nb_flags & NB_GROUP) ? True : False;
469 struct name_record *namerec = NULL;
470 int ttl = get_ttl_from_packet(nmb);
471 struct in_addr from_ip;
472 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
474 putip( (char *)&from_ip, &nmb->additional->rdata[2] );
478 * We should only get unicast name refresh packets here.
479 * Anyone trying to refresh broadcast should not be going
480 * to a WINS server. Log an error here.
482 if( DEBUGLVL( 0 ) ) {
483 dbgtext( "wins_process_name_refresh_request: " );
484 dbgtext( "Broadcast name refresh request received " );
485 dbgtext( "for name %s ", nmb_namestr(question) );
486 dbgtext( "from IP %s ", inet_ntoa(from_ip) );
487 dbgtext( "on subnet %s. ", subrec->subnet_name );
488 dbgtext( "Error - Broadcasts should not be sent " );
489 dbgtext( "to a WINS server\n" );
494 if( DEBUGLVL( 3 ) ) {
495 dbgtext( "wins_process_name_refresh_request: " );
496 dbgtext( "Name refresh for name %s IP %s\n",
497 nmb_namestr(question), inet_ntoa(from_ip) );
501 * See if the name already exists.
502 * If not, handle it as a name registration and return.
504 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
507 * If this is a refresh request and the name doesn't exist then
508 * treat it like a registration request. This allows us to recover
509 * from errors (tridge)
511 if(namerec == NULL) {
512 if( DEBUGLVL( 3 ) ) {
513 dbgtext( "wins_process_name_refresh_request: " );
514 dbgtext( "Name refresh for name %s ",
515 nmb_namestr( question ) );
516 dbgtext( "and the name does not exist. Treating " );
517 dbgtext( "as registration.\n" );
519 wins_process_name_registration_request(subrec,p);
524 * if the name is present but not active, simply remove it
525 * and treat the refresh request as a registration & return.
527 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
528 if( DEBUGLVL( 5 ) ) {
529 dbgtext( "wins_process_name_refresh_request: " );
530 dbgtext( "Name (%s) in WINS ", nmb_namestr(question) );
531 dbgtext( "was not active - removing it.\n" );
533 remove_name_from_namelist( subrec, namerec );
535 wins_process_name_registration_request( subrec, p );
540 * Check that the group bits for the refreshing name and the
541 * name in our database match. If not, refuse the refresh.
542 * [crh: Why RFS_ERR instead of ACT_ERR? Is this what MS does?]
544 if( (namerec != NULL) &&
545 ( (group && !NAME_GROUP(namerec))
546 || (!group && NAME_GROUP(namerec)) ) ) {
547 if( DEBUGLVL( 3 ) ) {
548 dbgtext( "wins_process_name_refresh_request: " );
549 dbgtext( "Name %s ", nmb_namestr(question) );
550 dbgtext( "group bit = %s does not match ",
551 group ? "True" : "False" );
552 dbgtext( "group bit in WINS for this name.\n" );
554 send_wins_name_registration_response(RFS_ERR, 0, p);
559 * For a unique name check that the person refreshing the name is
560 * one of the registered IP addresses. If not - fail the refresh.
561 * Do the same for group names with a type of 0x1c.
562 * Just return success for unique 0x1d refreshes. For normal group
563 * names update the ttl and return success.
565 if( (!group || (group && (question->name_type == 0x1c)))
566 && find_ip_in_name_record(namerec, from_ip) ) {
570 update_name_ttl(namerec, ttl);
573 * if the record is a replica:
574 * we take ownership and update the version ID.
576 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
577 update_wins_owner(namerec, our_fake_ip);
578 get_global_id_and_update(&namerec->data.id, True);
581 send_wins_name_registration_response(0, ttl, p);
582 wins_hook("refresh", namerec, ttl);
584 } else if((group && (question->name_type == 0x1c))) {
586 * Added by crh for bug #1079.
587 * Fix from Bert Driehuis
589 if( DEBUGLVL( 3 ) ) {
590 dbgtext( "wins_process_name_refresh_request: " );
591 dbgtext( "Name refresh for name %s, ",
592 nmb_namestr(question) );
593 dbgtext( "but IP address %s ", inet_ntoa(from_ip) );
594 dbgtext( "is not yet associated with " );
595 dbgtext( "that name. Treating as registration.\n" );
597 wins_process_name_registration_request(subrec,p);
601 * Normal groups are all registered with an IP address of
602 * 255.255.255.255 so we can't search for the IP address.
604 update_name_ttl(namerec, ttl);
605 wins_hook("refresh", namerec, ttl);
606 send_wins_name_registration_response(0, ttl, p);
608 } else if(!group && (question->name_type == 0x1d)) {
610 * Special name type - just pretend the refresh succeeded.
612 send_wins_name_registration_response(0, ttl, p);
618 if( DEBUGLVL( 3 ) ) {
619 dbgtext( "wins_process_name_refresh_request: " );
620 dbgtext( "Name refresh for name %s with IP %s ",
621 nmb_namestr(question), inet_ntoa(from_ip) );
622 dbgtext( "and is IP is not known to the name.\n" );
624 send_wins_name_registration_response(RFS_ERR, 0, p);
629 /***********************************************************************
630 Deal with a name registration request query success to a client that
633 We have a locked pointer to the original packet stashed away in the
634 userdata pointer. The success here is actually a failure as it means
635 the client we queried wants to keep the name, so we must return
636 a registration failure to the original requestor.
637 ************************************************************************/
639 static void wins_register_query_success(struct subnet_record *subrec,
640 struct userdata_struct *userdata,
641 struct nmb_name *question_name,
643 struct res_rec *answers)
645 struct packet_struct *orig_reg_packet;
647 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
649 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
650 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
652 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
654 orig_reg_packet->locked = False;
655 free_packet(orig_reg_packet);
658 /***********************************************************************
659 Deal with a name registration request query failure to a client that
662 We have a locked pointer to the original packet stashed away in the
663 userdata pointer. The failure here is actually a success as it means
664 the client we queried didn't want to keep the name, so we can remove
665 the old name record and then successfully add the new name.
666 ************************************************************************/
668 static void wins_register_query_fail(struct subnet_record *subrec,
669 struct response_record *rrec,
670 struct nmb_name *question_name,
673 struct userdata_struct *userdata = rrec->userdata;
674 struct packet_struct *orig_reg_packet;
675 struct name_record *namerec = NULL;
677 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
680 * We want to just add the name, as we now know the original owner
681 * didn't want it. But we can't just do that as an arbitary
682 * amount of time may have taken place between the name query
683 * request and this timeout/error response. So we check that
684 * the name still exists and is in the same state - if so
685 * we remove it and call wins_process_name_registration_request()
686 * as we know it will do the right thing now.
689 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
691 if ((namerec != NULL) && (namerec->data.source == REGISTER_NAME) &&
692 ip_equal(rrec->packet->ip, *namerec->data.ip)) {
693 remove_name_from_namelist( subrec, namerec);
697 if(namerec == NULL) {
698 wins_process_name_registration_request(subrec, orig_reg_packet);
700 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between "
701 "querying for name %s in order to replace it and this reply.\n",
702 nmb_namestr(question_name) ));
705 orig_reg_packet->locked = False;
706 free_packet(orig_reg_packet);
709 /***********************************************************************
710 Deal with a name registration request to a WINS server.
712 Use the following pseudocode :
720 | +--- existing name is group
723 | | +--- add name (return).
726 | +--- exiting name is unique
729 | +--- query existing owner (return).
732 +--------name doesn't exist
735 +--- add name (return).
743 | +--- existing name is group
746 | | +--- fail add (return).
749 | +--- exiting name is unique
752 | +--- query existing owner (return).
755 +--------name doesn't exist
758 +--- add name (return).
760 As can be seen from the above, the two cases may be collapsed onto each
761 other with the exception of the case where the name already exists and
762 is a group name. This case we handle with an if statement.
764 ************************************************************************/
766 void wins_process_name_registration_request(struct subnet_record *subrec,
767 struct packet_struct *p)
770 struct nmb_packet *nmb = &p->packet.nmb;
771 struct nmb_name *question = &nmb->question.question_name;
772 BOOL bcast = nmb->header.nm_flags.bcast;
773 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
774 int ttl = get_ttl_from_packet(nmb);
775 struct name_record *namerec = NULL;
776 struct in_addr from_ip;
777 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
778 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
780 putip((char *)&from_ip,&nmb->additional->rdata[2]);
784 * We should only get unicast name registration packets here.
785 * Anyone trying to register broadcast should not be going to a WINS
786 * server. Log an error here.
789 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
790 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
791 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
795 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
796 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
799 * See if the name already exists.
802 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
805 * if the record exists but NOT in active state,
808 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
809 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
810 not active - removing it.\n", nmb_namestr(question) ));
811 remove_name_from_namelist( subrec, namerec );
816 * Deal with the case where the name found was a dns entry.
817 * Remove it as we now have a NetBIOS client registering the
821 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
822 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
823 a dns lookup - removing it.\n", nmb_namestr(question) ));
824 remove_name_from_namelist( subrec, namerec );
829 * Reject if the name exists and is not a REGISTER_NAME.
830 * (ie. Don't allow any static names to be overwritten.
833 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
834 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
835 to register name %s. Name already exists in WINS with source type %d.\n",
836 nmb_namestr(question), namerec->data.source ));
837 send_wins_name_registration_response(RFS_ERR, 0, p);
842 * Special policy decisions based on MS documentation.
843 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
844 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
848 * A group name is always added as the local broadcast address, except
849 * for group names ending in 0x1c.
850 * Group names with type 0x1c are registered with individual IP addresses.
853 if(registering_group_name && (question->name_type != 0x1c)) {
854 from_ip = *interpret_addr2("255.255.255.255");
858 * Ignore all attempts to register a unique 0x1d name, although return success.
861 if(!registering_group_name && (question->name_type == 0x1d)) {
862 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
863 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
864 send_wins_name_registration_response(0, ttl, p);
869 * Next two cases are the 'if statement' mentioned above.
872 if((namerec != NULL) && NAME_GROUP(namerec)) {
873 if(registering_group_name) {
875 * If we are adding a group name, the name exists and is also a group entry just add this
876 * IP address to it and update the ttl.
879 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
880 inet_ntoa(from_ip), nmb_namestr(question) ));
883 * Check the ip address is not already in the group.
886 if(!find_ip_in_name_record(namerec, from_ip)) {
887 add_ip_to_name_record(namerec, from_ip);
888 /* we need to update the record for replication */
889 get_global_id_and_update(&namerec->data.id, True);
892 * if the record is a replica, we must change
893 * the wins owner to us to make the replication updates
894 * it on the other wins servers.
895 * And when the partner will receive this record,
896 * it will update its own record.
899 update_wins_owner(namerec, our_fake_ip);
901 update_name_ttl(namerec, ttl);
902 wins_hook("refresh", namerec, ttl);
903 send_wins_name_registration_response(0, ttl, p);
908 * If we are adding a unique name, the name exists in the WINS db
909 * and is a group name then reject the registration.
911 * explanation: groups have a higher priority than unique names.
914 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
915 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
916 send_wins_name_registration_response(RFS_ERR, 0, p);
922 * From here on down we know that if the name exists in the WINS db it is
923 * a unique name, not a group name.
927 * If the name exists and is one of our names then check the
928 * registering IP address. If it's not one of ours then automatically
929 * reject without doing the query - we know we will reject it.
932 if ( namerec != NULL ) {
933 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
938 if( is_myname(name) ) {
939 if(!ismyip(from_ip)) {
940 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
941 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
942 send_wins_name_registration_response(RFS_ERR, 0, p);
946 * It's one of our names and one of our IP's - update the ttl.
948 update_name_ttl(namerec, ttl);
949 wins_hook("refresh", namerec, ttl);
950 send_wins_name_registration_response(0, ttl, p);
956 * If the name exists and it is a unique registration and the registering IP
957 * is the same as the (single) already registered IP then just update the ttl.
959 * But not if the record is an active replica. IF it's a replica, it means it can be
960 * the same client which has moved and not yet expired. So we don't update
961 * the ttl in this case and go beyond to do a WACK and query the old client
964 if( !registering_group_name
966 && (namerec->data.num_ips == 1)
967 && ip_equal( namerec->data.ip[0], from_ip )
968 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
969 update_name_ttl( namerec, ttl );
970 wins_hook("refresh", namerec, ttl);
971 send_wins_name_registration_response( 0, ttl, p );
976 * Finally if the name exists do a query to the registering machine
977 * to see if they still claim to have the name.
980 if( namerec != NULL ) {
981 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
982 struct userdata_struct *userdata = (struct userdata_struct *)ud;
985 * First send a WACK to the registering machine.
988 send_wins_wack_response(60, p);
991 * When the reply comes back we need the original packet.
992 * Lock this so it won't be freed and then put it into
993 * the userdata structure.
998 userdata = (struct userdata_struct *)ud;
1000 userdata->copy_fn = NULL;
1001 userdata->free_fn = NULL;
1002 userdata->userdata_len = sizeof(struct packet_struct *);
1003 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1006 * Use the new call to send a query directly to an IP address.
1007 * This sends the query directly to the IP address, and ensures
1008 * the recursion desired flag is not set (you were right Luke :-).
1009 * This function should *only* be called from the WINS server
1013 pull_ascii_nstring(name, sizeof(name), question->name);
1014 query_name_from_wins_server( *namerec->data.ip,
1016 question->name_type,
1017 wins_register_query_success,
1018 wins_register_query_fail,
1024 * Name did not exist - add it.
1027 pull_ascii_nstring(name, sizeof(name), question->name);
1028 add_name_to_subnet( subrec, name, question->name_type,
1029 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1031 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1032 get_global_id_and_update(&namerec->data.id, True);
1033 update_wins_owner(namerec, our_fake_ip);
1034 update_wins_flag(namerec, WINS_ACTIVE);
1035 wins_hook("add", namerec, ttl);
1038 send_wins_name_registration_response(0, ttl, p);
1041 /***********************************************************************
1042 Deal with a mutihomed name query success to the machine that
1043 requested the multihomed name registration.
1045 We have a locked pointer to the original packet stashed away in the
1047 ************************************************************************/
1049 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1050 struct userdata_struct *userdata,
1051 struct nmb_name *question_name,
1053 struct res_rec *answers)
1055 struct packet_struct *orig_reg_packet;
1056 struct nmb_packet *nmb;
1057 struct name_record *namerec = NULL;
1058 struct in_addr from_ip;
1060 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1062 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1064 nmb = &orig_reg_packet->packet.nmb;
1066 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1067 ttl = get_ttl_from_packet(nmb);
1070 * We want to just add the new IP, as we now know the requesting
1071 * machine claims to own it. But we can't just do that as an arbitary
1072 * amount of time may have taken place between the name query
1073 * request and this response. So we check that
1074 * the name still exists and is in the same state - if so
1075 * we just add the extra IP and update the ttl.
1078 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1080 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1081 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1082 a subsequent IP address.\n", nmb_namestr(question_name) ));
1083 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1085 orig_reg_packet->locked = False;
1086 free_packet(orig_reg_packet);
1091 if(!find_ip_in_name_record(namerec, from_ip)) {
1092 add_ip_to_name_record(namerec, from_ip);
1095 get_global_id_and_update(&namerec->data.id, True);
1096 update_wins_owner(namerec, our_fake_ip);
1097 update_wins_flag(namerec, WINS_ACTIVE);
1098 update_name_ttl(namerec, ttl);
1099 wins_hook("add", namerec, ttl);
1100 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1102 orig_reg_packet->locked = False;
1103 free_packet(orig_reg_packet);
1106 /***********************************************************************
1107 Deal with a name registration request query failure to a client that
1110 We have a locked pointer to the original packet stashed away in the
1112 ************************************************************************/
1114 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1115 struct response_record *rrec,
1116 struct nmb_name *question_name,
1119 struct userdata_struct *userdata = rrec->userdata;
1120 struct packet_struct *orig_reg_packet;
1122 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1124 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1125 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1126 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1128 orig_reg_packet->locked = False;
1129 free_packet(orig_reg_packet);
1133 /***********************************************************************
1134 Deal with a multihomed name registration request to a WINS server.
1135 These cannot be group name registrations.
1136 ***********************************************************************/
1138 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1139 struct packet_struct *p)
1141 struct nmb_packet *nmb = &p->packet.nmb;
1142 struct nmb_name *question = &nmb->question.question_name;
1143 BOOL bcast = nmb->header.nm_flags.bcast;
1144 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1145 int ttl = get_ttl_from_packet(nmb);
1146 struct name_record *namerec = NULL;
1147 struct in_addr from_ip;
1148 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1149 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1152 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1156 * We should only get unicast name registration packets here.
1157 * Anyone trying to register broadcast should not be going to a WINS
1158 * server. Log an error here.
1161 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1162 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1163 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1168 * Only unique names should be registered multihomed.
1172 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1173 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1174 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1178 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1179 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1182 * Deal with policy regarding 0x1d names.
1185 if(question->name_type == 0x1d) {
1186 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1187 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1188 send_wins_name_registration_response(0, ttl, p);
1193 * See if the name already exists.
1196 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1199 * if the record exists but NOT in active state,
1203 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1204 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1205 remove_name_from_namelist(subrec, namerec);
1210 * Deal with the case where the name found was a dns entry.
1211 * Remove it as we now have a NetBIOS client registering the
1215 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1216 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1217 - removing it.\n", nmb_namestr(question) ));
1218 remove_name_from_namelist( subrec, namerec);
1223 * Reject if the name exists and is not a REGISTER_NAME.
1224 * (ie. Don't allow any static names to be overwritten.
1227 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1228 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1229 to register name %s. Name already exists in WINS with source type %d.\n",
1230 nmb_namestr(question), namerec->data.source ));
1231 send_wins_name_registration_response(RFS_ERR, 0, p);
1236 * Reject if the name exists and is a GROUP name and is active.
1239 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1240 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1241 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1242 send_wins_name_registration_response(RFS_ERR, 0, p);
1247 * From here on down we know that if the name exists in the WINS db it is
1248 * a unique name, not a group name.
1252 * If the name exists and is one of our names then check the
1253 * registering IP address. If it's not one of ours then automatically
1254 * reject without doing the query - we know we will reject it.
1257 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1258 if(!ismyip(from_ip)) {
1259 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1260 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1261 send_wins_name_registration_response(RFS_ERR, 0, p);
1265 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1266 * update the ttl. Update the version ID to force replication.
1268 update_name_ttl(namerec, ttl);
1270 if(!find_ip_in_name_record(namerec, from_ip)) {
1271 get_global_id_and_update(&namerec->data.id, True);
1272 update_wins_owner(namerec, our_fake_ip);
1273 update_wins_flag(namerec, WINS_ACTIVE);
1275 add_ip_to_name_record(namerec, from_ip);
1278 wins_hook("refresh", namerec, ttl);
1279 send_wins_name_registration_response(0, ttl, p);
1285 * If the name exists and is active, check if the IP address is already registered
1286 * to that name. If so then update the ttl and reply success.
1289 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1290 update_name_ttl(namerec, ttl);
1293 * If it's a replica, we need to become the wins owner
1294 * to force the replication
1296 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1297 get_global_id_and_update(&namerec->data.id, True);
1298 update_wins_owner(namerec, our_fake_ip);
1299 update_wins_flag(namerec, WINS_ACTIVE);
1302 wins_hook("refresh", namerec, ttl);
1303 send_wins_name_registration_response(0, ttl, p);
1308 * If the name exists do a query to the owner
1309 * to see if they still want the name.
1312 if(namerec != NULL) {
1313 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1314 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1317 * First send a WACK to the registering machine.
1320 send_wins_wack_response(60, p);
1323 * When the reply comes back we need the original packet.
1324 * Lock this so it won't be freed and then put it into
1325 * the userdata structure.
1330 userdata = (struct userdata_struct *)ud;
1332 userdata->copy_fn = NULL;
1333 userdata->free_fn = NULL;
1334 userdata->userdata_len = sizeof(struct packet_struct *);
1335 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1338 * Use the new call to send a query directly to an IP address.
1339 * This sends the query directly to the IP address, and ensures
1340 * the recursion desired flag is not set (you were right Luke :-).
1341 * This function should *only* be called from the WINS server
1344 * Note that this packet is sent to the current owner of the name,
1345 * not the person who sent the packet
1348 pull_ascii_nstring( qname, sizeof(qname), question->name);
1349 query_name_from_wins_server( namerec->data.ip[0],
1351 question->name_type,
1352 wins_multihomed_register_query_success,
1353 wins_multihomed_register_query_fail,
1360 * Name did not exist - add it.
1363 pull_ascii_nstring( qname, sizeof(qname), question->name);
1364 add_name_to_subnet( subrec, qname, question->name_type,
1365 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1367 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1368 get_global_id_and_update(&namerec->data.id, True);
1369 update_wins_owner(namerec, our_fake_ip);
1370 update_wins_flag(namerec, WINS_ACTIVE);
1371 wins_hook("add", namerec, ttl);
1374 send_wins_name_registration_response(0, ttl, p);
1377 /***********************************************************************
1378 Deal with the special name query for *<1b>.
1379 ***********************************************************************/
1381 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1382 struct packet_struct *p)
1384 struct name_record *namerec = NULL;
1389 * Go through all the ACTIVE names in the WINS db looking for those
1390 * ending in <1b>. Use this to calculate the number of IP
1391 * addresses we need to return.
1395 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1396 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1397 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1398 num_ips += namerec->data.num_ips;
1403 * There are no 0x1b names registered. Return name query fail.
1405 send_wins_name_query_response(NAM_ERR, p, NULL);
1409 if((prdata = (char *)SMB_MALLOC( num_ips * 6 )) == NULL) {
1410 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1415 * Go through all the names again in the WINS db looking for those
1416 * ending in <1b>. Add their IP addresses into the list we will
1421 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1422 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1423 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1425 for(i = 0; i < namerec->data.num_ips; i++) {
1426 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1427 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1434 * Send back the reply containing the IP list.
1437 reply_netbios_packet(p, /* Packet to reply to. */
1438 0, /* Result code. */
1439 WINS_QUERY, /* nmbd type code. */
1440 NMB_NAME_QUERY_OPCODE, /* opcode. */
1441 lp_min_wins_ttl(), /* ttl. */
1442 prdata, /* data to send. */
1443 num_ips*6); /* data length. */
1448 /****************************************************************************
1449 Send a WINS name query response.
1450 **************************************************************************/
1452 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1453 struct name_record *namerec)
1456 char *prdata = rdata;
1457 int reply_data_len = 0;
1461 memset(rdata,'\0',6);
1464 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1466 /* Copy all known ip addresses into the return data. */
1467 /* Optimise for the common case of one IP address so we don't need a malloc. */
1469 if( namerec->data.num_ips == 1 ) {
1472 if((prdata = (char *)SMB_MALLOC( namerec->data.num_ips * 6 )) == NULL) {
1473 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1478 for(i = 0; i < namerec->data.num_ips; i++) {
1479 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1480 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1483 sort_query_replies(prdata, i, p->ip);
1484 reply_data_len = namerec->data.num_ips * 6;
1487 reply_netbios_packet(p, /* Packet to reply to. */
1488 rcode, /* Result code. */
1489 WINS_QUERY, /* nmbd type code. */
1490 NMB_NAME_QUERY_OPCODE, /* opcode. */
1492 prdata, /* data to send. */
1493 reply_data_len); /* data length. */
1495 if(prdata != rdata) {
1500 /***********************************************************************
1501 Deal with a name query.
1502 ***********************************************************************/
1504 void wins_process_name_query_request(struct subnet_record *subrec,
1505 struct packet_struct *p)
1507 struct nmb_packet *nmb = &p->packet.nmb;
1508 struct nmb_name *question = &nmb->question.question_name;
1509 struct name_record *namerec = NULL;
1512 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1513 nmb_namestr(question), inet_ntoa(p->ip) ));
1516 * Special name code. If the queried name is *<1b> then search
1517 * the entire WINS database and return a list of all the IP addresses
1518 * registered to any <1b> name. This is to allow domain master browsers
1519 * to discover other domains that may not have a presence on their subnet.
1522 pull_ascii_nstring(qname, sizeof(qname), question->name);
1523 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1524 process_wins_dmb_query_request( subrec, p);
1528 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1530 if(namerec != NULL) {
1532 * If the name is not anymore in active state then reply not found.
1533 * it's fair even if we keep it in the cache for days.
1535 if (!WINS_STATE_ACTIVE(namerec)) {
1536 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1537 nmb_namestr(question) ));
1538 send_wins_name_query_response(NAM_ERR, p, namerec);
1543 * If it's a DNSFAIL_NAME then reply name not found.
1546 if( namerec->data.source == DNSFAIL_NAME ) {
1547 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1548 nmb_namestr(question) ));
1549 send_wins_name_query_response(NAM_ERR, p, namerec);
1554 * If the name has expired then reply name not found.
1557 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1558 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1559 nmb_namestr(question) ));
1560 send_wins_name_query_response(NAM_ERR, p, namerec);
1564 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1565 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1567 send_wins_name_query_response(0, p, namerec);
1572 * Name not found in WINS - try a dns query if it's a 0x20 name.
1575 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1576 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1577 nmb_namestr(question) ));
1579 queue_dns_query(p, question, &namerec);
1584 * Name not found - return error.
1587 send_wins_name_query_response(NAM_ERR, p, NULL);
1590 /****************************************************************************
1591 Send a WINS name release response.
1592 **************************************************************************/
1594 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1596 struct nmb_packet *nmb = &p->packet.nmb;
1599 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1601 reply_netbios_packet(p, /* Packet to reply to. */
1602 rcode, /* Result code. */
1603 NMB_REL, /* nmbd type code. */
1604 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1606 rdata, /* data to send. */
1607 6); /* data length. */
1610 /***********************************************************************
1611 Deal with a name release.
1612 ***********************************************************************/
1614 void wins_process_name_release_request(struct subnet_record *subrec,
1615 struct packet_struct *p)
1617 struct nmb_packet *nmb = &p->packet.nmb;
1618 struct nmb_name *question = &nmb->question.question_name;
1619 BOOL bcast = nmb->header.nm_flags.bcast;
1620 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1621 struct name_record *namerec = NULL;
1622 struct in_addr from_ip;
1623 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1625 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1629 * We should only get unicast name registration packets here.
1630 * Anyone trying to register broadcast should not be going to a WINS
1631 * server. Log an error here.
1634 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1635 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1636 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1640 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1641 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1644 * Deal with policy regarding 0x1d names.
1647 if(!releasing_group_name && (question->name_type == 0x1d)) {
1648 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1649 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1650 send_wins_name_release_response(0, p);
1655 * See if the name already exists.
1658 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1660 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
1661 send_wins_name_release_response(NAM_ERR, p);
1666 * Check that the sending machine has permission to release this name.
1667 * If it's a group name not ending in 0x1c then just say yes and let
1668 * the group time out.
1671 if(releasing_group_name && (question->name_type != 0x1c)) {
1672 send_wins_name_release_response(0, p);
1677 * Check that the releasing node is on the list of IP addresses
1678 * for this name. Disallow the release if not.
1681 if(!find_ip_in_name_record(namerec, from_ip)) {
1682 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1683 release name %s as IP %s is not one of the known IP's for this name.\n",
1684 nmb_namestr(question), inet_ntoa(from_ip) ));
1685 send_wins_name_release_response(NAM_ERR, p);
1690 * Check if the record is active. IF it's already released
1691 * or tombstoned, refuse the release.
1694 if (!WINS_STATE_ACTIVE(namerec)) {
1695 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1696 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
1697 send_wins_name_release_response(NAM_ERR, p);
1702 * Check if the record is a 0x1c group
1703 * and has more then one ip
1704 * remove only this address.
1707 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
1708 remove_ip_from_name_record(namerec, from_ip);
1709 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1710 inet_ntoa(from_ip),nmb_namestr(question)));
1711 wins_hook("delete", namerec, 0);
1712 send_wins_name_release_response(0, p);
1717 * Send a release response.
1718 * Flag the name as released and update the ttl
1721 namerec->data.wins_flags |= WINS_RELEASED;
1722 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1724 wins_hook("delete", namerec, 0);
1725 send_wins_name_release_response(0, p);
1728 /*******************************************************************
1729 WINS time dependent processing.
1730 ******************************************************************/
1732 void initiate_wins_processing(time_t t)
1734 static time_t lasttime = 0;
1735 struct name_record *namerec;
1736 struct name_record *next_namerec;
1737 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1741 if (t - lasttime < 20)
1746 if(!lp_we_are_a_wins_server())
1749 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1751 namerec = next_namerec ) {
1752 next_namerec = (struct name_record *)ubi_trNext( namerec );
1754 if( (namerec->data.death_time != PERMANENT_TTL)
1755 && (namerec->data.death_time < t) ) {
1757 if( namerec->data.source == SELF_NAME ) {
1758 DEBUG( 3, ( "initiate_wins_processing: Subnet %s not expiring SELF name %s\n",
1759 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1760 namerec->data.death_time += 300;
1761 namerec->subnet->namelist_changed = True;
1763 } else if (namerec->data.source == DNS_NAME || namerec->data.source == DNSFAIL_NAME) {
1764 DEBUG(3,("initiate_wins_processing: deleting timed out DNS name %s\n",
1765 nmb_namestr(&namerec->name)));
1766 remove_name_from_namelist( wins_server_subnet, namerec );
1770 /* handle records, samba is the wins owner */
1771 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1772 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1774 namerec->data.wins_flags&=~WINS_STATE_MASK;
1775 namerec->data.wins_flags|=WINS_RELEASED;
1776 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1777 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1780 namerec->data.wins_flags&=~WINS_STATE_MASK;
1781 namerec->data.wins_flags|=WINS_TOMBSTONED;
1782 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1783 get_global_id_and_update(&namerec->data.id, True);
1784 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1786 case WINS_TOMBSTONED:
1787 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1788 remove_name_from_namelist( wins_server_subnet, namerec );
1792 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1794 /* that's not as MS says it should be */
1795 namerec->data.wins_flags&=~WINS_STATE_MASK;
1796 namerec->data.wins_flags|=WINS_TOMBSTONED;
1797 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1798 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1799 case WINS_TOMBSTONED:
1800 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1801 remove_name_from_namelist( wins_server_subnet, namerec );
1804 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1805 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1813 if(wins_server_subnet->namelist_changed)
1814 wins_write_database(True);
1816 wins_server_subnet->namelist_changed = False;
1819 /*******************************************************************
1820 Write out the current WINS database.
1821 ******************************************************************/
1823 void wins_write_database(BOOL background)
1825 struct name_record *namerec;
1826 pstring fname, fnamenew;
1830 if(!lp_we_are_a_wins_server())
1833 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1841 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1842 all_string_sub(fname,"//", "/", 0);
1843 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1845 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
1846 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1853 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1855 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1857 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1861 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1863 if( namerec->data.death_time != PERMANENT_TTL ) {
1866 tm = localtime(&namerec->data.death_time);
1868 nl = strrchr( ts, '\n' );
1872 DEBUGADD(4,("TTL = %s ", ts ));
1874 DEBUGADD(4,("TTL = PERMANENT "));
1877 for (i = 0; i < namerec->data.num_ips; i++) {
1878 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1880 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1882 if( namerec->data.source == REGISTER_NAME ) {
1884 pull_ascii_nstring(name, sizeof(name), namerec->name.name);
1885 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
1886 (int)namerec->data.death_time);
1888 for (i = 0; i < namerec->data.num_ips; i++)
1889 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1890 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1895 chmod(fnamenew,0644);
1897 rename(fnamenew,fname);
1904 Until winsrepl is done.
1905 /****************************************************************************
1906 Process a internal Samba message receiving a wins record.
1907 ***************************************************************************/
1909 void nmbd_wins_new_entry(int msg_type, struct process_id src,
1910 void *buf, size_t len)
1912 WINS_RECORD *record;
1913 struct name_record *namerec = NULL;
1914 struct name_record *new_namerec = NULL;
1915 struct nmb_name question;
1916 BOOL overwrite=False;
1917 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1924 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1925 record=(WINS_RECORD *)buf;
1927 make_nmb_name(&question, record->name, record->type);
1929 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1931 /* record doesn't exist, add it */
1932 if (namerec == NULL) {
1933 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1934 record->name, record->type, inet_ntoa(record->wins_ip)));
1936 new_namerec=add_name_to_subnet( wins_server_subnet,
1940 EXTINCTION_INTERVAL,
1945 if (new_namerec!=NULL) {
1946 update_wins_owner(new_namerec, record->wins_ip);
1947 update_wins_flag(new_namerec, record->wins_flags);
1948 new_namerec->data.id=record->id;
1950 wins_server_subnet->namelist_changed = True;
1954 /* check if we have a conflict */
1955 if (namerec != NULL) {
1956 /* both records are UNIQUE */
1957 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1959 /* the database record is a replica */
1960 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1961 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1962 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1967 /* we are the wins owner of the database record */
1968 /* the 2 records have the same IP address */
1969 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1970 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1971 get_global_id_and_update(&namerec->data.id, True);
1976 /* the 2 records have different IP address */
1977 if (namerec->data.wins_flags&WINS_ACTIVE) {
1978 if (record->wins_flags&WINS_TOMBSTONED)
1979 get_global_id_and_update(&namerec->data.id, True);
1980 if (record->wins_flags&WINS_ACTIVE)
1981 /* send conflict challenge to the replica node */
1990 /* the replica is a standard group */
1991 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1992 /* if the database record is unique and active force a name release */
1993 if (namerec->data.wins_flags&WINS_UNIQUE)
1994 /* send a release name to the unique node */
2000 /* the replica is a special group */
2001 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
2002 if (namerec->data.wins_flags&WINS_ACTIVE) {
2003 for (i=0; i<record->num_ips; i++)
2004 if(!find_ip_in_name_record(namerec, record->ip[i]))
2005 add_ip_to_name_record(namerec, record->ip[i]);
2011 /* the replica is a multihomed host */
2013 /* I'm giving up on multi homed. Too much complex to understand */
2015 if (record->wins_flags&WINS_MHOMED) {
2016 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2017 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2021 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2024 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
2025 if (namerec->data.wins_flags&WINS_UNIQUE)
2026 get_global_id_and_update(&namerec->data.id, True);
2030 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2031 if (namerec->data.wins_flags&WINS_UNIQUE ||
2032 namerec->data.wins_flags&WINS_MHOMED)
2033 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2038 if (overwrite == False)
2039 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2040 record->name, record->type, inet_ntoa(record->wins_ip)));
2042 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2043 record->name, record->type, inet_ntoa(record->wins_ip)));
2045 /* remove the old record and add a new one */
2046 remove_name_from_namelist( wins_server_subnet, namerec );
2047 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2048 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2049 if (new_namerec!=NULL) {
2050 update_wins_owner(new_namerec, record->wins_ip);
2051 update_wins_flag(new_namerec, record->wins_flags);
2052 new_namerec->data.id=record->id;
2054 wins_server_subnet->namelist_changed = True;
2057 wins_server_subnet->namelist_changed = True;