2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #define WINS_LIST "wins.dat"
27 #define WINS_VERSION 1
29 extern int DEBUGLEVEL;
30 extern struct in_addr ipzero;
34 /****************************************************************************
35 hash our interfaces and netbios names settings
36 *****************************************************************************/
37 static unsigned wins_hash(void)
40 unsigned ret = iface_hash();
41 extern char **my_netbios_names;
43 for (i=0;my_netbios_names[i];i++)
44 ret ^= str_checksum(my_netbios_names[i]);
46 ret ^= str_checksum(lp_workgroup());
52 /****************************************************************************
53 Determine if this packet should be allocated to the WINS server.
54 *****************************************************************************/
56 BOOL packet_is_for_wins_server(struct packet_struct *packet)
58 struct nmb_packet *nmb = &packet->packet.nmb;
60 /* Only unicast packets go to a WINS server. */
61 if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
63 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
67 /* Check for node status requests. */
68 if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
71 switch(nmb->header.opcode)
74 * A WINS server issues WACKS, not receives them.
77 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
80 * A WINS server only processes registration and
81 * release requests, not responses.
83 case NMB_NAME_REG_OPCODE:
84 case NMB_NAME_MULTIHOMED_REG_OPCODE:
85 case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
86 case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
87 if(nmb->header.response)
89 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
94 case NMB_NAME_RELEASE_OPCODE:
95 if(nmb->header.response)
97 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
103 * Only process unicast name queries with rd = 1.
105 case NMB_NAME_QUERY_OPCODE:
106 if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
108 DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
117 /****************************************************************************
118 Utility function to decide what ttl to give a register/refresh request.
119 *****************************************************************************/
121 static int get_ttl_from_packet(struct nmb_packet *nmb)
123 int ttl = nmb->additional->ttl;
125 if(ttl < lp_min_wins_ttl() )
126 ttl = lp_min_wins_ttl();
128 if(ttl > lp_max_wins_ttl() )
129 ttl = lp_max_wins_ttl();
134 /****************************************************************************
135 Load or create the WINS database.
136 *****************************************************************************/
138 BOOL initialise_wins(void)
141 time_t time_now = time(NULL);
145 if(!lp_we_are_a_wins_server())
148 add_samba_names_to_subnet(wins_server_subnet);
151 /* Setup the async dns. */
155 pstrcpy(fname,lp_lockdir());
156 trim_string(fname,NULL,"/");
158 pstrcat(fname,WINS_LIST);
160 if((fp = sys_fopen(fname,"r")) == NULL)
162 DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
163 fname, strerror(errno) ));
169 pstring name_str, ip_str, ttl_str, nb_flags_str;
170 unsigned int num_ips;
172 struct in_addr *ip_list;
184 /* Read a line from the wins.dat file. Strips whitespace
185 from the beginning and end of the line.
187 if (!fgets_slash(line,sizeof(pstring),fp))
193 if (strncmp(line,"VERSION ", 8) == 0) {
194 if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
195 version != WINS_VERSION ||
196 hash != wins_hash()) {
197 DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
207 * Now we handle multiple IP addresses per name we need
208 * to iterate over the line twice. The first time to
209 * determine how many IP addresses there are, the second
210 * time to actually parse them into the ip_list array.
213 if (!next_token(&ptr,name_str,NULL,sizeof(name_str)))
215 DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
219 if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
221 DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
226 * Determine the number of IP addresses per line.
231 got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
234 if(got_token && strchr(ip_str, '.'))
239 } while( got_token && was_ip);
243 DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
249 DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
253 /* Allocate the space for the ip_list. */
254 if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
256 DEBUG(0,("initialise_wins: Malloc fail !\n"));
260 /* Reset and re-parse the line. */
262 next_token(&ptr,name_str,NULL,sizeof(name_str));
263 next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
264 for(i = 0; i < num_ips; i++)
266 next_token(&ptr, ip_str, NULL, sizeof(ip_str));
267 ip_list[i] = *interpret_addr2(ip_str);
269 next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
272 * Deal with SELF or REGISTER name encoding. Default is REGISTER
273 * for compatibility with old nmbds.
276 if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
278 DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
279 free((char *)ip_list);
283 if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
284 nb_flags_str[strlen(nb_flags_str)-1] = '\0';
286 /* Netbios name. # divides the name from the type (hex): netbios#xx */
287 pstrcpy(name,name_str);
289 if((p = strchr(name,'#')) != NULL)
292 sscanf(p+1,"%x",&type);
295 /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
296 sscanf(nb_flags_str,"%x",&nb_flags);
297 sscanf(ttl_str,"%d",&ttl);
299 /* add all entries that have 60 seconds or more to live */
300 if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
302 if(ttl != PERMANENT_TTL)
305 DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
306 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
308 (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
309 ttl, REGISTER_NAME, num_ips, ip_list );
314 DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
315 name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
318 free((char *)ip_list);
325 /****************************************************************************
326 Send a WINS WACK (Wait ACKnowledgement) response.
327 **************************************************************************/
329 static void send_wins_wack_response(int ttl, struct packet_struct *p)
331 struct nmb_packet *nmb = &p->packet.nmb;
332 unsigned char rdata[2];
334 rdata[0] = rdata[1] = 0;
336 /* Taken from nmblib.c - we need to send back almost
337 identical bytes from the requesting packet header. */
339 rdata[0] = (nmb->header.opcode & 0xF) << 3;
340 if (nmb->header.nm_flags.authoritative &&
341 nmb->header.response) rdata[0] |= 0x4;
342 if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
343 if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
344 if (nmb->header.nm_flags.recursion_available &&
345 nmb->header.response) rdata[1] |= 0x80;
346 if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
348 reply_netbios_packet(p, /* Packet to reply to. */
349 0, /* Result code. */
350 NMB_WAIT_ACK, /* nmbd type code. */
351 NMB_WACK_OPCODE, /* opcode. */
353 (char *)rdata, /* data to send. */
354 2); /* data length. */
357 /****************************************************************************
358 Send a WINS name registration response.
359 **************************************************************************/
361 static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
363 struct nmb_packet *nmb = &p->packet.nmb;
366 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
368 reply_netbios_packet(p, /* Packet to reply to. */
369 rcode, /* Result code. */
370 WINS_REG, /* nmbd type code. */
371 NMB_NAME_REG_OPCODE, /* opcode. */
373 rdata, /* data to send. */
374 6); /* data length. */
377 /***********************************************************************
378 Deal with a name refresh request to a WINS server.
379 ************************************************************************/
381 void wins_process_name_refresh_request(struct subnet_record *subrec,
382 struct packet_struct *p)
384 struct nmb_packet *nmb = &p->packet.nmb;
385 struct nmb_name *question = &nmb->question.question_name;
386 BOOL bcast = nmb->header.nm_flags.bcast;
387 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
388 BOOL group = (nb_flags & NB_GROUP) ? True : False;
389 struct name_record *namerec = NULL;
390 int ttl = get_ttl_from_packet(nmb);
391 struct in_addr from_ip;
393 putip((char *)&from_ip,&nmb->additional->rdata[2]);
398 * We should only get unicast name refresh packets here.
399 * Anyone trying to refresh broadcast should not be going to a WINS
400 * server. Log an error here.
403 DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
404 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
405 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
409 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
410 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
413 * See if the name already exists.
416 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
419 * If this is a refresh request and the name doesn't exist then
420 * treat it like a registration request. This allows us to recover
421 * from errors (tridge)
426 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
427 the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
428 wins_process_name_registration_request(subrec,p);
433 * Check that the group bits for the refreshing name and the
434 * name in our database match.
437 if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
439 DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
440 does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
441 send_wins_name_registration_response(RFS_ERR, 0, p);
446 * For a unique name check that the person refreshing the name is one of the registered IP
447 * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
448 * Just return success for unique 0x1d refreshes. For normal group names update the ttl
449 * and return success.
452 if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
457 update_name_ttl(namerec, ttl);
458 send_wins_name_registration_response(0, ttl, p);
464 * Normal groups are all registered with an IP address of 255.255.255.255
465 * so we can't search for the IP address.
467 update_name_ttl(namerec, ttl);
468 send_wins_name_registration_response(0, ttl, p);
471 else if(!group && (question->name_type == 0x1d))
474 * Special name type - just pretend the refresh succeeded.
476 send_wins_name_registration_response(0, ttl, p);
485 DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
486 is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
487 send_wins_name_registration_response(RFS_ERR, 0, p);
492 /***********************************************************************
493 Deal with a name registration request query success to a client that
496 We have a locked pointer to the original packet stashed away in the
497 userdata pointer. The success here is actually a failure as it means
498 the client we queried wants to keep the name, so we must return
499 a registration failure to the original requestor.
500 ************************************************************************/
502 static void wins_register_query_success(struct subnet_record *subrec,
503 struct userdata_struct *userdata,
504 struct nmb_name *question_name,
506 struct res_rec *answers)
508 struct packet_struct *orig_reg_packet;
510 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
512 DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
513 name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
515 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
517 orig_reg_packet->locked = False;
518 free_packet(orig_reg_packet);
521 /***********************************************************************
522 Deal with a name registration request query failure to a client that
525 We have a locked pointer to the original packet stashed away in the
526 userdata pointer. The failure here is actually a success as it means
527 the client we queried didn't want to keep the name, so we can remove
528 the old name record and then successfully add the new name.
529 ************************************************************************/
531 static void wins_register_query_fail(struct subnet_record *subrec,
532 struct response_record *rrec,
533 struct nmb_name *question_name,
536 struct userdata_struct *userdata = rrec->userdata;
537 struct packet_struct *orig_reg_packet;
538 struct name_record *namerec = NULL;
540 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
543 * We want to just add the name, as we now know the original owner
544 * didn't want it. But we can't just do that as an arbitary
545 * amount of time may have taken place between the name query
546 * request and this timeout/error response. So we check that
547 * the name still exists and is in the same state - if so
548 * we remove it and call wins_process_name_registration_request()
549 * as we know it will do the right thing now.
552 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
554 if( (namerec != NULL)
555 && (namerec->data.source == REGISTER_NAME)
556 && ip_equal(rrec->packet->ip, *namerec->data.ip) )
558 remove_name_from_namelist( subrec, namerec);
563 wins_process_name_registration_request(subrec, orig_reg_packet);
565 DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
566 querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
568 orig_reg_packet->locked = False;
569 free_packet(orig_reg_packet);
572 /***********************************************************************
573 Deal with a name registration request to a WINS server.
575 Use the following pseudocode :
583 | +--- existing name is group
586 | | +--- add name (return).
589 | +--- exiting name is unique
592 | +--- query existing owner (return).
595 +--------name doesn't exist
598 +--- add name (return).
606 | +--- existing name is group
609 | | +--- fail add (return).
612 | +--- exiting name is unique
615 | +--- query existing owner (return).
618 +--------name doesn't exist
621 +--- add name (return).
623 As can be seen from the above, the two cases may be collapsed onto each
624 other with the exception of the case where the name already exists and
625 is a group name. This case we handle with an if statement.
627 ************************************************************************/
629 void wins_process_name_registration_request(struct subnet_record *subrec,
630 struct packet_struct *p)
632 struct nmb_packet *nmb = &p->packet.nmb;
633 struct nmb_name *question = &nmb->question.question_name;
634 BOOL bcast = nmb->header.nm_flags.bcast;
635 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
636 int ttl = get_ttl_from_packet(nmb);
637 struct name_record *namerec = NULL;
638 struct in_addr from_ip;
639 BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;;
641 putip((char *)&from_ip,&nmb->additional->rdata[2]);
646 * We should only get unicast name registration packets here.
647 * Anyone trying to register broadcast should not be going to a WINS
648 * server. Log an error here.
651 DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
652 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
653 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
657 DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
658 IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
661 * See if the name already exists.
664 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
667 * Deal with the case where the name found was a dns entry.
668 * Remove it as we now have a NetBIOS client registering the
672 if( (namerec != NULL)
673 && ( (namerec->data.source == DNS_NAME)
674 || (namerec->data.source == DNSFAIL_NAME) ) )
676 DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
677 a dns lookup - removing it.\n", nmb_namestr(question) ));
678 remove_name_from_namelist( subrec, namerec );
683 * Reject if the name exists and is not a REGISTER_NAME.
684 * (ie. Don't allow any static names to be overwritten.
687 if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
689 DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
690 to register name %s. Name already exists in WINS with source type %d.\n",
691 nmb_namestr(question), namerec->data.source ));
692 send_wins_name_registration_response(RFS_ERR, 0, p);
697 * Special policy decisions based on MS documentation.
698 * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
699 * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
703 * A group name is always added as the local broadcast address, except
704 * for group names ending in 0x1c.
705 * Group names with type 0x1c are registered with individual IP addresses.
708 if(registering_group_name && (question->name_type != 0x1c))
709 from_ip = *interpret_addr2("255.255.255.255");
712 * Ignore all attempts to register a unique 0x1d name, although return success.
715 if(!registering_group_name && (question->name_type == 0x1d))
717 DEBUG(3,("wins_process_name_registration_request: Ignoring request \
718 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
719 send_wins_name_registration_response(0, ttl, p);
724 * Next two cases are the 'if statement' mentioned above.
727 if((namerec != NULL) && NAME_GROUP(namerec))
729 if(registering_group_name)
732 * If we are adding a group name, the name exists and is also a group entry just add this
733 * IP address to it and update the ttl.
736 DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
737 inet_ntoa(from_ip), nmb_namestr(question) ));
739 * Check the ip address is not already in the group.
741 if(!find_ip_in_name_record(namerec, from_ip))
742 add_ip_to_name_record(namerec, from_ip);
743 update_name_ttl(namerec, ttl);
744 send_wins_name_registration_response(0, ttl, p);
750 * If we are adding a unique name, the name exists in the WINS db
751 * and is a group name then reject the registration.
754 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
755 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
756 send_wins_name_registration_response(RFS_ERR, 0, p);
762 * From here on down we know that if the name exists in the WINS db it is
763 * a unique name, not a group name.
767 * If the name exists and is one of our names then check the
768 * registering IP address. If it's not one of ours then automatically
769 * reject without doing the query - we know we will reject it.
772 if((namerec != NULL) && (is_myname(namerec->name.name)) )
776 DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
777 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
778 send_wins_name_registration_response(RFS_ERR, 0, p);
784 * It's one of our names and one of our IP's - update the ttl.
786 update_name_ttl(namerec, ttl);
787 send_wins_name_registration_response(0, ttl, p);
793 * If the name exists and it is a unique registration and the registering IP
794 * is the same as the the (single) already registered IP then just update the ttl.
797 if( !registering_group_name
799 && (namerec->data.num_ips == 1)
800 && ip_equal( namerec->data.ip[0], from_ip ) )
802 update_name_ttl( namerec, ttl );
803 send_wins_name_registration_response( 0, ttl, p );
808 * Finally if the name exists do a query to the registering machine
809 * to see if they still claim to have the name.
812 if( namerec != NULL )
814 char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
815 struct userdata_struct *userdata = (struct userdata_struct *)ud;
818 * First send a WACK to the registering machine.
821 send_wins_wack_response(60, p);
824 * When the reply comes back we need the original packet.
825 * Lock this so it won't be freed and then put it into
826 * the userdata structure.
831 userdata = (struct userdata_struct *)ud;
833 userdata->copy_fn = NULL;
834 userdata->free_fn = NULL;
835 userdata->userdata_len = sizeof(struct packet_struct *);
836 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
839 * Use the new call to send a query directly to an IP address.
840 * This sends the query directly to the IP address, and ensures
841 * the recursion desired flag is not set (you were right Luke :-).
842 * This function should *only* be called from the WINS server
846 query_name_from_wins_server( *namerec->data.ip,
849 wins_register_query_success,
850 wins_register_query_fail,
856 * Name did not exist - add it.
859 (void)add_name_to_subnet( subrec, question->name, question->name_type,
860 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
862 send_wins_name_registration_response(0, ttl, p);
865 /***********************************************************************
866 Deal with a mutihomed name query success to the machine that
867 requested the multihomed name registration.
869 We have a locked pointer to the original packet stashed away in the
871 ************************************************************************/
873 static void wins_multihomed_register_query_success(struct subnet_record *subrec,
874 struct userdata_struct *userdata,
875 struct nmb_name *question_name,
877 struct res_rec *answers)
879 struct packet_struct *orig_reg_packet;
880 struct nmb_packet *nmb;
881 struct name_record *namerec = NULL;
882 struct in_addr from_ip;
885 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
887 nmb = &orig_reg_packet->packet.nmb;
889 putip((char *)&from_ip,&nmb->additional->rdata[2]);
890 ttl = get_ttl_from_packet(nmb);
893 * We want to just add the new IP, as we now know the requesting
894 * machine claims to own it. But we can't just do that as an arbitary
895 * amount of time may have taken place between the name query
896 * request and this response. So we check that
897 * the name still exists and is in the same state - if so
898 * we just add the extra IP and update the ttl.
901 namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
903 if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) )
905 DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
906 a subsequent IP addess.\n", nmb_namestr(question_name) ));
907 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
909 orig_reg_packet->locked = False;
910 free_packet(orig_reg_packet);
915 if(!find_ip_in_name_record(namerec, from_ip))
916 add_ip_to_name_record(namerec, from_ip);
917 update_name_ttl(namerec, ttl);
918 send_wins_name_registration_response(0, ttl, orig_reg_packet);
920 orig_reg_packet->locked = False;
921 free_packet(orig_reg_packet);
924 /***********************************************************************
925 Deal with a name registration request query failure to a client that
928 We have a locked pointer to the original packet stashed away in the
930 ************************************************************************/
932 static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
933 struct response_record *rrec,
934 struct nmb_name *question_name,
937 struct userdata_struct *userdata = rrec->userdata;
938 struct packet_struct *orig_reg_packet;
940 memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
942 DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
943 query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
944 send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
946 orig_reg_packet->locked = False;
947 free_packet(orig_reg_packet);
951 /***********************************************************************
952 Deal with a multihomed name registration request to a WINS server.
953 These cannot be group name registrations.
954 ***********************************************************************/
956 void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
957 struct packet_struct *p)
959 struct nmb_packet *nmb = &p->packet.nmb;
960 struct nmb_name *question = &nmb->question.question_name;
961 BOOL bcast = nmb->header.nm_flags.bcast;
962 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
963 int ttl = get_ttl_from_packet(nmb);
964 struct name_record *namerec = NULL;
965 struct in_addr from_ip;
966 BOOL group = (nb_flags & NB_GROUP) ? True : False;;
968 putip((char *)&from_ip,&nmb->additional->rdata[2]);
973 * We should only get unicast name registration packets here.
974 * Anyone trying to register broadcast should not be going to a WINS
975 * server. Log an error here.
978 DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
979 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
980 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
985 * Only unique names should be registered multihomed.
990 DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
991 received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
992 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
996 DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
997 IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
1000 * Deal with policy regarding 0x1d names.
1003 if(question->name_type == 0x1d)
1005 DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
1006 to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1007 send_wins_name_registration_response(0, ttl, p);
1012 * See if the name already exists.
1015 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1018 * Deal with the case where the name found was a dns entry.
1019 * Remove it as we now have a NetBIOS client registering the
1023 if( (namerec != NULL)
1024 && ( (namerec->data.source == DNS_NAME)
1025 || (namerec->data.source == DNSFAIL_NAME) ) )
1027 DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
1028 - removing it.\n", nmb_namestr(question) ));
1029 remove_name_from_namelist( subrec, namerec);
1034 * Reject if the name exists and is not a REGISTER_NAME.
1035 * (ie. Don't allow any static names to be overwritten.
1038 if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
1040 DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
1041 to register name %s. Name already exists in WINS with source type %d.\n",
1042 nmb_namestr(question), namerec->data.source ));
1043 send_wins_name_registration_response(RFS_ERR, 0, p);
1048 * Reject if the name exists and is a GROUP name.
1051 if((namerec != NULL) && NAME_GROUP(namerec))
1053 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1054 already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
1055 send_wins_name_registration_response(RFS_ERR, 0, p);
1060 * From here on down we know that if the name exists in the WINS db it is
1061 * a unique name, not a group name.
1065 * If the name exists and is one of our names then check the
1066 * registering IP address. If it's not one of ours then automatically
1067 * reject without doing the query - we know we will reject it.
1070 if((namerec != NULL) && (is_myname(namerec->name.name)) )
1072 if(!ismyip(from_ip))
1074 DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
1075 is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
1076 send_wins_name_registration_response(RFS_ERR, 0, p);
1082 * It's one of our names and one of our IP's. Ensure the IP is in the record and
1085 if(!find_ip_in_name_record(namerec, from_ip))
1086 add_ip_to_name_record(namerec, from_ip);
1087 update_name_ttl(namerec, ttl);
1088 send_wins_name_registration_response(0, ttl, p);
1094 * If the name exists check if the IP address is already registered
1095 * to that name. If so then update the ttl and reply success.
1098 if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip))
1100 update_name_ttl(namerec, ttl);
1101 send_wins_name_registration_response(0, ttl, p);
1106 * If the name exists do a query to the owner
1107 * to see if they still want the name.
1112 char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
1113 struct userdata_struct *userdata = (struct userdata_struct *)ud;
1116 * First send a WACK to the registering machine.
1119 send_wins_wack_response(60, p);
1122 * When the reply comes back we need the original packet.
1123 * Lock this so it won't be freed and then put it into
1124 * the userdata structure.
1129 userdata = (struct userdata_struct *)ud;
1131 userdata->copy_fn = NULL;
1132 userdata->free_fn = NULL;
1133 userdata->userdata_len = sizeof(struct packet_struct *);
1134 memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
1137 * Use the new call to send a query directly to an IP address.
1138 * This sends the query directly to the IP address, and ensures
1139 * the recursion desired flag is not set (you were right Luke :-).
1140 * This function should *only* be called from the WINS server
1144 query_name_from_wins_server( p->ip,
1146 question->name_type,
1147 wins_multihomed_register_query_success,
1148 wins_multihomed_register_query_fail,
1155 * Name did not exist - add it.
1158 (void)add_name_to_subnet( subrec, question->name, question->name_type,
1159 nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
1161 send_wins_name_registration_response(0, ttl, p);
1164 /***********************************************************************
1165 Deal with the special name query for *<1b>.
1166 ***********************************************************************/
1168 static void process_wins_dmb_query_request(struct subnet_record *subrec,
1169 struct packet_struct *p)
1171 struct name_record *namerec = NULL;
1176 * Go through all the names in the WINS db looking for those
1177 * ending in <1b>. Use this to calculate the number of IP
1178 * addresses we need to return.
1182 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1184 namerec = (struct name_record *)ubi_trNext( namerec ) )
1186 if( namerec->name.name_type == 0x1b )
1187 num_ips += namerec->data.num_ips;
1193 * There are no 0x1b names registered. Return name query fail.
1195 send_wins_name_query_response(NAM_ERR, p, NULL);
1199 if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
1201 DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
1206 * Go through all the names again in the WINS db looking for those
1207 * ending in <1b>. Add their IP addresses into the list we will
1212 for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
1214 namerec = (struct name_record *)ubi_trNext( namerec ) )
1216 if(namerec->name.name_type == 0x1b)
1219 for(i = 0; i < namerec->data.num_ips; i++)
1221 set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
1222 putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
1229 * Send back the reply containing the IP list.
1232 reply_netbios_packet(p, /* Packet to reply to. */
1233 0, /* Result code. */
1234 WINS_QUERY, /* nmbd type code. */
1235 NMB_NAME_QUERY_OPCODE, /* opcode. */
1236 lp_min_wins_ttl(), /* ttl. */
1237 prdata, /* data to send. */
1238 num_ips*6); /* data length. */
1243 /****************************************************************************
1244 Send a WINS name query response.
1245 **************************************************************************/
1247 void send_wins_name_query_response(int rcode, struct packet_struct *p,
1248 struct name_record *namerec)
1251 char *prdata = rdata;
1252 int reply_data_len = 0;
1260 ttl = (namerec->data.death_time != PERMANENT_TTL) ?
1261 namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
1263 /* Copy all known ip addresses into the return data. */
1264 /* Optimise for the common case of one IP address so
1265 we don't need a malloc. */
1267 if( namerec->data.num_ips == 1 )
1271 if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
1273 DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
1278 for(i = 0; i < namerec->data.num_ips; i++)
1280 set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
1281 putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
1284 sort_query_replies(prdata, i, p->ip);
1286 reply_data_len = namerec->data.num_ips * 6;
1289 reply_netbios_packet(p, /* Packet to reply to. */
1290 rcode, /* Result code. */
1291 WINS_QUERY, /* nmbd type code. */
1292 NMB_NAME_QUERY_OPCODE, /* opcode. */
1294 prdata, /* data to send. */
1295 reply_data_len); /* data length. */
1297 if((prdata != rdata) && (prdata != NULL))
1301 /***********************************************************************
1302 Deal with a name query.
1303 ***********************************************************************/
1305 void wins_process_name_query_request(struct subnet_record *subrec,
1306 struct packet_struct *p)
1308 struct nmb_packet *nmb = &p->packet.nmb;
1309 struct nmb_name *question = &nmb->question.question_name;
1310 struct name_record *namerec = NULL;
1312 DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
1313 nmb_namestr(question), inet_ntoa(p->ip) ));
1316 * Special name code. If the queried name is *<1b> then search
1317 * the entire WINS database and return a list of all the IP addresses
1318 * registered to any <1b> name. This is to allow domain master browsers
1319 * to discover other domains that may not have a presence on their subnet.
1322 if(strequal( question->name, "*") && (question->name_type == 0x1b))
1324 process_wins_dmb_query_request( subrec, p);
1328 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1333 * If it's a DNSFAIL_NAME then reply name not found.
1336 if( namerec->data.source == DNSFAIL_NAME )
1338 DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
1339 nmb_namestr(question) ));
1340 send_wins_name_query_response(NAM_ERR, p, namerec);
1345 * If the name has expired then reply name not found.
1348 if( (namerec->data.death_time != PERMANENT_TTL)
1349 && (namerec->data.death_time < p->timestamp) )
1351 DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
1352 nmb_namestr(question) ));
1353 send_wins_name_query_response(NAM_ERR, p, namerec);
1357 DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
1358 nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
1360 send_wins_name_query_response(0, p, namerec);
1365 * Name not found in WINS - try a dns query if it's a 0x20 name.
1368 if(lp_dns_proxy() &&
1369 ((question->name_type == 0x20) || question->name_type == 0))
1372 DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
1373 nmb_namestr(question) ));
1375 queue_dns_query(p, question, &namerec);
1380 * Name not found - return error.
1383 send_wins_name_query_response(NAM_ERR, p, NULL);
1386 /****************************************************************************
1387 Send a WINS name release response.
1388 **************************************************************************/
1390 static void send_wins_name_release_response(int rcode, struct packet_struct *p)
1392 struct nmb_packet *nmb = &p->packet.nmb;
1395 memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
1397 reply_netbios_packet(p, /* Packet to reply to. */
1398 rcode, /* Result code. */
1399 NMB_REL, /* nmbd type code. */
1400 NMB_NAME_RELEASE_OPCODE, /* opcode. */
1402 rdata, /* data to send. */
1403 6); /* data length. */
1406 /***********************************************************************
1407 Deal with a name release.
1408 ***********************************************************************/
1410 void wins_process_name_release_request(struct subnet_record *subrec,
1411 struct packet_struct *p)
1413 struct nmb_packet *nmb = &p->packet.nmb;
1414 struct nmb_name *question = &nmb->question.question_name;
1415 BOOL bcast = nmb->header.nm_flags.bcast;
1416 uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
1417 struct name_record *namerec = NULL;
1418 struct in_addr from_ip;
1419 BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
1421 putip((char *)&from_ip,&nmb->additional->rdata[2]);
1426 * We should only get unicast name registration packets here.
1427 * Anyone trying to register broadcast should not be going to a WINS
1428 * server. Log an error here.
1431 DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
1432 received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
1433 nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
1437 DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
1438 IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
1441 * Deal with policy regarding 0x1d names.
1444 if(!releasing_group_name && (question->name_type == 0x1d))
1446 DEBUG(3,("wins_process_name_release_request: Ignoring request \
1447 to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
1448 send_wins_name_release_response(0, p);
1453 * See if the name already exists.
1456 namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
1458 if( (namerec == NULL)
1459 || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
1461 send_wins_name_release_response(NAM_ERR, p);
1466 * Check that the sending machine has permission to release this name.
1467 * If it's a group name not ending in 0x1c then just say yes and let
1468 * the group time out.
1471 if(releasing_group_name && (question->name_type != 0x1c))
1473 send_wins_name_release_response(0, p);
1478 * Check that the releasing node is on the list of IP addresses
1479 * for this name. Disallow the release if not.
1482 if(!find_ip_in_name_record(namerec, from_ip))
1484 DEBUG(3,("wins_process_name_release_request: Refusing request to \
1485 release name %s as IP %s is not one of the known IP's for this name.\n",
1486 nmb_namestr(question), inet_ntoa(from_ip) ));
1487 send_wins_name_release_response(NAM_ERR, p);
1492 * Release the name and then remove the IP from the known list.
1495 send_wins_name_release_response(0, p);
1496 remove_ip_from_name_record(namerec, from_ip);
1499 * Remove the name entirely if no IP addresses left.
1501 if (namerec->data.num_ips == 0)
1502 remove_name_from_namelist(subrec, namerec);
1506 /*******************************************************************
1507 WINS time dependent processing.
1508 ******************************************************************/
1510 void initiate_wins_processing(time_t t)
1512 static time_t lasttime = 0;
1516 if (t - lasttime < 20)
1521 if(!lp_we_are_a_wins_server())
1524 expire_names_on_subnet(wins_server_subnet, t);
1526 if(wins_server_subnet->namelist_changed)
1527 wins_write_database(True);
1529 wins_server_subnet->namelist_changed = False;
1532 /*******************************************************************
1533 Write out the current WINS database.
1534 ******************************************************************/
1535 void wins_write_database(BOOL background)
1537 struct name_record *namerec;
1538 pstring fname, fnamenew;
1542 if(!lp_we_are_a_wins_server())
1545 /* we will do the writing in a child process to ensure that the parent
1546 doesn't block while this is done */
1554 slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST);
1555 string_sub(fname,"//", "/");
1556 slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid());
1558 if((fp = sys_fopen(fnamenew,"w")) == NULL)
1560 DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
1567 DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
1569 fprintf(fp,"VERSION %d %u\n", WINS_VERSION, wins_hash());
1572 = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
1574 namerec = (struct name_record *)ubi_trNext( namerec ) )
1579 DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
1581 if( namerec->data.death_time != PERMANENT_TTL )
1585 tm = LocalTime(&namerec->data.death_time);
1587 nl = strrchr( ts, '\n' );
1590 DEBUGADD(4,("TTL = %s ", ts ));
1593 DEBUGADD(4,("TTL = PERMANENT "));
1595 for (i = 0; i < namerec->data.num_ips; i++)
1596 DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
1597 DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
1599 if( namerec->data.source == REGISTER_NAME )
1601 fprintf(fp, "\"%s#%02x\" %d ",
1602 namerec->name.name,namerec->name.name_type, /* Ignore scope. */
1603 (int)namerec->data.death_time);
1605 for (i = 0; i < namerec->data.num_ips; i++)
1606 fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
1607 fprintf( fp, "%2xR\n", namerec->data.nb_flags );
1612 chmod(fnamenew,0644);
1614 rename(fnamenew,fname);