#include "includes.h"
#define WINS_LIST "wins.dat"
+#define WINS_VERSION 1
extern int DEBUGLEVEL;
extern struct in_addr ipzero;
+
+/****************************************************************************
+possibly call the WINS hook external program when a WINS change is made
+*****************************************************************************/
+static void wins_hook(char *operation, struct name_record *namerec, int ttl)
+{
+ pstring command;
+ char *cmd = lp_wins_hook();
+ char *p;
+ int i;
+
+ if (!cmd || !*cmd) return;
+
+ for (p=namerec->name.name; *p; p++) {
+ if (!(isalnum((int)*p) || strchr("._-",*p))) {
+ DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
+ return;
+ }
+ }
+
+ p = command;
+ p += slprintf(p, sizeof(command), "%s %s %s %02x %d",
+ cmd,
+ operation,
+ namerec->name.name,
+ namerec->name.name_type,
+ ttl);
+
+ for (i=0;i<namerec->data.num_ips;i++) {
+ p += slprintf(p, sizeof(command) - (p-command), " %s", inet_ntoa(namerec->data.ip[i]));
+ }
+
+ DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
+ smbrun(command, NULL, False);
+}
+
+
+/****************************************************************************
+hash our interfaces and netbios names settings
+*****************************************************************************/
+static unsigned wins_hash(void)
+{
+ int i;
+ unsigned ret = iface_hash();
+ extern char **my_netbios_names;
+
+ for (i=0;my_netbios_names[i];i++)
+ ret ^= str_checksum(my_netbios_names[i]);
+
+ ret ^= str_checksum(lp_workgroup());
+
+ return ret;
+}
+
+
/****************************************************************************
Determine if this packet should be allocated to the WINS server.
*****************************************************************************/
add_samba_names_to_subnet(wins_server_subnet);
-#ifndef SYNC_DNS
- /* Setup the async dns. */
- start_async_dns();
-#endif
-
pstrcpy(fname,lp_lockdir());
trim_string(fname,NULL,"/");
pstrcat(fname,"/");
pstrcat(fname,WINS_LIST);
- if((fp = fopen(fname,"r")) == NULL)
+ if((fp = sys_fopen(fname,"r")) == NULL)
{
DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
fname, strerror(errno) ));
int type = 0;
int nb_flags;
int ttl;
- enum name_source source;
char *ptr;
char *p;
BOOL got_token;
BOOL was_ip;
int i;
+ unsigned hash;
+ int version;
/* Read a line from the wins.dat file. Strips whitespace
from the beginning and end of the line.
if (*line == '#')
continue;
+ if (strncmp(line,"VERSION ", 8) == 0) {
+ if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 ||
+ version != WINS_VERSION ||
+ hash != wins_hash()) {
+ DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line));
+ fclose(fp);
+ return True;
+ }
+ continue;
+ }
+
ptr = line;
/*
* time to actually parse them into the ip_list array.
*/
- if (!next_token(&ptr,name_str,NULL))
+ if (!next_token(&ptr,name_str,NULL,sizeof(name_str)))
{
DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
continue;
}
- if (!next_token(&ptr,ttl_str,NULL))
+ if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)))
{
DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
continue;
num_ips = 0;
do
{
- got_token = next_token(&ptr,ip_str,NULL);
+ got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str));
was_ip = False;
if(got_token && strchr(ip_str, '.'))
/* Reset and re-parse the line. */
ptr = line;
- next_token(&ptr,name_str,NULL);
- next_token(&ptr,ttl_str,NULL);
+ next_token(&ptr,name_str,NULL,sizeof(name_str));
+ next_token(&ptr,ttl_str,NULL,sizeof(ttl_str));
for(i = 0; i < num_ips; i++)
{
- next_token(&ptr, ip_str, NULL);
+ next_token(&ptr, ip_str, NULL, sizeof(ip_str));
ip_list[i] = *interpret_addr2(ip_str);
- if (ip_equal(ip_list[i], ipzero))
- source = SELF_NAME;
}
- next_token(&ptr,nb_flags_str,NULL);
+ next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str));
/*
* Deal with SELF or REGISTER name encoding. Default is REGISTER
/* add all entries that have 60 seconds or more to live */
if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
{
- struct name_record *namerec;
-
if(ttl != PERMANENT_TTL)
ttl -= time_now;
- DEBUG(4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
+ DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
- namerec = add_name_to_subnet(wins_server_subnet, name, type, nb_flags,
- ttl, REGISTER_NAME, num_ips, ip_list);
+ (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
+ ttl, REGISTER_NAME, num_ips, ip_list );
}
else
DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
-IP %s\n", namestr(question), inet_ntoa(from_ip) ));
+IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
/*
* See if the name already exists.
/*
* If this is a refresh request and the name doesn't exist then
- * fail it.
+ * treat it like a registration request. This allows us to recover
+ * from errors (tridge)
*/
if(namerec == NULL)
{
DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
-the name does not exist.\n", namestr(question) ));
- send_wins_name_registration_response(NAM_ERR, 0, p);
+the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
+ wins_process_name_registration_request(subrec,p);
return;
}
if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
{
DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
-does not match group bit in WINS for this name.\n", namestr(question), group ? "True" : "False" ));
+does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
*/
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
else if(group)
*/
DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
-is IP is not known to the name.\n", namestr(question), inet_ntoa(from_ip) ));
+is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
-name %s. Rejecting registration request.\n", inet_ntoa(ip), namestr(question_name) ));
+name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
{
struct userdata_struct *userdata = rrec->userdata;
struct packet_struct *orig_reg_packet;
- struct nmb_packet *nmb;
struct name_record *namerec = NULL;
- uint16 nb_flags;
- BOOL group;
memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
- nmb = &orig_reg_packet->packet.nmb;
-
- nb_flags = get_nb_flags(nmb->additional->rdata);
- group = (nb_flags & NB_GROUP) ? True : False;
-
/*
* We want to just add the name, as we now know the original owner
* didn't want it. But we can't just do that as an arbitary
namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
- if((namerec != NULL) && (namerec->source == REGISTER_NAME) &&
- ip_equal(rrec->packet->ip, *namerec->ip) )
+ if( (namerec != NULL)
+ && (namerec->data.source == REGISTER_NAME)
+ && ip_equal(rrec->packet->ip, *namerec->data.ip) )
{
remove_name_from_namelist( subrec, namerec);
namerec = NULL;
wins_process_name_registration_request(subrec, orig_reg_packet);
else
DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
-querying for name %s in order to replace it and this reply.\n", namestr(question_name) ));
+querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
orig_reg_packet->locked = False;
free_packet(orig_reg_packet);
int ttl = get_ttl_from_packet(nmb);
struct name_record *namerec = NULL;
struct in_addr from_ip;
- BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;;
+ BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
putip((char *)&from_ip,&nmb->additional->rdata[2]);
DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
-IP %s\n", registering_group_name ? "Group" : "Unique", namestr(question), inet_ntoa(from_ip) ));
+IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
/*
* See if the name already exists.
* name.
*/
- if((namerec != NULL) && ((namerec->source == DNS_NAME) || (namerec->source == DNSFAIL_NAME)))
+ if( (namerec != NULL)
+ && ( (namerec->data.source == DNS_NAME)
+ || (namerec->data.source == DNSFAIL_NAME) ) )
{
- DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was a dns lookup \
-- removing it.\n", namestr(question) ));
- remove_name_from_namelist( subrec, namerec);
+ DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
+a dns lookup - removing it.\n", nmb_namestr(question) ));
+ remove_name_from_namelist( subrec, namerec );
namerec = NULL;
}
* (ie. Don't allow any static names to be overwritten.
*/
- if((namerec != NULL) && (namerec->source != REGISTER_NAME))
+ if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
{
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS with source type %d.\n", namestr(question), namerec->source ));
+ DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
+to register name %s. Name already exists in WINS with source type %d.\n",
+ nmb_namestr(question), namerec->data.source ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
if(!registering_group_name && (question->name_type == 0x1d))
{
DEBUG(3,("wins_process_name_registration_request: Ignoring request \
-to register name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
+to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
send_wins_name_registration_response(0, ttl, p);
return;
}
*/
DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
- inet_ntoa(from_ip), namestr(question) ));
+ inet_ntoa(from_ip), nmb_namestr(question) ));
/*
* Check the ip address is not already in the group.
*/
*/
DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", namestr(question) ));
+already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
if(!ismyip(from_ip))
{
DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", namestr(question) ));
+is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
*/
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
}
* is the same as the the (single) already registered IP then just update the ttl.
*/
- if(!registering_group_name && (namerec != NULL) && (namerec->num_ips == 1) &&
- ip_equal(namerec->ip[0], from_ip))
+ if( !registering_group_name
+ && (namerec != NULL)
+ && (namerec->data.num_ips == 1)
+ && ip_equal( namerec->data.ip[0], from_ip ) )
{
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
+ update_name_ttl( namerec, ttl );
+ send_wins_name_registration_response( 0, ttl, p );
+ wins_hook("refresh", namerec, ttl);
return;
}
* to see if they still claim to have the name.
*/
- if(namerec != NULL)
+ if( namerec != NULL )
{
char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
struct userdata_struct *userdata = (struct userdata_struct *)ud;
* code. JRA.
*/
- query_name_from_wins_server( *namerec->ip, question->name, question->name_type,
- wins_register_query_success,
- wins_register_query_fail,
- userdata);
+ query_name_from_wins_server( *namerec->data.ip,
+ question->name,
+ question->name_type,
+ wins_register_query_success,
+ wins_register_query_fail,
+ userdata );
return;
}
* Name did not exist - add it.
*/
- add_name_to_subnet(subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
+ (void)add_name_to_subnet( subrec, question->name, question->name_type,
+ nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
+ if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
+ wins_hook("add", namerec, ttl);
+ }
send_wins_name_registration_response(0, ttl, p);
}
namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
- if( (namerec == NULL) || (namerec->source != REGISTER_NAME) )
+ if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) )
{
DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
-a subsequent IP addess.\n", namestr(question_name) ));
+a subsequent IP addess.\n", nmb_namestr(question_name) ));
send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
+
+ orig_reg_packet->locked = False;
+ free_packet(orig_reg_packet);
+
return;
}
add_ip_to_name_record(namerec, from_ip);
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, orig_reg_packet);
+ wins_hook("add", namerec, ttl);
+ orig_reg_packet->locked = False;
+ free_packet(orig_reg_packet);
}
/***********************************************************************
memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
-query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), namestr(question_name) ));
+query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
+
+ orig_reg_packet->locked = False;
+ free_packet(orig_reg_packet);
return;
}
DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
{
DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
-IP %s\n", namestr(question), inet_ntoa(from_ip) ));
+IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
/*
* Deal with policy regarding 0x1d names.
if(question->name_type == 0x1d)
{
DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
-to register name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
+to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
send_wins_name_registration_response(0, ttl, p);
return;
}
* name.
*/
- if((namerec != NULL) && ((namerec->source == DNS_NAME) || (namerec->source == DNSFAIL_NAME)))
+ if( (namerec != NULL)
+ && ( (namerec->data.source == DNS_NAME)
+ || (namerec->data.source == DNSFAIL_NAME) ) )
{
DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
-- removing it.\n", namestr(question) ));
+- removing it.\n", nmb_namestr(question) ));
remove_name_from_namelist( subrec, namerec);
namerec = NULL;
}
* (ie. Don't allow any static names to be overwritten.
*/
- if((namerec != NULL) && (namerec->source != REGISTER_NAME))
+ if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
{
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS with source type %d.\n", namestr(question), namerec->source ));
+ DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
+to register name %s. Name already exists in WINS with source type %d.\n",
+ nmb_namestr(question), namerec->data.source ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
if((namerec != NULL) && NAME_GROUP(namerec))
{
DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", namestr(question) ));
+already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
if(!ismyip(from_ip))
{
DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", namestr(question) ));
+is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
send_wins_name_registration_response(RFS_ERR, 0, p);
return;
}
* It's one of our names and one of our IP's. Ensure the IP is in the record and
* update the ttl.
*/
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
+ if(!find_ip_in_name_record(namerec, from_ip)) {
+ add_ip_to_name_record(namerec, from_ip);
+ wins_hook("add", namerec, ttl);
+ } else {
+ wins_hook("refresh", namerec, ttl);
+ }
+
+ update_name_ttl(namerec, ttl);
+ send_wins_name_registration_response(0, ttl, p);
+ return;
}
}
{
update_name_ttl(namerec, ttl);
send_wins_name_registration_response(0, ttl, p);
+ wins_hook("refresh", namerec, ttl);
return;
}
userdata->userdata_len = sizeof(struct packet_struct *);
memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
- /*
- * As query_name uses the subnet broadcast address as the destination
- * of the packet we temporarily change the subnet broadcast address to
- * be the IP address of the requesting machine and send the packet. This
- * is a *horrible* hack but the alternative is to add the destination
- * address parameter to all query_name() calls. I hate this code :-).
+ /*
+ * Use the new call to send a query directly to an IP address.
+ * This sends the query directly to the IP address, and ensures
+ * the recursion desired flag is not set (you were right Luke :-).
+ * This function should *only* be called from the WINS server
+ * code. JRA.
*/
- subrec->bcast_ip = p->ip;
- query_name( subrec, question->name, question->name_type,
- wins_multihomed_register_query_success,
- wins_multihomed_register_query_fail,
- userdata);
- subrec->bcast_ip = ipzero;
+ query_name_from_wins_server( p->ip,
+ question->name,
+ question->name_type,
+ wins_multihomed_register_query_success,
+ wins_multihomed_register_query_fail,
+ userdata );
+
return;
}
* Name did not exist - add it.
*/
- add_name_to_subnet(subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
+ (void)add_name_to_subnet( subrec, question->name, question->name_type,
+ nb_flags, ttl, REGISTER_NAME, 1, &from_ip );
+
+ if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
+ wins_hook("add", namerec, ttl);
+ }
send_wins_name_registration_response(0, ttl, p);
}
*/
num_ips = 0;
- for(namerec = subrec->namelist; namerec; namerec = namerec->next)
+ for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec;
+ namerec = (struct name_record *)ubi_trNext( namerec ) )
{
- if(namerec->name.name_type == 0x1b)
- num_ips += namerec->num_ips;
+ if( namerec->name.name_type == 0x1b )
+ num_ips += namerec->data.num_ips;
}
if(num_ips == 0)
*/
num_ips = 0;
- for(namerec = subrec->namelist; namerec; namerec = namerec->next)
+ for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
+ namerec;
+ namerec = (struct name_record *)ubi_trNext( namerec ) )
{
if(namerec->name.name_type == 0x1b)
{
int i;
- for(i = 0; i < namerec->num_ips; i++)
+ for(i = 0; i < namerec->data.num_ips; i++)
{
- set_nb_flags(&prdata[num_ips * 6],namerec->nb_flags);
- putip((char *)&prdata[(num_ips * 6) + 2], &namerec->ip[i]);
+ set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
+ putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
num_ips++;
}
}
char *prdata = rdata;
int reply_data_len = 0;
int ttl = 0;
- int i = 0;
- int j;
+ int i;
- bzero(rdata,6);
+ memset(rdata,'\0',6);
if(rcode == 0)
{
- int same_net_index = -1;
-
- ttl = (namerec->death_time != PERMANENT_TTL) ?
- namerec->death_time - p->timestamp : lp_max_wins_ttl();
+ ttl = (namerec->data.death_time != PERMANENT_TTL) ?
+ namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
/* Copy all known ip addresses into the return data. */
/* Optimise for the common case of one IP address so
we don't need a malloc. */
- if(namerec->num_ips == 1 )
+ if( namerec->data.num_ips == 1 )
prdata = rdata;
else
{
- if((prdata = (char *)malloc( namerec->num_ips * 6 )) == NULL)
+ if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
{
DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
return;
}
-
- /*
- * Look over the known IP addresses and see if one of them
- * is on the same (local) net as the requesting IP address. If so then
- * put that IP address into the packet as the first IP.
- * We can only do this for local nets as they're the only
- * ones we know the netmask for.
- */
-
- i = 0;
-
- if(is_local_net(p->ip))
- {
- struct in_addr *n_mask = iface_nmask(p->ip);
-
- for( j = 0; j < namerec->num_ips; j++)
- {
- if(same_net( namerec->ip[j], p->ip, *n_mask))
- {
- set_nb_flags(&prdata[0],namerec->nb_flags);
- putip((char *)&prdata[2], &namerec->ip[j]);
- same_net_index = j;
- i = 1;
- }
- }
- }
}
- for(j = 0; j < namerec->num_ips; j++)
+ for(i = 0; i < namerec->data.num_ips; i++)
{
- if(j == same_net_index)
- continue;
- set_nb_flags(&prdata[i*6],namerec->nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->ip[j]);
- i++;
+ set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
+ putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
}
- reply_data_len = namerec->num_ips * 6;
+ sort_query_replies(prdata, i, p->ip);
+
+ reply_data_len = namerec->data.num_ips * 6;
}
reply_netbios_packet(p, /* Packet to reply to. */
struct name_record *namerec = NULL;
DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
- namestr(question), inet_ntoa(p->ip) ));
+ nmb_namestr(question), inet_ntoa(p->ip) ));
/*
* Special name code. If the queried name is *<1b> then search
* If it's a DNSFAIL_NAME then reply name not found.
*/
- if(namerec->source == DNSFAIL_NAME)
+ if( namerec->data.source == DNSFAIL_NAME )
{
DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
- namestr(question) ));
+ nmb_namestr(question) ));
send_wins_name_query_response(NAM_ERR, p, namerec);
return;
}
* If the name has expired then reply name not found.
*/
- if((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < p->timestamp))
+ if( (namerec->data.death_time != PERMANENT_TTL)
+ && (namerec->data.death_time < p->timestamp) )
{
DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
- namestr(question) ));
+ nmb_namestr(question) ));
send_wins_name_query_response(NAM_ERR, p, namerec);
return;
}
DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
- namestr(question), inet_ntoa(namerec->ip[0]) ));
+ nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
send_wins_name_query_response(0, p, namerec);
return;
{
DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
- namestr(question) ));
+ nmb_namestr(question) ));
queue_dns_query(p, question, &namerec);
return;
DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
+ nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
return;
}
DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
-IP %s\n", releasing_group_name ? "Group" : "Unique", namestr(question), inet_ntoa(from_ip) ));
+IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
/*
* Deal with policy regarding 0x1d names.
if(!releasing_group_name && (question->name_type == 0x1d))
{
DEBUG(3,("wins_process_name_release_request: Ignoring request \
-to release name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
+to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
send_wins_name_release_response(0, p);
return;
}
namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
- if((namerec == NULL) || ((namerec != NULL) && (namerec->source != REGISTER_NAME)) )
+ if( (namerec == NULL)
+ || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
{
send_wins_name_release_response(NAM_ERR, p);
return;
{
DEBUG(3,("wins_process_name_release_request: Refusing request to \
release name %s as IP %s is not one of the known IP's for this name.\n",
- namestr(question), inet_ntoa(from_ip) ));
+ nmb_namestr(question), inet_ntoa(from_ip) ));
send_wins_name_release_response(NAM_ERR, p);
return;
}
send_wins_name_release_response(0, p);
remove_ip_from_name_record(namerec, from_ip);
+ wins_hook("delete", namerec, 0);
+
/*
* Remove the name entirely if no IP addresses left.
*/
- if (namerec->num_ips == 0)
+ if (namerec->data.num_ips == 0)
remove_name_from_namelist(subrec, namerec);
}
if (!lasttime)
lasttime = t;
- if (t - lasttime < 5)
+ if (t - lasttime < 20)
return;
+ lasttime = t;
+
if(!lp_we_are_a_wins_server())
return;
expire_names_on_subnet(wins_server_subnet, t);
if(wins_server_subnet->namelist_changed)
- wins_write_database();
+ wins_write_database(True);
wins_server_subnet->namelist_changed = False;
}
/*******************************************************************
Write out the current WINS database.
******************************************************************/
-
-void wins_write_database(void)
+void wins_write_database(BOOL background)
{
struct name_record *namerec;
pstring fname, fnamenew;
-
+
FILE *fp;
if(!lp_we_are_a_wins_server())
return;
- fstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- pstrcat(fname,"/");
- pstrcat(fname,WINS_LIST);
- pstrcpy(fnamenew,fname);
- pstrcat(fnamenew,".");
+ /* we will do the writing in a child process to ensure that the parent
+ doesn't block while this is done */
+ if (background) {
+ CatchChild();
+ if (fork()) {
+ return;
+ }
+ }
- if((fp = fopen(fnamenew,"w")) == NULL)
+ slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST);
+ all_string_sub(fname,"//", "/", 0);
+ slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid());
+
+ if((fp = sys_fopen(fnamenew,"w")) == NULL)
{
DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
+ if (background) {
+ _exit(0);
+ }
return;
}
DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
+
+ fprintf(fp,"VERSION %d %u\n", WINS_VERSION, wins_hash());
- for (namerec = wins_server_subnet->namelist; namerec; namerec = namerec->next)
+ for( namerec
+ = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
+ namerec;
+ namerec = (struct name_record *)ubi_trNext( namerec ) )
{
int i;
struct tm *tm;
- DEBUG(4,("%-19s ", namestr(&namerec->name) ));
+ DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) ));
- if(namerec->death_time != PERMANENT_TTL)
+ if( namerec->data.death_time != PERMANENT_TTL )
{
- tm = LocalTime(&namerec->death_time);
- DEBUG(4,("TTL = %s", asctime(tm) ));
+ char *ts, *nl;
+
+ tm = LocalTime(&namerec->data.death_time);
+ ts = asctime(tm);
+ nl = strrchr( ts, '\n' );
+ if( NULL != nl )
+ *nl = '\0';
+ DEBUGADD(4,("TTL = %s ", ts ));
}
else
- DEBUG(4,("TTL = PERMANENT\t"));
+ DEBUGADD(4,("TTL = PERMANENT "));
- for (i = 0; i < namerec->num_ips; i++)
- DEBUG(4,("%15s ", inet_ntoa(namerec->ip[i]) ));
- DEBUG(4,("%2x\n", namerec->nb_flags ));
+ for (i = 0; i < namerec->data.num_ips; i++)
+ DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
+ DEBUGADD(4,("%2x\n", namerec->data.nb_flags ));
- if (namerec->source == REGISTER_NAME)
+ if( namerec->data.source == REGISTER_NAME )
{
fprintf(fp, "\"%s#%02x\" %d ",
namerec->name.name,namerec->name.name_type, /* Ignore scope. */
- (int)namerec->death_time);
+ (int)namerec->data.death_time);
- for (i = 0; i < namerec->num_ips; i++)
- fprintf(fp, "%s ", inet_ntoa(namerec->ip[i]));
- fprintf(fp, "%2xR\n", namerec->nb_flags);
+ for (i = 0; i < namerec->data.num_ips; i++)
+ fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) );
+ fprintf( fp, "%2xR\n", namerec->data.nb_flags );
}
}
fclose(fp);
- unlink(fname);
chmod(fnamenew,0644);
+ unlink(fname);
rename(fnamenew,fname);
+ if (background) {
+ _exit(0);
+ }
}