2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-1998
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 *****************************************************************************/
31 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
35 namerec->data.wins_ip=wins_ip;
38 /****************************************************************************
39 create the wins flags based on the nb flags and the input value.
40 *****************************************************************************/
41 static void update_wins_flag(struct name_record *namerec, int flags)
46 namerec->data.wins_flags=0x0;
48 /* if it's a group, it can be a normal or a special one */
49 if (namerec->data.nb_flags & NB_GROUP) {
50 if (namerec->name.name_type==0x1C)
51 namerec->data.wins_flags|=WINS_SGROUP;
53 if (namerec->data.num_ips>1)
54 namerec->data.wins_flags|=WINS_SGROUP;
56 namerec->data.wins_flags|=WINS_NGROUP;
58 /* can be unique or multi-homed */
59 if (namerec->data.num_ips>1)
60 namerec->data.wins_flags|=WINS_MHOMED;
62 namerec->data.wins_flags|=WINS_UNIQUE;
65 /* the node type are the same bits */
66 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
68 /* the static bit is elsewhere */
69 if (namerec->data.death_time == PERMANENT_TTL)
70 namerec->data.wins_flags|=WINS_STATIC;
72 /* and add the given bits */
73 namerec->data.wins_flags|=flags;
75 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
76 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
80 /****************************************************************************
81 return the general ID value and increase it if requested
82 *****************************************************************************/
83 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
86 * it's kept as a static here, to prevent people from messing
87 * with the value directly
90 static SMB_BIG_UINT general_id = 1;
92 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
94 *current_id = general_id;
100 /****************************************************************************
101 possibly call the WINS hook external program when a WINS change is made
102 *****************************************************************************/
103 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
106 char *cmd = lp_wins_hook();
110 if (!cmd || !*cmd) return;
112 for (p=namerec->name.name; *p; p++) {
113 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
114 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
120 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
124 namerec->name.name_type,
127 for (i=0;i<namerec->data.num_ips;i++) {
128 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
131 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
132 smbrun(command, NULL);
136 /****************************************************************************
137 Determine if this packet should be allocated to the WINS server.
138 *****************************************************************************/
140 BOOL packet_is_for_wins_server(struct packet_struct *packet)
142 struct nmb_packet *nmb = &packet->packet.nmb;
144 /* Only unicast packets go to a WINS server. */
145 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
147 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
151 /* Check for node status requests. */
152 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
155 switch(nmb->header.opcode)
158 * A WINS server issues WACKS, not receives them.
160 case NMB_WACK_OPCODE:
161 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
164 * A WINS server only processes registration and
165 * release requests, not responses.
167 case NMB_NAME_REG_OPCODE:
168 case NMB_NAME_MULTIHOMED_REG_OPCODE:
169 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
170 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
171 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)
181 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
187 * Only process unicast name queries with rd = 1.
189 case NMB_NAME_QUERY_OPCODE:
190 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
192 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
201 /****************************************************************************
202 Utility function to decide what ttl to give a register/refresh request.
203 *****************************************************************************/
205 static int get_ttl_from_packet(struct nmb_packet *nmb)
207 int ttl = nmb->additional->ttl;
209 if(ttl < lp_min_wins_ttl() )
210 ttl = lp_min_wins_ttl();
212 if(ttl > lp_max_wins_ttl() )
213 ttl = lp_max_wins_ttl();
218 /****************************************************************************
219 Load or create the WINS database.
220 *****************************************************************************/
222 BOOL initialise_wins(void)
224 time_t time_now = time(NULL);
228 if(!lp_we_are_a_wins_server())
231 add_samba_names_to_subnet(wins_server_subnet);
233 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL)
235 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
236 WINS_LIST, strerror(errno) ));
242 pstring name_str, ip_str, ttl_str, nb_flags_str;
243 unsigned int num_ips;
245 struct in_addr *ip_list;
257 /* Read a line from the wins.dat file. Strips whitespace
258 from the beginning and end of the line.
260 if (!fgets_slash(line,sizeof(pstring),fp))
266 if (strncmp(line,"VERSION ", 8) == 0) {
267 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
268 version != WINS_VERSION) {
269 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
279 * Now we handle multiple IP addresses per name we need
280 * to iterate over the line twice. The first time to
281 * determine how many IP addresses there are, the second
282 * time to actually parse them into the ip_list array.
285 if (!next_token(&ptr,name_str,NULL,sizeof(name_str)))
287 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
291 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
293 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
298 * Determine the number of IP addresses per line.
303 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
306 if(got_token && strchr(ip_str, '.'))
311 } while( got_token && was_ip);
315 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
321 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
325 /* Allocate the space for the ip_list. */
326 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
328 DEBUG(0,("initialise_wins: Malloc fail !\n"));
332 /* Reset and re-parse the line. */
334 next_token(&ptr,name_str,NULL,sizeof(name_str));
335 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
336 for(i = 0; i < num_ips; i++)
338 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
339 ip_list[i] = *interpret_addr2(ip_str);
341 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
344 * Deal with SELF or REGISTER name encoding. Default is REGISTER
345 * for compatibility with old nmbds.
348 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
350 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
355 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
356 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
358 /* Netbios name. # divides the name from the type (hex): netbios#xx */
359 pstrcpy(name,name_str);
361 if((p = strchr(name,'#')) != NULL)
364 sscanf(p+1,"%x",&type);
367 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
368 sscanf(nb_flags_str,"%x",&nb_flags);
369 sscanf(ttl_str,"%d",&ttl);
371 /* add all entries that have 60 seconds or more to live */
372 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
374 if(ttl != PERMANENT_TTL)
377 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
378 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
380 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
381 ttl, REGISTER_NAME, num_ips, ip_list );
386 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %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 &&
413 nmb->header.response) rdata[0] |= 0x4;
414 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
415 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
416 if (nmb->header.nm_flags.recursion_available &&
417 nmb->header.response) rdata[1] |= 0x80;
418 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
420 reply_netbios_packet(p, /* Packet to reply to. */
421 0, /* Result code. */
422 NMB_WAIT_ACK, /* nmbd type code. */
423 NMB_WACK_OPCODE, /* opcode. */
425 (char *)rdata, /* data to send. */
426 2); /* data length. */
429 /****************************************************************************
430 Send a WINS name registration response.
431 **************************************************************************/
433 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
435 struct nmb_packet *nmb = &p->packet.nmb;
438 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
440 reply_netbios_packet(p, /* Packet to reply to. */
441 rcode, /* Result code. */
442 WINS_REG, /* nmbd type code. */
443 NMB_NAME_REG_OPCODE, /* opcode. */
445 rdata, /* data to send. */
446 6); /* data length. */
449 /***********************************************************************
450 Deal with a name refresh request to a WINS server.
451 ************************************************************************/
453 void wins_process_name_refresh_request(struct subnet_record *subrec,
454 struct packet_struct *p)
456 struct nmb_packet *nmb = &p->packet.nmb;
457 struct nmb_name *question = &nmb->question.question_name;
458 BOOL bcast = nmb->header.nm_flags.bcast;
459 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
460 BOOL group = (nb_flags & NB_GROUP) ? True : False;
461 struct name_record *namerec = NULL;
462 int ttl = get_ttl_from_packet(nmb);
463 struct in_addr from_ip;
464 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
466 putip((char *)&from_ip,&nmb->additional->rdata[2]);
471 * We should only get unicast name refresh packets here.
472 * Anyone trying to refresh broadcast should not be going to a WINS
473 * server. Log an error here.
476 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
477 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
478 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
482 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
483 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
486 * See if the name already exists.
489 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
492 * If this is a refresh request and the name doesn't exist then
493 * treat it like a registration request. This allows us to recover
494 * from errors (tridge)
499 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
500 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
501 wins_process_name_registration_request(subrec,p);
506 * if the name is present but not active,
507 * simply remove it and treat the request
510 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
512 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
513 not active - removing it.\n", nmb_namestr(question) ));
514 remove_name_from_namelist( subrec, namerec );
516 wins_process_name_registration_request(subrec,p);
521 * Check that the group bits for the refreshing name and the
522 * name in our database match.
525 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
527 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
528 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
529 send_wins_name_registration_response(RFS_ERR, 0, p);
534 * For a unique name check that the person refreshing the name is one of the registered IP
535 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
536 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
537 * and return success.
540 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
545 update_name_ttl(namerec, ttl);
548 * if the record is a replica:
549 * we take ownership and update the version ID.
551 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
552 update_wins_owner(namerec, our_fake_ip);
553 get_global_id_and_update(&namerec->data.id, True);
556 send_wins_name_registration_response(0, ttl, p);
557 wins_hook("refresh", namerec, ttl);
563 * Normal groups are all registered with an IP address of 255.255.255.255
564 * so we can't search for the IP address.
566 update_name_ttl(namerec, ttl);
567 send_wins_name_registration_response(0, ttl, p);
570 else if(!group && (question->name_type == 0x1d))
573 * Special name type - just pretend the refresh succeeded.
575 send_wins_name_registration_response(0, ttl, p);
584 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
585 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
586 send_wins_name_registration_response(RFS_ERR, 0, p);
591 /***********************************************************************
592 Deal with a name registration request query success to a client that
595 We have a locked pointer to the original packet stashed away in the
596 userdata pointer. The success here is actually a failure as it means
597 the client we queried wants to keep the name, so we must return
598 a registration failure to the original requestor.
599 ************************************************************************/
601 static void wins_register_query_success(struct subnet_record *subrec,
602 struct userdata_struct *userdata,
603 struct nmb_name *question_name,
605 struct res_rec *answers)
607 struct packet_struct *orig_reg_packet;
609 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
611 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
612 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
614 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
616 orig_reg_packet->locked = False;
617 free_packet(orig_reg_packet);
620 /***********************************************************************
621 Deal with a name registration request query failure to a client that
624 We have a locked pointer to the original packet stashed away in the
625 userdata pointer. The failure here is actually a success as it means
626 the client we queried didn't want to keep the name, so we can remove
627 the old name record and then successfully add the new name.
628 ************************************************************************/
630 static void wins_register_query_fail(struct subnet_record *subrec,
631 struct response_record *rrec,
632 struct nmb_name *question_name,
635 struct userdata_struct *userdata = rrec->userdata;
636 struct packet_struct *orig_reg_packet;
637 struct name_record *namerec = NULL;
639 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
642 * We want to just add the name, as we now know the original owner
643 * didn't want it. But we can't just do that as an arbitary
644 * amount of time may have taken place between the name query
645 * request and this timeout/error response. So we check that
646 * the name still exists and is in the same state - if so
647 * we remove it and call wins_process_name_registration_request()
648 * as we know it will do the right thing now.
651 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
653 if( (namerec != NULL)
654 && (namerec->data.source == REGISTER_NAME)
655 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
657 remove_name_from_namelist( subrec, namerec);
662 wins_process_name_registration_request(subrec, orig_reg_packet);
664 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
665 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
667 orig_reg_packet->locked = False;
668 free_packet(orig_reg_packet);
671 /***********************************************************************
672 Deal with a name registration request to a WINS server.
674 Use the following pseudocode :
682 | +--- existing name is group
685 | | +--- add name (return).
688 | +--- exiting name is unique
691 | +--- query existing owner (return).
694 +--------name doesn't exist
697 +--- add name (return).
705 | +--- existing name is group
708 | | +--- fail add (return).
711 | +--- exiting name is unique
714 | +--- query existing owner (return).
717 +--------name doesn't exist
720 +--- add name (return).
722 As can be seen from the above, the two cases may be collapsed onto each
723 other with the exception of the case where the name already exists and
724 is a group name. This case we handle with an if statement.
726 ************************************************************************/
728 void wins_process_name_registration_request(struct subnet_record *subrec,
729 struct packet_struct *p)
731 struct nmb_packet *nmb = &p->packet.nmb;
732 struct nmb_name *question = &nmb->question.question_name;
733 BOOL bcast = nmb->header.nm_flags.bcast;
734 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
735 int ttl = get_ttl_from_packet(nmb);
736 struct name_record *namerec = NULL;
737 struct in_addr from_ip;
738 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
739 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
741 putip((char *)&from_ip,&nmb->additional->rdata[2]);
746 * We should only get unicast name registration packets here.
747 * Anyone trying to register broadcast should not be going to a WINS
748 * server. Log an error here.
751 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
752 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
753 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
757 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
758 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
761 * See if the name already exists.
764 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
767 * if the record exists but NOT in active state,
770 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
772 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
773 not active - removing it.\n", nmb_namestr(question) ));
774 remove_name_from_namelist( subrec, namerec );
779 * Deal with the case where the name found was a dns entry.
780 * Remove it as we now have a NetBIOS client registering the
784 if( (namerec != NULL)
785 && ( (namerec->data.source == DNS_NAME)
786 || (namerec->data.source == DNSFAIL_NAME) ) )
788 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
789 a dns lookup - removing it.\n", nmb_namestr(question) ));
790 remove_name_from_namelist( subrec, namerec );
795 * Reject if the name exists and is not a REGISTER_NAME.
796 * (ie. Don't allow any static names to be overwritten.
799 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
801 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
802 to register name %s. Name already exists in WINS with source type %d.\n",
803 nmb_namestr(question), namerec->data.source ));
804 send_wins_name_registration_response(RFS_ERR, 0, p);
809 * Special policy decisions based on MS documentation.
810 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
811 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
815 * A group name is always added as the local broadcast address, except
816 * for group names ending in 0x1c.
817 * Group names with type 0x1c are registered with individual IP addresses.
820 if(registering_group_name && (question->name_type != 0x1c))
821 from_ip = *interpret_addr2("255.255.255.255");
824 * Ignore all attempts to register a unique 0x1d name, although return success.
827 if(!registering_group_name && (question->name_type == 0x1d))
829 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
830 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
831 send_wins_name_registration_response(0, ttl, p);
836 * Next two cases are the 'if statement' mentioned above.
839 if((namerec != NULL) && NAME_GROUP(namerec))
841 if(registering_group_name)
844 * If we are adding a group name, the name exists and is also a group entry just add this
845 * IP address to it and update the ttl.
848 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
849 inet_ntoa(from_ip), nmb_namestr(question) ));
851 * Check the ip address is not already in the group.
853 if(!find_ip_in_name_record(namerec, from_ip)) {
854 add_ip_to_name_record(namerec, from_ip);
855 /* we need to update the record for replication */
856 get_global_id_and_update(&namerec->data.id, True);
859 * if the record is a replica, we must change
860 * the wins owner to us to make the replication updates
861 * it on the other wins servers.
862 * And when the partner will receive this record,
863 * it will update its own record.
866 update_wins_owner(namerec, our_fake_ip);
869 update_name_ttl(namerec, ttl);
870 send_wins_name_registration_response(0, ttl, p);
876 * If we are adding a unique name, the name exists in the WINS db
877 * and is a group name then reject the registration.
879 * explanation: groups have a higher priority than unique names.
882 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
883 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
884 send_wins_name_registration_response(RFS_ERR, 0, p);
890 * From here on down we know that if the name exists in the WINS db it is
891 * a unique name, not a group name.
895 * If the name exists and is one of our names then check the
896 * registering IP address. If it's not one of ours then automatically
897 * reject without doing the query - we know we will reject it.
900 if((namerec != NULL) && (is_myname(namerec->name.name)) )
904 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
905 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
906 send_wins_name_registration_response(RFS_ERR, 0, p);
912 * It's one of our names and one of our IP's - update the ttl.
914 update_name_ttl(namerec, ttl);
915 send_wins_name_registration_response(0, ttl, p);
916 wins_hook("refresh", namerec, ttl);
922 * If the name exists and it is a unique registration and the registering IP
923 * is the same as the (single) already registered IP then just update the ttl.
925 * But not if the record is an active replica. IF it's a replica, it means it can be
926 * the same client which has moved and not yet expired. So we don't update
927 * the ttl in this case and go beyond to do a WACK and query the old client
930 if( !registering_group_name
932 && (namerec->data.num_ips == 1)
933 && ip_equal( namerec->data.ip[0], from_ip )
934 && ip_equal(namerec->data.wins_ip, our_fake_ip) )
936 update_name_ttl( namerec, ttl );
937 send_wins_name_registration_response( 0, ttl, p );
938 wins_hook("refresh", namerec, ttl);
943 * Finally if the name exists do a query to the registering machine
944 * to see if they still claim to have the name.
947 if( namerec != NULL )
949 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
950 struct userdata_struct *userdata = (struct userdata_struct *)ud;
953 * First send a WACK to the registering machine.
956 send_wins_wack_response(60, p);
959 * When the reply comes back we need the original packet.
960 * Lock this so it won't be freed and then put it into
961 * the userdata structure.
966 userdata = (struct userdata_struct *)ud;
968 userdata->copy_fn = NULL;
969 userdata->free_fn = NULL;
970 userdata->userdata_len = sizeof(struct packet_struct *);
971 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
974 * Use the new call to send a query directly to an IP address.
975 * This sends the query directly to the IP address, and ensures
976 * the recursion desired flag is not set (you were right Luke :-).
977 * This function should *only* be called from the WINS server
981 query_name_from_wins_server( *namerec->data.ip,
984 wins_register_query_success,
985 wins_register_query_fail,
991 * Name did not exist - add it.
994 (void)add_name_to_subnet( subrec, question->name, question->name_type,
995 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
996 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
997 get_global_id_and_update(&namerec->data.id, True);
998 update_wins_owner(namerec, our_fake_ip);
999 update_wins_flag(namerec, WINS_ACTIVE);
1000 wins_hook("add", namerec, ttl);
1003 send_wins_name_registration_response(0, ttl, p);
1006 /***********************************************************************
1007 Deal with a mutihomed name query success to the machine that
1008 requested the multihomed name registration.
1010 We have a locked pointer to the original packet stashed away in the
1012 ************************************************************************/
1014 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
1015 struct userdata_struct *userdata,
1016 struct nmb_name *question_name,
1018 struct res_rec *answers)
1020 struct packet_struct *orig_reg_packet;
1021 struct nmb_packet *nmb;
1022 struct name_record *namerec = NULL;
1023 struct in_addr from_ip;
1025 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1027 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1029 nmb = &orig_reg_packet->packet.nmb;
1031 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1032 ttl = get_ttl_from_packet(nmb);
1035 * We want to just add the new IP, as we now know the requesting
1036 * machine claims to own it. But we can't just do that as an arbitary
1037 * amount of time may have taken place between the name query
1038 * request and this response. So we check that
1039 * the name still exists and is in the same state - if so
1040 * we just add the extra IP and update the ttl.
1043 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1045 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
1047 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1048 a subsequent IP address.\n", nmb_namestr(question_name) ));
1049 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1051 orig_reg_packet->locked = False;
1052 free_packet(orig_reg_packet);
1057 if(!find_ip_in_name_record(namerec, from_ip))
1058 add_ip_to_name_record(namerec, from_ip);
1060 get_global_id_and_update(&namerec->data.id, True);
1061 update_wins_owner(namerec, our_fake_ip);
1062 update_wins_flag(namerec, WINS_ACTIVE);
1063 update_name_ttl(namerec, ttl);
1064 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1065 wins_hook("add", namerec, ttl);
1067 orig_reg_packet->locked = False;
1068 free_packet(orig_reg_packet);
1071 /***********************************************************************
1072 Deal with a name registration request query failure to a client that
1075 We have a locked pointer to the original packet stashed away in the
1077 ************************************************************************/
1079 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1080 struct response_record *rrec,
1081 struct nmb_name *question_name,
1084 struct userdata_struct *userdata = rrec->userdata;
1085 struct packet_struct *orig_reg_packet;
1087 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1089 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1090 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1091 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1093 orig_reg_packet->locked = False;
1094 free_packet(orig_reg_packet);
1098 /***********************************************************************
1099 Deal with a multihomed name registration request to a WINS server.
1100 These cannot be group name registrations.
1101 ***********************************************************************/
1103 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1104 struct packet_struct *p)
1106 struct nmb_packet *nmb = &p->packet.nmb;
1107 struct nmb_name *question = &nmb->question.question_name;
1108 BOOL bcast = nmb->header.nm_flags.bcast;
1109 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1110 int ttl = get_ttl_from_packet(nmb);
1111 struct name_record *namerec = NULL;
1112 struct in_addr from_ip;
1113 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1114 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1116 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1121 * We should only get unicast name registration packets here.
1122 * Anyone trying to register broadcast should not be going to a WINS
1123 * server. Log an error here.
1126 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1127 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1128 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1133 * Only unique names should be registered multihomed.
1138 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1139 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1140 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1144 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1145 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1148 * Deal with policy regarding 0x1d names.
1151 if(question->name_type == 0x1d)
1153 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1154 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1155 send_wins_name_registration_response(0, ttl, p);
1160 * See if the name already exists.
1163 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1166 * if the record exists but NOT in active state,
1169 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1170 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1171 remove_name_from_namelist(subrec, namerec);
1176 * Deal with the case where the name found was a dns entry.
1177 * Remove it as we now have a NetBIOS client registering the
1181 if( (namerec != NULL)
1182 && ( (namerec->data.source == DNS_NAME)
1183 || (namerec->data.source == DNSFAIL_NAME) ) )
1185 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1186 - removing it.\n", nmb_namestr(question) ));
1187 remove_name_from_namelist( subrec, namerec);
1192 * Reject if the name exists and is not a REGISTER_NAME.
1193 * (ie. Don't allow any static names to be overwritten.
1196 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1198 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1199 to register name %s. Name already exists in WINS with source type %d.\n",
1200 nmb_namestr(question), namerec->data.source ));
1201 send_wins_name_registration_response(RFS_ERR, 0, p);
1206 * Reject if the name exists and is a GROUP name and is active.
1209 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
1211 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1212 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1213 send_wins_name_registration_response(RFS_ERR, 0, p);
1218 * From here on down we know that if the name exists in the WINS db it is
1219 * a unique name, not a group name.
1223 * If the name exists and is one of our names then check the
1224 * registering IP address. If it's not one of ours then automatically
1225 * reject without doing the query - we know we will reject it.
1228 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1230 if(!ismyip(from_ip))
1232 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1233 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1234 send_wins_name_registration_response(RFS_ERR, 0, p);
1240 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1241 * update the ttl. Update the version ID to force replication.
1243 if(!find_ip_in_name_record(namerec, from_ip)) {
1244 get_global_id_and_update(&namerec->data.id, True);
1245 update_wins_owner(namerec, our_fake_ip);
1246 update_wins_flag(namerec, WINS_ACTIVE);
1248 add_ip_to_name_record(namerec, from_ip);
1249 wins_hook("add", namerec, ttl);
1251 wins_hook("refresh", namerec, ttl);
1254 update_name_ttl(namerec, ttl);
1255 send_wins_name_registration_response(0, ttl, p);
1261 * If the name exists and is active, check if the IP address is already registered
1262 * to that name. If so then update the ttl and reply success.
1265 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
1267 update_name_ttl(namerec, ttl);
1269 * If it's a replica, we need to become the wins owner
1270 * to force the replication
1272 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1273 get_global_id_and_update(&namerec->data.id, True);
1274 update_wins_owner(namerec, our_fake_ip);
1275 update_wins_flag(namerec, WINS_ACTIVE);
1278 send_wins_name_registration_response(0, ttl, p);
1279 wins_hook("refresh", namerec, ttl);
1284 * If the name exists do a query to the owner
1285 * to see if they still want the name.
1290 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1291 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1294 * First send a WACK to the registering machine.
1297 send_wins_wack_response(60, p);
1300 * When the reply comes back we need the original packet.
1301 * Lock this so it won't be freed and then put it into
1302 * the userdata structure.
1307 userdata = (struct userdata_struct *)ud;
1309 userdata->copy_fn = NULL;
1310 userdata->free_fn = NULL;
1311 userdata->userdata_len = sizeof(struct packet_struct *);
1312 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1315 * Use the new call to send a query directly to an IP address.
1316 * This sends the query directly to the IP address, and ensures
1317 * the recursion desired flag is not set (you were right Luke :-).
1318 * This function should *only* be called from the WINS server
1321 * Note that this packet is sent to the current owner of the name,
1322 * not the person who sent the packet
1325 query_name_from_wins_server( namerec->data.ip[0],
1327 question->name_type,
1328 wins_multihomed_register_query_success,
1329 wins_multihomed_register_query_fail,
1336 * Name did not exist - add it.
1339 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1340 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1342 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1343 get_global_id_and_update(&namerec->data.id, True);
1344 update_wins_owner(namerec, our_fake_ip);
1345 update_wins_flag(namerec, WINS_ACTIVE);
1346 wins_hook("add", namerec, ttl);
1349 send_wins_name_registration_response(0, ttl, p);
1352 /***********************************************************************
1353 Deal with the special name query for *<1b>.
1354 ***********************************************************************/
1356 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1357 struct packet_struct *p)
1359 struct name_record *namerec = NULL;
1364 * Go through all the ACTIVE names in the WINS db looking for those
1365 * ending in <1b>. Use this to calculate the number of IP
1366 * addresses we need to return.
1370 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1372 namerec = (struct name_record *)ubi_trNext( namerec ) )
1374 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1375 num_ips += namerec->data.num_ips;
1381 * There are no 0x1b names registered. Return name query fail.
1383 send_wins_name_query_response(NAM_ERR, p, NULL);
1387 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1389 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1394 * Go through all the names again in the WINS db looking for those
1395 * ending in <1b>. Add their IP addresses into the list we will
1400 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1402 namerec = (struct name_record *)ubi_trNext( namerec ) )
1404 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
1407 for(i = 0; i < namerec->data.num_ips; i++)
1409 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1410 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1417 * Send back the reply containing the IP list.
1420 reply_netbios_packet(p, /* Packet to reply to. */
1421 0, /* Result code. */
1422 WINS_QUERY, /* nmbd type code. */
1423 NMB_NAME_QUERY_OPCODE, /* opcode. */
1424 lp_min_wins_ttl(), /* ttl. */
1425 prdata, /* data to send. */
1426 num_ips*6); /* data length. */
1431 /****************************************************************************
1432 Send a WINS name query response.
1433 **************************************************************************/
1435 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1436 struct name_record *namerec)
1439 char *prdata = rdata;
1440 int reply_data_len = 0;
1444 memset(rdata,'\0',6);
1448 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1449 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1451 /* Copy all known ip addresses into the return data. */
1452 /* Optimise for the common case of one IP address so
1453 we don't need a malloc. */
1455 if( namerec->data.num_ips == 1 )
1459 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1461 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1466 for(i = 0; i < namerec->data.num_ips; i++)
1468 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1469 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1472 sort_query_replies(prdata, i, p->ip);
1474 reply_data_len = namerec->data.num_ips * 6;
1477 reply_netbios_packet(p, /* Packet to reply to. */
1478 rcode, /* Result code. */
1479 WINS_QUERY, /* nmbd type code. */
1480 NMB_NAME_QUERY_OPCODE, /* opcode. */
1482 prdata, /* data to send. */
1483 reply_data_len); /* data length. */
1489 /***********************************************************************
1490 Deal with a name query.
1491 ***********************************************************************/
1493 void wins_process_name_query_request(struct subnet_record *subrec,
1494 struct packet_struct *p)
1496 struct nmb_packet *nmb = &p->packet.nmb;
1497 struct nmb_name *question = &nmb->question.question_name;
1498 struct name_record *namerec = NULL;
1500 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1501 nmb_namestr(question), inet_ntoa(p->ip) ));
1504 * Special name code. If the queried name is *<1b> then search
1505 * the entire WINS database and return a list of all the IP addresses
1506 * registered to any <1b> name. This is to allow domain master browsers
1507 * to discover other domains that may not have a presence on their subnet.
1510 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1512 process_wins_dmb_query_request( subrec, p);
1516 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1521 * If the name is not anymore in active state then reply not found.
1522 * it's fair even if we keep it in the cache for days.
1524 if (!WINS_STATE_ACTIVE(namerec))
1526 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1527 nmb_namestr(question) ));
1528 send_wins_name_query_response(NAM_ERR, p, namerec);
1532 * If it's a DNSFAIL_NAME then reply name not found.
1535 if( namerec->data.source == DNSFAIL_NAME )
1537 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1538 nmb_namestr(question) ));
1539 send_wins_name_query_response(NAM_ERR, p, namerec);
1544 * If the name has expired then reply name not found.
1547 if( (namerec->data.death_time != PERMANENT_TTL)
1548 && (namerec->data.death_time < p->timestamp) )
1550 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1551 nmb_namestr(question) ));
1552 send_wins_name_query_response(NAM_ERR, p, namerec);
1556 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1557 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1559 send_wins_name_query_response(0, p, namerec);
1564 * Name not found in WINS - try a dns query if it's a 0x20 name.
1567 if(lp_dns_proxy() &&
1568 ((question->name_type == 0x20) || question->name_type == 0))
1571 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1572 nmb_namestr(question) ));
1574 queue_dns_query(p, question, &namerec);
1579 * Name not found - return error.
1582 send_wins_name_query_response(NAM_ERR, p, NULL);
1585 /****************************************************************************
1586 Send a WINS name release response.
1587 **************************************************************************/
1589 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1591 struct nmb_packet *nmb = &p->packet.nmb;
1594 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1596 reply_netbios_packet(p, /* Packet to reply to. */
1597 rcode, /* Result code. */
1598 NMB_REL, /* nmbd type code. */
1599 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1601 rdata, /* data to send. */
1602 6); /* data length. */
1605 /***********************************************************************
1606 Deal with a name release.
1607 ***********************************************************************/
1609 void wins_process_name_release_request(struct subnet_record *subrec,
1610 struct packet_struct *p)
1612 struct nmb_packet *nmb = &p->packet.nmb;
1613 struct nmb_name *question = &nmb->question.question_name;
1614 BOOL bcast = nmb->header.nm_flags.bcast;
1615 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1616 struct name_record *namerec = NULL;
1617 struct in_addr from_ip;
1618 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1620 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1625 * We should only get unicast name registration packets here.
1626 * Anyone trying to register broadcast should not be going to a WINS
1627 * server. Log an error here.
1630 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1631 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1632 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1636 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1637 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1640 * Deal with policy regarding 0x1d names.
1643 if(!releasing_group_name && (question->name_type == 0x1d))
1645 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1646 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1647 send_wins_name_release_response(0, p);
1652 * See if the name already exists.
1655 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1657 if( (namerec == NULL)
1658 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1660 send_wins_name_release_response(NAM_ERR, p);
1665 * Check that the sending machine has permission to release this name.
1666 * If it's a group name not ending in 0x1c then just say yes and let
1667 * the group time out.
1670 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))
1683 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1684 release name %s as IP %s is not one of the known IP's for this name.\n",
1685 nmb_namestr(question), inet_ntoa(from_ip) ));
1686 send_wins_name_release_response(NAM_ERR, p);
1691 * Check if the record is active. IF it's already released
1692 * 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 anymore active.\n",
1697 nmb_namestr(question) ));
1698 send_wins_name_release_response(NAM_ERR, p);
1703 * Check if the record is a 0x1c group
1704 * and has more then one ip
1705 * remove only this address.
1708 if(releasing_group_name &&
1709 (question->name_type == 0x1c) &&
1710 (namerec->data.num_ips > 1)) {
1711 remove_ip_from_name_record(namerec, from_ip);
1712 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1713 inet_ntoa(from_ip),nmb_namestr(question)));
1714 send_wins_name_release_response(0, p);
1719 * Send a release response.
1720 * Flag the name as released and update the ttl
1723 send_wins_name_release_response(0, p);
1725 namerec->data.wins_flags |= WINS_RELEASED;
1726 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1728 wins_hook("delete", namerec, 0);
1731 /*******************************************************************
1732 WINS time dependent processing.
1733 ******************************************************************/
1735 void initiate_wins_processing(time_t t)
1737 static time_t lasttime = 0;
1738 struct name_record *namerec;
1739 struct name_record *next_namerec;
1740 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1744 if (t - lasttime < 20)
1749 if(!lp_we_are_a_wins_server())
1752 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1754 namerec = next_namerec ) {
1755 next_namerec = (struct name_record *)ubi_trNext( namerec );
1757 if( (namerec->data.death_time != PERMANENT_TTL)
1758 && (namerec->data.death_time < t) ) {
1760 if( namerec->data.source == SELF_NAME ) {
1761 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1762 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1763 namerec->data.death_time += 300;
1764 namerec->subnet->namelist_changed = True;
1768 /* handle records, samba is the wins owner */
1769 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1770 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1772 namerec->data.wins_flags&=~WINS_STATE_MASK;
1773 namerec->data.wins_flags|=WINS_RELEASED;
1774 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1775 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1778 namerec->data.wins_flags&=~WINS_STATE_MASK;
1779 namerec->data.wins_flags|=WINS_TOMBSTONED;
1780 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1781 get_global_id_and_update(&namerec->data.id, True);
1782 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1784 case WINS_TOMBSTONED:
1785 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1786 remove_name_from_namelist( wins_server_subnet, namerec );
1790 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1792 /* that's not as MS says it should be */
1793 namerec->data.wins_flags&=~WINS_STATE_MASK;
1794 namerec->data.wins_flags|=WINS_TOMBSTONED;
1795 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1796 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1797 case WINS_TOMBSTONED:
1798 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1799 remove_name_from_namelist( wins_server_subnet, namerec );
1802 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1803 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1811 if(wins_server_subnet->namelist_changed)
1812 wins_write_database(True);
1814 wins_server_subnet->namelist_changed = False;
1817 /*******************************************************************
1818 Write out the current WINS database.
1819 ******************************************************************/
1820 void wins_write_database(BOOL background)
1822 struct name_record *namerec;
1823 pstring fname, fnamenew;
1827 if(!lp_we_are_a_wins_server())
1830 /* we will do the writing in a child process to ensure that the parent
1831 doesn't block while this is done */
1839 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1840 all_string_sub(fname,"//", "/", 0);
1841 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1843 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL)
1845 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1852 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1854 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1857 = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1859 namerec = (struct name_record *)ubi_trNext( namerec ) )
1864 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1866 if( namerec->data.death_time != PERMANENT_TTL )
1870 tm = LocalTime(&namerec->data.death_time);
1872 nl = strrchr( ts, '\n' );
1875 DEBUGADD(4,("TTL = %s ", ts ));
1878 DEBUGADD(4,("TTL = PERMANENT "));
1880 for (i = 0; i < namerec->data.num_ips; i++)
1881 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1882 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1884 if( namerec->data.source == REGISTER_NAME )
1886 x_fprintf(fp, "\"%s#%02x\" %d ",
1887 namerec->name.name,namerec->name.name_type, /* Ignore scope. */
1888 (int)namerec->data.death_time);
1890 for (i = 0; i < namerec->data.num_ips; i++)
1891 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1892 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1897 chmod(fnamenew,0644);
1899 rename(fnamenew,fname);
1905 /****************************************************************************
1906 process a internal Samba message receiving a wins record
1907 ***************************************************************************/
1908 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1910 WINS_RECORD *record;
1911 struct name_record *namerec = NULL;
1912 struct name_record *new_namerec = NULL;
1913 struct nmb_name question;
1914 BOOL overwrite=False;
1915 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1921 record=(WINS_RECORD *)buf;
1923 ZERO_STRUCT(question);
1924 memcpy(question.name, record->name, 16);
1925 question.name_type=record->type;
1927 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1929 /* record doesn't exist, add it */
1930 if (namerec == NULL) {
1931 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1932 record->name, record->type, inet_ntoa(record->wins_ip)));
1934 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1935 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1936 if (new_namerec!=NULL) {
1937 update_wins_owner(new_namerec, record->wins_ip);
1938 update_wins_flag(new_namerec, record->wins_flags);
1939 new_namerec->data.id=record->id;
1941 wins_server_subnet->namelist_changed = True;
1945 /* check if we have a conflict */
1946 if (namerec != NULL) {
1947 /* both records are UNIQUE */
1948 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1950 /* the database record is a replica */
1951 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1952 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1953 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1958 /* we are the wins owner of the database record */
1959 /* the 2 records have the same IP address */
1960 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1961 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1962 get_global_id_and_update(&namerec->data.id, True);
1967 /* the 2 records have different IP address */
1968 if (namerec->data.wins_flags&WINS_ACTIVE) {
1969 if (record->wins_flags&WINS_TOMBSTONED)
1970 get_global_id_and_update(&namerec->data.id, True);
1971 if (record->wins_flags&WINS_ACTIVE)
1972 /* send conflict challenge to the replica node */
1981 /* the replica is a standard group */
1982 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1983 /* if the database record is unique and active force a name release */
1984 if (namerec->data.wins_flags&WINS_UNIQUE)
1985 /* send a release name to the unique node */
1991 /* the replica is a special group */
1992 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1993 if (namerec->data.wins_flags&WINS_ACTIVE) {
1994 for (i=0; i<record->num_ips; i++)
1995 if(!find_ip_in_name_record(namerec, record->ip[i]))
1996 add_ip_to_name_record(namerec, record->ip[i]);
2002 /* the replica is a multihomed host */
2004 /* I'm giving up on multi homed. Too much complex to understand */
2006 if (record->wins_flags&WINS_MHOMED) {
2007 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
2008 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
2012 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2015 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
2016 if (namerec->data.wins_flags&WINS_UNIQUE)
2017 get_global_id_and_update(&namerec->data.id, True);
2021 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
2022 if (namerec->data.wins_flags&WINS_UNIQUE ||
2023 namerec->data.wins_flags&WINS_MHOMED)
2024 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
2029 if (overwrite == False)
2030 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
2031 record->name, record->type, inet_ntoa(record->wins_ip)));
2033 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
2034 record->name, record->type, inet_ntoa(record->wins_ip)));
2036 /* remove the old record and add a new one */
2037 remove_name_from_namelist( wins_server_subnet, namerec );
2038 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
2039 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
2040 if (new_namerec!=NULL) {
2041 update_wins_owner(new_namerec, record->wins_ip);
2042 update_wins_flag(new_namerec, record->wins_flags);
2043 new_namerec->data.id=record->id;
2045 wins_server_subnet->namelist_changed = True;
2048 wins_server_subnet->namelist_changed = True;