2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
5 Copyright (C) Jeremy Allison 1994-2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #define WINS_LIST "wins.dat"
26 #define WINS_VERSION 1
28 /****************************************************************************
29 Change the wins owner address in the record.
30 *****************************************************************************/
32 static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
36 namerec->data.wins_ip=wins_ip;
39 /****************************************************************************
40 Create the wins flags based on the nb flags and the input value.
41 *****************************************************************************/
43 static void update_wins_flag(struct name_record *namerec, int flags)
48 namerec->data.wins_flags=0x0;
50 /* if it's a group, it can be a normal or a special one */
51 if (namerec->data.nb_flags & NB_GROUP) {
52 if (namerec->name.name_type==0x1C)
53 namerec->data.wins_flags|=WINS_SGROUP;
55 if (namerec->data.num_ips>1)
56 namerec->data.wins_flags|=WINS_SGROUP;
58 namerec->data.wins_flags|=WINS_NGROUP;
60 /* can be unique or multi-homed */
61 if (namerec->data.num_ips>1)
62 namerec->data.wins_flags|=WINS_MHOMED;
64 namerec->data.wins_flags|=WINS_UNIQUE;
67 /* the node type are the same bits */
68 namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
70 /* the static bit is elsewhere */
71 if (namerec->data.death_time == PERMANENT_TTL)
72 namerec->data.wins_flags|=WINS_STATIC;
74 /* and add the given bits */
75 namerec->data.wins_flags|=flags;
77 DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
78 namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
81 /****************************************************************************
82 Return the general ID value and increase it if requested.
83 *****************************************************************************/
85 static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
88 * it's kept as a static here, to prevent people from messing
89 * with the value directly
92 static SMB_BIG_UINT general_id = 1;
94 DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
96 *current_id = general_id;
102 /****************************************************************************
103 Possibly call the WINS hook external program when a WINS change is made.
104 *****************************************************************************/
106 static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
109 char *cmd = lp_wins_hook();
113 if (!cmd || !*cmd) return;
115 for (p=namerec->name.name; *p; p++) {
116 if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
117 DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
123 p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
126 nmb_namestr(&namerec->name),
127 namerec->name.name_type,
130 for (i=0;i<namerec->data.num_ips;i++) {
131 p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
134 DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
135 smbrun(command, NULL);
139 /****************************************************************************
140 Determine if this packet should be allocated to the WINS server.
141 *****************************************************************************/
143 BOOL packet_is_for_wins_server(struct packet_struct *packet)
145 struct nmb_packet *nmb = &packet->packet.nmb;
147 /* Only unicast packets go to a WINS server. */
148 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) {
149 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
153 /* Check for node status requests. */
154 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
157 switch(nmb->header.opcode) {
159 * A WINS server issues WACKS, not receives them.
161 case NMB_WACK_OPCODE:
162 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
165 * A WINS server only processes registration and
166 * release requests, not responses.
168 case NMB_NAME_REG_OPCODE:
169 case NMB_NAME_MULTIHOMED_REG_OPCODE:
170 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
171 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
172 if(nmb->header.response) {
173 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
178 case NMB_NAME_RELEASE_OPCODE:
179 if(nmb->header.response) {
180 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
186 * Only process unicast name queries with rd = 1.
188 case NMB_NAME_QUERY_OPCODE:
189 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) {
190 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
199 /****************************************************************************
200 Utility function to decide what ttl to give a register/refresh request.
201 *****************************************************************************/
203 static int get_ttl_from_packet(struct nmb_packet *nmb)
205 int ttl = nmb->additional->ttl;
207 if(ttl < lp_min_wins_ttl() )
208 ttl = lp_min_wins_ttl();
210 if(ttl > lp_max_wins_ttl() )
211 ttl = lp_max_wins_ttl();
216 /****************************************************************************
217 Load or create the WINS database.
218 *****************************************************************************/
220 BOOL initialise_wins(void)
222 time_t time_now = time(NULL);
226 if(!lp_we_are_a_wins_server())
229 add_samba_names_to_subnet(wins_server_subnet);
231 if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) {
232 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
233 WINS_LIST, strerror(errno) ));
237 while (!x_feof(fp)) {
238 pstring name_str, ip_str, ttl_str, nb_flags_str;
239 unsigned int num_ips;
241 struct in_addr *ip_list;
253 /* Read a line from the wins.dat file. Strips whitespace
254 from the beginning and end of the line. */
255 if (!fgets_slash(line,sizeof(pstring),fp))
261 if (strncmp(line,"VERSION ", 8) == 0) {
262 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
263 version != WINS_VERSION) {
264 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
274 * Now we handle multiple IP addresses per name we need
275 * to iterate over the line twice. The first time to
276 * determine how many IP addresses there are, the second
277 * time to actually parse them into the ip_list array.
280 if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) {
281 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
285 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) {
286 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
291 * Determine the number of IP addresses per line.
295 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
298 if(got_token && strchr(ip_str, '.')) {
302 } while( got_token && was_ip);
305 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
310 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
314 /* Allocate the space for the ip_list. */
315 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
316 DEBUG(0,("initialise_wins: Malloc fail !\n"));
320 /* Reset and re-parse the line. */
322 next_token(&ptr,name_str,NULL,sizeof(name_str));
323 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
324 for(i = 0; i < num_ips; i++) {
325 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
326 ip_list[i] = *interpret_addr2(ip_str);
328 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
331 * Deal with SELF or REGISTER name encoding. Default is REGISTER
332 * for compatibility with old nmbds.
335 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') {
336 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
341 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
342 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
344 /* Netbios name. # divides the name from the type (hex): netbios#xx */
345 pstrcpy(name,name_str);
347 if((p = strchr(name,'#')) != NULL) {
349 sscanf(p+1,"%x",&type);
352 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
353 sscanf(nb_flags_str,"%x",&nb_flags);
354 sscanf(ttl_str,"%d",&ttl);
356 /* add all entries that have 60 seconds or more to live */
357 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
358 if(ttl != PERMANENT_TTL)
361 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
362 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
364 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
365 ttl, REGISTER_NAME, num_ips, ip_list );
367 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
368 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
378 /****************************************************************************
379 Send a WINS WACK (Wait ACKnowledgement) response.
380 **************************************************************************/
382 static void send_wins_wack_response(int ttl, struct packet_struct *p)
384 struct nmb_packet *nmb = &p->packet.nmb;
385 unsigned char rdata[2];
387 rdata[0] = rdata[1] = 0;
389 /* Taken from nmblib.c - we need to send back almost
390 identical bytes from the requesting packet header. */
392 rdata[0] = (nmb->header.opcode & 0xF) << 3;
393 if (nmb->header.nm_flags.authoritative && nmb->header.response)
395 if (nmb->header.nm_flags.trunc)
397 if (nmb->header.nm_flags.recursion_desired)
399 if (nmb->header.nm_flags.recursion_available && nmb->header.response)
401 if (nmb->header.nm_flags.bcast)
404 reply_netbios_packet(p, /* Packet to reply to. */
405 0, /* Result code. */
406 NMB_WAIT_ACK, /* nmbd type code. */
407 NMB_WACK_OPCODE, /* opcode. */
409 (char *)rdata, /* data to send. */
410 2); /* data length. */
413 /****************************************************************************
414 Send a WINS name registration response.
415 **************************************************************************/
417 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
419 struct nmb_packet *nmb = &p->packet.nmb;
422 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
424 reply_netbios_packet(p, /* Packet to reply to. */
425 rcode, /* Result code. */
426 WINS_REG, /* nmbd type code. */
427 NMB_NAME_REG_OPCODE, /* opcode. */
429 rdata, /* data to send. */
430 6); /* data length. */
433 /***********************************************************************
434 Deal with a name refresh request to a WINS server.
435 ************************************************************************/
437 void wins_process_name_refresh_request(struct subnet_record *subrec,
438 struct packet_struct *p)
440 struct nmb_packet *nmb = &p->packet.nmb;
441 struct nmb_name *question = &nmb->question.question_name;
442 BOOL bcast = nmb->header.nm_flags.bcast;
443 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
444 BOOL group = (nb_flags & NB_GROUP) ? True : False;
445 struct name_record *namerec = NULL;
446 int ttl = get_ttl_from_packet(nmb);
447 struct in_addr from_ip;
448 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
450 putip((char *)&from_ip,&nmb->additional->rdata[2]);
454 * We should only get unicast name refresh packets here.
455 * Anyone trying to refresh broadcast should not be going to a WINS
456 * server. Log an error here.
459 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
460 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
461 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
465 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
466 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
469 * See if the name already exists.
472 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
475 * If this is a refresh request and the name doesn't exist then
476 * treat it like a registration request. This allows us to recover
477 * from errors (tridge)
480 if(namerec == NULL) {
481 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
482 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
483 wins_process_name_registration_request(subrec,p);
488 * if the name is present but not active,
489 * simply remove it and treat the request
492 if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) {
493 DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
494 not active - removing it.\n", nmb_namestr(question) ));
495 remove_name_from_namelist( subrec, namerec );
497 wins_process_name_registration_request(subrec,p);
502 * Check that the group bits for the refreshing name and the
503 * name in our database match.
506 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) {
507 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
508 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
509 send_wins_name_registration_response(RFS_ERR, 0, p);
514 * For a unique name check that the person refreshing the name is one of the registered IP
515 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
516 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
517 * and return success.
520 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) {
524 update_name_ttl(namerec, ttl);
527 * if the record is a replica:
528 * we take ownership and update the version ID.
530 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
531 update_wins_owner(namerec, our_fake_ip);
532 get_global_id_and_update(&namerec->data.id, True);
535 send_wins_name_registration_response(0, ttl, p);
536 wins_hook("refresh", namerec, ttl);
540 * Normal groups are all registered with an IP address of 255.255.255.255
541 * so we can't search for the IP address.
543 update_name_ttl(namerec, ttl);
544 send_wins_name_registration_response(0, ttl, p);
546 } else if(!group && (question->name_type == 0x1d)) {
548 * Special name type - just pretend the refresh succeeded.
550 send_wins_name_registration_response(0, ttl, p);
557 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
558 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
559 send_wins_name_registration_response(RFS_ERR, 0, p);
564 /***********************************************************************
565 Deal with a name registration request query success to a client that
568 We have a locked pointer to the original packet stashed away in the
569 userdata pointer. The success here is actually a failure as it means
570 the client we queried wants to keep the name, so we must return
571 a registration failure to the original requestor.
572 ************************************************************************/
574 static void wins_register_query_success(struct subnet_record *subrec,
575 struct userdata_struct *userdata,
576 struct nmb_name *question_name,
578 struct res_rec *answers)
580 struct packet_struct *orig_reg_packet;
582 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
584 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
585 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
587 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
589 orig_reg_packet->locked = False;
590 free_packet(orig_reg_packet);
593 /***********************************************************************
594 Deal with a name registration request query failure to a client that
597 We have a locked pointer to the original packet stashed away in the
598 userdata pointer. The failure here is actually a success as it means
599 the client we queried didn't want to keep the name, so we can remove
600 the old name record and then successfully add the new name.
601 ************************************************************************/
603 static void wins_register_query_fail(struct subnet_record *subrec,
604 struct response_record *rrec,
605 struct nmb_name *question_name,
608 struct userdata_struct *userdata = rrec->userdata;
609 struct packet_struct *orig_reg_packet;
610 struct name_record *namerec = NULL;
612 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
615 * We want to just add the name, as we now know the original owner
616 * didn't want it. But we can't just do that as an arbitary
617 * amount of time may have taken place between the name query
618 * request and this timeout/error response. So we check that
619 * the name still exists and is in the same state - if so
620 * we remove it and call wins_process_name_registration_request()
621 * as we know it will do the right thing now.
624 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
626 if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) {
627 remove_name_from_namelist( subrec, namerec);
632 wins_process_name_registration_request(subrec, orig_reg_packet);
634 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
635 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
637 orig_reg_packet->locked = False;
638 free_packet(orig_reg_packet);
641 /***********************************************************************
642 Deal with a name registration request to a WINS server.
644 Use the following pseudocode :
652 | +--- existing name is group
655 | | +--- add name (return).
658 | +--- exiting name is unique
661 | +--- query existing owner (return).
664 +--------name doesn't exist
667 +--- add name (return).
675 | +--- existing name is group
678 | | +--- fail add (return).
681 | +--- exiting name is unique
684 | +--- query existing owner (return).
687 +--------name doesn't exist
690 +--- add name (return).
692 As can be seen from the above, the two cases may be collapsed onto each
693 other with the exception of the case where the name already exists and
694 is a group name. This case we handle with an if statement.
696 ************************************************************************/
698 void wins_process_name_registration_request(struct subnet_record *subrec,
699 struct packet_struct *p)
702 struct nmb_packet *nmb = &p->packet.nmb;
703 struct nmb_name *question = &nmb->question.question_name;
704 BOOL bcast = nmb->header.nm_flags.bcast;
705 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
706 int ttl = get_ttl_from_packet(nmb);
707 struct name_record *namerec = NULL;
708 struct in_addr from_ip;
709 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
710 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
712 putip((char *)&from_ip,&nmb->additional->rdata[2]);
716 * We should only get unicast name registration packets here.
717 * Anyone trying to register broadcast should not be going to a WINS
718 * server. Log an error here.
721 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
722 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
723 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
727 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
728 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
731 * See if the name already exists.
734 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
737 * if the record exists but NOT in active state,
740 if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
741 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
742 not active - removing it.\n", nmb_namestr(question) ));
743 remove_name_from_namelist( subrec, namerec );
748 * Deal with the case where the name found was a dns entry.
749 * Remove it as we now have a NetBIOS client registering the
753 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
754 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
755 a dns lookup - removing it.\n", nmb_namestr(question) ));
756 remove_name_from_namelist( subrec, namerec );
761 * Reject if the name exists and is not a REGISTER_NAME.
762 * (ie. Don't allow any static names to be overwritten.
765 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) {
766 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
767 to register name %s. Name already exists in WINS with source type %d.\n",
768 nmb_namestr(question), namerec->data.source ));
769 send_wins_name_registration_response(RFS_ERR, 0, p);
774 * Special policy decisions based on MS documentation.
775 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
776 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
780 * A group name is always added as the local broadcast address, except
781 * for group names ending in 0x1c.
782 * Group names with type 0x1c are registered with individual IP addresses.
785 if(registering_group_name && (question->name_type != 0x1c))
786 from_ip = *interpret_addr2("255.255.255.255");
789 * Ignore all attempts to register a unique 0x1d name, although return success.
792 if(!registering_group_name && (question->name_type == 0x1d)) {
793 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
794 to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
795 send_wins_name_registration_response(0, ttl, p);
800 * Next two cases are the 'if statement' mentioned above.
803 if((namerec != NULL) && NAME_GROUP(namerec)) {
804 if(registering_group_name) {
806 * If we are adding a group name, the name exists and is also a group entry just add this
807 * IP address to it and update the ttl.
810 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
811 inet_ntoa(from_ip), nmb_namestr(question) ));
814 * Check the ip address is not already in the group.
817 if(!find_ip_in_name_record(namerec, from_ip)) {
818 add_ip_to_name_record(namerec, from_ip);
819 /* we need to update the record for replication */
820 get_global_id_and_update(&namerec->data.id, True);
823 * if the record is a replica, we must change
824 * the wins owner to us to make the replication updates
825 * it on the other wins servers.
826 * And when the partner will receive this record,
827 * it will update its own record.
830 update_wins_owner(namerec, our_fake_ip);
832 update_name_ttl(namerec, ttl);
833 send_wins_name_registration_response(0, ttl, p);
838 * If we are adding a unique name, the name exists in the WINS db
839 * and is a group name then reject the registration.
841 * explanation: groups have a higher priority than unique names.
844 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
845 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
846 send_wins_name_registration_response(RFS_ERR, 0, p);
852 * From here on down we know that if the name exists in the WINS db it is
853 * a unique name, not a group name.
857 * If the name exists and is one of our names then check the
858 * registering IP address. If it's not one of ours then automatically
859 * reject without doing the query - we know we will reject it.
862 pull_ascii_nstring(name, namerec->name.name);
863 if((namerec != NULL) && (is_myname(name)) ) {
864 if(!ismyip(from_ip)) {
865 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
866 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
867 send_wins_name_registration_response(RFS_ERR, 0, p);
871 * It's one of our names and one of our IP's - update the ttl.
873 update_name_ttl(namerec, ttl);
874 send_wins_name_registration_response(0, ttl, p);
875 wins_hook("refresh", namerec, ttl);
881 * If the name exists and it is a unique registration and the registering IP
882 * is the same as the (single) already registered IP then just update the ttl.
884 * But not if the record is an active replica. IF it's a replica, it means it can be
885 * the same client which has moved and not yet expired. So we don't update
886 * the ttl in this case and go beyond to do a WACK and query the old client
889 if( !registering_group_name
891 && (namerec->data.num_ips == 1)
892 && ip_equal( namerec->data.ip[0], from_ip )
893 && ip_equal(namerec->data.wins_ip, our_fake_ip) ) {
894 update_name_ttl( namerec, ttl );
895 send_wins_name_registration_response( 0, ttl, p );
896 wins_hook("refresh", namerec, ttl);
901 * Finally if the name exists do a query to the registering machine
902 * to see if they still claim to have the name.
905 if( namerec != NULL ) {
906 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
907 struct userdata_struct *userdata = (struct userdata_struct *)ud;
910 * First send a WACK to the registering machine.
913 send_wins_wack_response(60, p);
916 * When the reply comes back we need the original packet.
917 * Lock this so it won't be freed and then put it into
918 * the userdata structure.
923 userdata = (struct userdata_struct *)ud;
925 userdata->copy_fn = NULL;
926 userdata->free_fn = NULL;
927 userdata->userdata_len = sizeof(struct packet_struct *);
928 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
931 * Use the new call to send a query directly to an IP address.
932 * This sends the query directly to the IP address, and ensures
933 * the recursion desired flag is not set (you were right Luke :-).
934 * This function should *only* be called from the WINS server
938 pull_ascii_nstring(name, question->name);
939 query_name_from_wins_server( *namerec->data.ip,
942 wins_register_query_success,
943 wins_register_query_fail,
949 * Name did not exist - add it.
952 pull_ascii_nstring(name, question->name);
953 add_name_to_subnet( subrec, name, question->name_type,
954 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
956 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
957 get_global_id_and_update(&namerec->data.id, True);
958 update_wins_owner(namerec, our_fake_ip);
959 update_wins_flag(namerec, WINS_ACTIVE);
960 wins_hook("add", namerec, ttl);
963 send_wins_name_registration_response(0, ttl, p);
966 /***********************************************************************
967 Deal with a mutihomed name query success to the machine that
968 requested the multihomed name registration.
970 We have a locked pointer to the original packet stashed away in the
972 ************************************************************************/
974 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
975 struct userdata_struct *userdata,
976 struct nmb_name *question_name,
978 struct res_rec *answers)
980 struct packet_struct *orig_reg_packet;
981 struct nmb_packet *nmb;
982 struct name_record *namerec = NULL;
983 struct in_addr from_ip;
985 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
987 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
989 nmb = &orig_reg_packet->packet.nmb;
991 putip((char *)&from_ip,&nmb->additional->rdata[2]);
992 ttl = get_ttl_from_packet(nmb);
995 * We want to just add the new IP, as we now know the requesting
996 * machine claims to own it. But we can't just do that as an arbitary
997 * amount of time may have taken place between the name query
998 * request and this response. So we check that
999 * the name still exists and is in the same state - if so
1000 * we just add the extra IP and update the ttl.
1003 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
1005 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) {
1006 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
1007 a subsequent IP address.\n", nmb_namestr(question_name) ));
1008 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1010 orig_reg_packet->locked = False;
1011 free_packet(orig_reg_packet);
1016 if(!find_ip_in_name_record(namerec, from_ip))
1017 add_ip_to_name_record(namerec, from_ip);
1019 get_global_id_and_update(&namerec->data.id, True);
1020 update_wins_owner(namerec, our_fake_ip);
1021 update_wins_flag(namerec, WINS_ACTIVE);
1022 update_name_ttl(namerec, ttl);
1023 send_wins_name_registration_response(0, ttl, orig_reg_packet);
1024 wins_hook("add", namerec, ttl);
1026 orig_reg_packet->locked = False;
1027 free_packet(orig_reg_packet);
1030 /***********************************************************************
1031 Deal with a name registration request query failure to a client that
1034 We have a locked pointer to the original packet stashed away in the
1036 ************************************************************************/
1038 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
1039 struct response_record *rrec,
1040 struct nmb_name *question_name,
1043 struct userdata_struct *userdata = rrec->userdata;
1044 struct packet_struct *orig_reg_packet;
1046 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
1048 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
1049 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
1050 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
1052 orig_reg_packet->locked = False;
1053 free_packet(orig_reg_packet);
1057 /***********************************************************************
1058 Deal with a multihomed name registration request to a WINS server.
1059 These cannot be group name registrations.
1060 ***********************************************************************/
1062 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
1063 struct packet_struct *p)
1065 struct nmb_packet *nmb = &p->packet.nmb;
1066 struct nmb_name *question = &nmb->question.question_name;
1067 BOOL bcast = nmb->header.nm_flags.bcast;
1068 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1069 int ttl = get_ttl_from_packet(nmb);
1070 struct name_record *namerec = NULL;
1071 struct in_addr from_ip;
1072 BOOL group = (nb_flags & NB_GROUP) ? True : False;
1073 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1076 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1080 * We should only get unicast name registration packets here.
1081 * Anyone trying to register broadcast should not be going to a WINS
1082 * server. Log an error here.
1085 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
1086 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1087 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1092 * Only unique names should be registered multihomed.
1096 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
1097 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
1098 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1102 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
1103 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1106 * Deal with policy regarding 0x1d names.
1109 if(question->name_type == 0x1d) {
1110 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1111 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1112 send_wins_name_registration_response(0, ttl, p);
1117 * See if the name already exists.
1120 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1123 * if the record exists but NOT in active state,
1127 if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
1128 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
1129 remove_name_from_namelist(subrec, namerec);
1134 * Deal with the case where the name found was a dns entry.
1135 * Remove it as we now have a NetBIOS client registering the
1139 if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) {
1140 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1141 - removing it.\n", nmb_namestr(question) ));
1142 remove_name_from_namelist( subrec, namerec);
1147 * Reject if the name exists and is not a REGISTER_NAME.
1148 * (ie. Don't allow any static names to be overwritten.
1151 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) {
1152 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1153 to register name %s. Name already exists in WINS with source type %d.\n",
1154 nmb_namestr(question), namerec->data.source ));
1155 send_wins_name_registration_response(RFS_ERR, 0, p);
1160 * Reject if the name exists and is a GROUP name and is active.
1163 if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) {
1164 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1165 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1166 send_wins_name_registration_response(RFS_ERR, 0, p);
1171 * From here on down we know that if the name exists in the WINS db it is
1172 * a unique name, not a group name.
1176 * If the name exists and is one of our names then check the
1177 * registering IP address. If it's not one of ours then automatically
1178 * reject without doing the query - we know we will reject it.
1181 if((namerec != NULL) && (is_myname(namerec->name.name)) ) {
1182 if(!ismyip(from_ip)) {
1183 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1184 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1185 send_wins_name_registration_response(RFS_ERR, 0, p);
1189 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1190 * update the ttl. Update the version ID to force replication.
1192 if(!find_ip_in_name_record(namerec, from_ip)) {
1193 get_global_id_and_update(&namerec->data.id, True);
1194 update_wins_owner(namerec, our_fake_ip);
1195 update_wins_flag(namerec, WINS_ACTIVE);
1197 add_ip_to_name_record(namerec, from_ip);
1198 wins_hook("add", namerec, ttl);
1200 wins_hook("refresh", namerec, ttl);
1203 update_name_ttl(namerec, ttl);
1204 send_wins_name_registration_response(0, ttl, p);
1210 * If the name exists and is active, check if the IP address is already registered
1211 * to that name. If so then update the ttl and reply success.
1214 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) {
1215 update_name_ttl(namerec, ttl);
1218 * If it's a replica, we need to become the wins owner
1219 * to force the replication
1221 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1222 get_global_id_and_update(&namerec->data.id, True);
1223 update_wins_owner(namerec, our_fake_ip);
1224 update_wins_flag(namerec, WINS_ACTIVE);
1227 send_wins_name_registration_response(0, ttl, p);
1228 wins_hook("refresh", namerec, ttl);
1233 * If the name exists do a query to the owner
1234 * to see if they still want the name.
1237 if(namerec != NULL) {
1238 long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
1239 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1242 * First send a WACK to the registering machine.
1245 send_wins_wack_response(60, p);
1248 * When the reply comes back we need the original packet.
1249 * Lock this so it won't be freed and then put it into
1250 * the userdata structure.
1255 userdata = (struct userdata_struct *)ud;
1257 userdata->copy_fn = NULL;
1258 userdata->free_fn = NULL;
1259 userdata->userdata_len = sizeof(struct packet_struct *);
1260 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1263 * Use the new call to send a query directly to an IP address.
1264 * This sends the query directly to the IP address, and ensures
1265 * the recursion desired flag is not set (you were right Luke :-).
1266 * This function should *only* be called from the WINS server
1269 * Note that this packet is sent to the current owner of the name,
1270 * not the person who sent the packet
1273 pull_ascii_nstring( qname, question->name);
1274 query_name_from_wins_server( namerec->data.ip[0],
1276 question->name_type,
1277 wins_multihomed_register_query_success,
1278 wins_multihomed_register_query_fail,
1285 * Name did not exist - add it.
1288 pull_ascii_nstring( qname, question->name);
1289 add_name_to_subnet( subrec, qname, question->name_type,
1290 nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
1292 if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
1293 get_global_id_and_update(&namerec->data.id, True);
1294 update_wins_owner(namerec, our_fake_ip);
1295 update_wins_flag(namerec, WINS_ACTIVE);
1296 wins_hook("add", namerec, ttl);
1299 send_wins_name_registration_response(0, ttl, p);
1302 /***********************************************************************
1303 Deal with the special name query for *<1b>.
1304 ***********************************************************************/
1306 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1307 struct packet_struct *p)
1309 struct name_record *namerec = NULL;
1314 * Go through all the ACTIVE names in the WINS db looking for those
1315 * ending in <1b>. Use this to calculate the number of IP
1316 * addresses we need to return.
1320 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1321 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1322 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
1323 num_ips += namerec->data.num_ips;
1328 * There are no 0x1b names registered. Return name query fail.
1330 send_wins_name_query_response(NAM_ERR, p, NULL);
1334 if((prdata = (char *)malloc( num_ips * 6 )) == NULL) {
1335 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1340 * Go through all the names again in the WINS db looking for those
1341 * ending in <1b>. Add their IP addresses into the list we will
1346 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1347 namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1348 if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) {
1350 for(i = 0; i < namerec->data.num_ips; i++) {
1351 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1352 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1359 * Send back the reply containing the IP list.
1362 reply_netbios_packet(p, /* Packet to reply to. */
1363 0, /* Result code. */
1364 WINS_QUERY, /* nmbd type code. */
1365 NMB_NAME_QUERY_OPCODE, /* opcode. */
1366 lp_min_wins_ttl(), /* ttl. */
1367 prdata, /* data to send. */
1368 num_ips*6); /* data length. */
1373 /****************************************************************************
1374 Send a WINS name query response.
1375 **************************************************************************/
1377 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1378 struct name_record *namerec)
1381 char *prdata = rdata;
1382 int reply_data_len = 0;
1386 memset(rdata,'\0',6);
1389 ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1391 /* Copy all known ip addresses into the return data. */
1392 /* Optimise for the common case of one IP address so we don't need a malloc. */
1394 if( namerec->data.num_ips == 1 ) {
1397 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
1398 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1403 for(i = 0; i < namerec->data.num_ips; i++) {
1404 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1405 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1408 sort_query_replies(prdata, i, p->ip);
1409 reply_data_len = namerec->data.num_ips * 6;
1412 reply_netbios_packet(p, /* Packet to reply to. */
1413 rcode, /* Result code. */
1414 WINS_QUERY, /* nmbd type code. */
1415 NMB_NAME_QUERY_OPCODE, /* opcode. */
1417 prdata, /* data to send. */
1418 reply_data_len); /* data length. */
1424 /***********************************************************************
1425 Deal with a name query.
1426 ***********************************************************************/
1428 void wins_process_name_query_request(struct subnet_record *subrec,
1429 struct packet_struct *p)
1431 struct nmb_packet *nmb = &p->packet.nmb;
1432 struct nmb_name *question = &nmb->question.question_name;
1433 struct name_record *namerec = NULL;
1436 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1437 nmb_namestr(question), inet_ntoa(p->ip) ));
1440 * Special name code. If the queried name is *<1b> then search
1441 * the entire WINS database and return a list of all the IP addresses
1442 * registered to any <1b> name. This is to allow domain master browsers
1443 * to discover other domains that may not have a presence on their subnet.
1446 pull_ascii_nstring(qname, question->name);
1447 if(strequal( qname, "*") && (question->name_type == 0x1b)) {
1448 process_wins_dmb_query_request( subrec, p);
1452 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1454 if(namerec != NULL) {
1456 * If the name is not anymore in active state then reply not found.
1457 * it's fair even if we keep it in the cache for days.
1459 if (!WINS_STATE_ACTIVE(namerec)) {
1460 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1461 nmb_namestr(question) ));
1462 send_wins_name_query_response(NAM_ERR, p, namerec);
1467 * If it's a DNSFAIL_NAME then reply name not found.
1470 if( namerec->data.source == DNSFAIL_NAME ) {
1471 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1472 nmb_namestr(question) ));
1473 send_wins_name_query_response(NAM_ERR, p, namerec);
1478 * If the name has expired then reply name not found.
1481 if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) {
1482 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1483 nmb_namestr(question) ));
1484 send_wins_name_query_response(NAM_ERR, p, namerec);
1488 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1489 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1491 send_wins_name_query_response(0, p, namerec);
1496 * Name not found in WINS - try a dns query if it's a 0x20 name.
1499 if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) {
1500 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1501 nmb_namestr(question) ));
1503 queue_dns_query(p, question, &namerec);
1508 * Name not found - return error.
1511 send_wins_name_query_response(NAM_ERR, p, NULL);
1514 /****************************************************************************
1515 Send a WINS name release response.
1516 **************************************************************************/
1518 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1520 struct nmb_packet *nmb = &p->packet.nmb;
1523 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1525 reply_netbios_packet(p, /* Packet to reply to. */
1526 rcode, /* Result code. */
1527 NMB_REL, /* nmbd type code. */
1528 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1530 rdata, /* data to send. */
1531 6); /* data length. */
1534 /***********************************************************************
1535 Deal with a name release.
1536 ***********************************************************************/
1538 void wins_process_name_release_request(struct subnet_record *subrec,
1539 struct packet_struct *p)
1541 struct nmb_packet *nmb = &p->packet.nmb;
1542 struct nmb_name *question = &nmb->question.question_name;
1543 BOOL bcast = nmb->header.nm_flags.bcast;
1544 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1545 struct name_record *namerec = NULL;
1546 struct in_addr from_ip;
1547 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1549 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1553 * We should only get unicast name registration packets here.
1554 * Anyone trying to register broadcast should not be going to a WINS
1555 * server. Log an error here.
1558 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1559 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1560 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1564 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1565 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1568 * Deal with policy regarding 0x1d names.
1571 if(!releasing_group_name && (question->name_type == 0x1d)) {
1572 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1573 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1574 send_wins_name_release_response(0, p);
1579 * See if the name already exists.
1582 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1584 if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) {
1585 send_wins_name_release_response(NAM_ERR, p);
1590 * Check that the sending machine has permission to release this name.
1591 * If it's a group name not ending in 0x1c then just say yes and let
1592 * the group time out.
1595 if(releasing_group_name && (question->name_type != 0x1c)) {
1596 send_wins_name_release_response(0, p);
1601 * Check that the releasing node is on the list of IP addresses
1602 * for this name. Disallow the release if not.
1605 if(!find_ip_in_name_record(namerec, from_ip)) {
1606 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1607 release name %s as IP %s is not one of the known IP's for this name.\n",
1608 nmb_namestr(question), inet_ntoa(from_ip) ));
1609 send_wins_name_release_response(NAM_ERR, p);
1614 * Check if the record is active. IF it's already released
1615 * or tombstoned, refuse the release.
1618 if (!WINS_STATE_ACTIVE(namerec)) {
1619 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1620 release name %s as this record is not active anymore.\n", nmb_namestr(question) ));
1621 send_wins_name_release_response(NAM_ERR, p);
1626 * Check if the record is a 0x1c group
1627 * and has more then one ip
1628 * remove only this address.
1631 if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) {
1632 remove_ip_from_name_record(namerec, from_ip);
1633 DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
1634 inet_ntoa(from_ip),nmb_namestr(question)));
1635 send_wins_name_release_response(0, p);
1640 * Send a release response.
1641 * Flag the name as released and update the ttl
1644 send_wins_name_release_response(0, p);
1646 namerec->data.wins_flags |= WINS_RELEASED;
1647 update_name_ttl(namerec, EXTINCTION_INTERVAL);
1649 wins_hook("delete", namerec, 0);
1652 /*******************************************************************
1653 WINS time dependent processing.
1654 ******************************************************************/
1656 void initiate_wins_processing(time_t t)
1658 static time_t lasttime = 0;
1659 struct name_record *namerec;
1660 struct name_record *next_namerec;
1661 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1665 if (t - lasttime < 20)
1670 if(!lp_we_are_a_wins_server())
1673 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1675 namerec = next_namerec ) {
1676 next_namerec = (struct name_record *)ubi_trNext( namerec );
1678 if( (namerec->data.death_time != PERMANENT_TTL)
1679 && (namerec->data.death_time < t) ) {
1681 if( namerec->data.source == SELF_NAME ) {
1682 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
1683 wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
1684 namerec->data.death_time += 300;
1685 namerec->subnet->namelist_changed = True;
1689 /* handle records, samba is the wins owner */
1690 if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1691 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1693 namerec->data.wins_flags&=~WINS_STATE_MASK;
1694 namerec->data.wins_flags|=WINS_RELEASED;
1695 namerec->data.death_time = t + EXTINCTION_INTERVAL;
1696 DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
1699 namerec->data.wins_flags&=~WINS_STATE_MASK;
1700 namerec->data.wins_flags|=WINS_TOMBSTONED;
1701 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1702 get_global_id_and_update(&namerec->data.id, True);
1703 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1705 case WINS_TOMBSTONED:
1706 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1707 remove_name_from_namelist( wins_server_subnet, namerec );
1711 switch (namerec->data.wins_flags | WINS_STATE_MASK) {
1713 /* that's not as MS says it should be */
1714 namerec->data.wins_flags&=~WINS_STATE_MASK;
1715 namerec->data.wins_flags|=WINS_TOMBSTONED;
1716 namerec->data.death_time = t + EXTINCTION_TIMEOUT;
1717 DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
1718 case WINS_TOMBSTONED:
1719 DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
1720 remove_name_from_namelist( wins_server_subnet, namerec );
1723 DEBUG(0,("initiate_wins_processing: %s is in released state and\
1724 we are not the wins owner !\n", nmb_namestr(&namerec->name)));
1732 if(wins_server_subnet->namelist_changed)
1733 wins_write_database(True);
1735 wins_server_subnet->namelist_changed = False;
1738 /*******************************************************************
1739 Write out the current WINS database.
1740 ******************************************************************/
1742 void wins_write_database(BOOL background)
1744 struct name_record *namerec;
1745 pstring fname, fnamenew;
1749 if(!lp_we_are_a_wins_server())
1752 /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */
1760 slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
1761 all_string_sub(fname,"//", "/", 0);
1762 slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
1764 if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) {
1765 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1772 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1774 x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0);
1776 for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) {
1780 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1782 if( namerec->data.death_time != PERMANENT_TTL ) {
1785 tm = LocalTime(&namerec->data.death_time);
1787 nl = strrchr( ts, '\n' );
1790 DEBUGADD(4,("TTL = %s ", ts ));
1792 DEBUGADD(4,("TTL = PERMANENT "));
1795 for (i = 0; i < namerec->data.num_ips; i++)
1796 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1797 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1799 if( namerec->data.source == REGISTER_NAME ) {
1801 pull_ascii_nstring(name, namerec->name.name);
1802 x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */
1803 (int)namerec->data.death_time);
1805 for (i = 0; i < namerec->data.num_ips; i++)
1806 x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1807 x_fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1812 chmod(fnamenew,0644);
1814 rename(fnamenew,fname);
1820 /****************************************************************************
1821 Process a internal Samba message receiving a wins record.
1822 ***************************************************************************/
1824 void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
1826 WINS_RECORD *record;
1827 struct name_record *namerec = NULL;
1828 struct name_record *new_namerec = NULL;
1829 struct nmb_name question;
1830 BOOL overwrite=False;
1831 struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
1837 /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */
1838 record=(WINS_RECORD *)buf;
1840 make_nmb_name(&question, record->name, record->type);
1842 namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
1844 /* record doesn't exist, add it */
1845 if (namerec == NULL) {
1846 DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
1847 record->name, record->type, inet_ntoa(record->wins_ip)));
1849 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1850 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1851 if (new_namerec!=NULL) {
1852 update_wins_owner(new_namerec, record->wins_ip);
1853 update_wins_flag(new_namerec, record->wins_flags);
1854 new_namerec->data.id=record->id;
1856 wins_server_subnet->namelist_changed = True;
1860 /* check if we have a conflict */
1861 if (namerec != NULL) {
1862 /* both records are UNIQUE */
1863 if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
1865 /* the database record is a replica */
1866 if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
1867 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
1868 if (ip_equal(namerec->data.wins_ip, record->wins_ip))
1873 /* we are the wins owner of the database record */
1874 /* the 2 records have the same IP address */
1875 if (ip_equal(namerec->data.ip[0], record->ip[0])) {
1876 if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
1877 get_global_id_and_update(&namerec->data.id, True);
1882 /* the 2 records have different IP address */
1883 if (namerec->data.wins_flags&WINS_ACTIVE) {
1884 if (record->wins_flags&WINS_TOMBSTONED)
1885 get_global_id_and_update(&namerec->data.id, True);
1886 if (record->wins_flags&WINS_ACTIVE)
1887 /* send conflict challenge to the replica node */
1896 /* the replica is a standard group */
1897 if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
1898 /* if the database record is unique and active force a name release */
1899 if (namerec->data.wins_flags&WINS_UNIQUE)
1900 /* send a release name to the unique node */
1906 /* the replica is a special group */
1907 if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
1908 if (namerec->data.wins_flags&WINS_ACTIVE) {
1909 for (i=0; i<record->num_ips; i++)
1910 if(!find_ip_in_name_record(namerec, record->ip[i]))
1911 add_ip_to_name_record(namerec, record->ip[i]);
1917 /* the replica is a multihomed host */
1919 /* I'm giving up on multi homed. Too much complex to understand */
1921 if (record->wins_flags&WINS_MHOMED) {
1922 if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
1923 if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
1927 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1930 if (ip_equal(namerec->data.wins_ip, our_fake_ip))
1931 if (namerec->data.wins_flags&WINS_UNIQUE)
1932 get_global_id_and_update(&namerec->data.id, True);
1936 if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
1937 if (namerec->data.wins_flags&WINS_UNIQUE ||
1938 namerec->data.wins_flags&WINS_MHOMED)
1939 if (ip_equal(record->wins_ip, namerec->data.wins_ip))
1944 if (overwrite == False)
1945 DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
1946 record->name, record->type, inet_ntoa(record->wins_ip)));
1948 DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
1949 record->name, record->type, inet_ntoa(record->wins_ip)));
1951 /* remove the old record and add a new one */
1952 remove_name_from_namelist( wins_server_subnet, namerec );
1953 new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
1954 EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
1955 if (new_namerec!=NULL) {
1956 update_wins_owner(new_namerec, record->wins_ip);
1957 update_wins_flag(new_namerec, record->wins_flags);
1958 new_namerec->data.id=record->id;
1960 wins_server_subnet->namelist_changed = True;
1963 wins_server_subnet->namelist_changed = True;