1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-28 01:58:17 +03:00

This commit finally gives us multiple wins server groups. We now

accept an extended syntax for 'wins server' like this:

  wins server = group1:192.168.2.10 group2:192.168.3.99 group1:192.168.0.1

The tags before the IPs don't mean anything, they are just a way of
grouping IPs together. If you use the old syntax (ie. no ':') then
an implicit group name of '*' is used. In general I'd recommend people
use interface names for the group names, but it doesn't matter much.

When we register in nmbd we try to register all our IPs with each group
of WINS servers. We keep trying until all of them are registered with
every group, falling back to the failover WINS servers for each group
as we go.

When we do a WINS lookup we try each of the WINS servers for each group.
If a WINS server for a group gives a negative answer then we give up
on that group and move to the next group. If it times out then
we move to the next failover wins server in the group.

In either case, if a WINS server doesn't respond then we mark it dead
for 10 minutes, to prevent lengthy waits for dead servers.
(This used to be commit e125f06058b6b51382cf046b1dbb30728b8aeda5)
This commit is contained in:
Andrew Tridgell 2002-06-26 12:17:11 +00:00
parent 38bd5bf9eb
commit caeaa0acb0
8 changed files with 548 additions and 257 deletions

View File

@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
Samba utility functions
Samba wins server helper functions
Copyright (C) Andrew Tridgell 1992-2002
Copyright (C) Christopher R. Hertel 2000
@ -21,6 +21,41 @@
#include "includes.h"
/*
this is pretty much a complete rewrite of the earlier code. The main
aim of the rewrite is to add support for having multiple wins server
lists, so Samba can register with multiple groups of wins servers
and each group has a failover list of wins servers.
Central to the way it all works is the idea of a wins server
'tag'. A wins tag is a label for a group of wins servers. For
example if you use
wins server = fred:192.168.2.10 mary:192.168.3.199 fred:192.168.2.61
then you would have two groups of wins servers, one tagged with the
name 'fred' and the other with the name 'mary'. I would usually
recommend using interface names instead of 'fred' and 'mary' but
they can be any alpha string.
Now, how does it all work. Well, nmbd needs to register each of its
IPs with each of its names once with each group of wins servers. So
it tries registering with the first one mentioned in the list, then
if that fails it marks that WINS server dead and moves onto the next
one.
In the client code things are a bit different. As each of the groups
of wins servers is a separate name space we need to try each of the
groups until we either succeed or we run out of wins servers to
try. If we get a negative response from a wins server then that
means the name doesn't exist in that group, so we give up on that
group and move to the next group. If we don't get a response at all
then maybe the wins server is down, in which case we need to
failover to the next one for that group.
confused yet? (tridge)
*/
/* how long a server is marked dead for */
#define DEATH_TIME 600
@ -33,10 +68,17 @@ static struct wins_dead {
} *dead_servers;
/* an internal convenience structure for an IP with a short string tag
attached */
struct tagged_ip {
fstring tag;
struct in_addr ip;
};
/*
see if an ip is on the dead list
*/
static int wins_is_dead(struct in_addr ip)
BOOL wins_srv_is_dead(struct in_addr ip)
{
struct wins_dead *d;
for (d=dead_servers; d; d=d->next) {
@ -46,12 +88,12 @@ static int wins_is_dead(struct in_addr ip)
DEBUG(4,("Reviving wins server %s\n", inet_ntoa(ip)));
DLIST_REMOVE(dead_servers, d);
free(d);
return 0;
return False;
}
return 1;
return True;
}
}
return 0;
return False;
}
/*
@ -61,7 +103,7 @@ void wins_srv_died(struct in_addr ip)
{
struct wins_dead *d;
if (is_zero_ip(ip) || wins_is_dead(ip)) {
if (is_zero_ip(ip) || wins_srv_is_dead(ip)) {
return;
}
@ -79,11 +121,16 @@ void wins_srv_died(struct in_addr ip)
/*
return the total number of wins servers, dead or not
*/
unsigned long wins_srv_count(void)
unsigned wins_srv_count(void)
{
char **list;
int count = 0;
if (lp_wins_support()) {
/* simple - just talk to ourselves */
return 1;
}
list = lp_wins_server_list();
for (count=0; list && list[count]; count++) /* nop */ ;
@ -91,32 +138,214 @@ unsigned long wins_srv_count(void)
return count;
}
/*
parse an IP string that might be in tagged format
the result is a tagged_ip structure containing the tag
and the ip in in_addr format. If there is no tag then
use the tag '*'
*/
static void parse_ip(struct tagged_ip *ip, const char *str)
{
char *s = strchr(str, ':');
if (!s) {
fstrcpy(ip->tag, "*");
ip->ip = *interpret_addr2(str);
return;
}
ip->ip = *interpret_addr2(s+1);
fstrcpy(ip->tag, str);
s = strchr(ip->tag, ':');
if (s) *s = 0;
}
/*
return the IP of the currently active wins server, or the zero IP otherwise
*/
struct in_addr wins_srv_ip(void)
{
char **list;
struct in_addr ip;
int i;
struct tagged_ip t_ip;
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
extern struct in_addr loopback_ip;
return loopback_ip;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
zero_ip(&ip);
return ip;
zero_ip(&t_ip.ip);
return t_ip.ip;
}
/* find the first live one */
for (i=0; list[i]; i++) {
ip = *interpret_addr2(list[i]);
if (!wins_is_dead(ip)) {
DEBUG(6,("Current wins server is %s\n", inet_ntoa(ip)));
return ip;
parse_ip(&t_ip, list[i]);
if (!wins_srv_is_dead(t_ip.ip)) {
DEBUG(6,("Current wins server is %s\n", inet_ntoa(t_ip.ip)));
return t_ip.ip;
}
}
/* damn, they are all dead. Keep trying the primary until they revive */
ip = *interpret_addr2(list[0]);
parse_ip(&t_ip, list[0]);
return ip;
return t_ip.ip;
}
/*
return the list of wins server tags. A 'tag' is used to distinguish
wins server as either belonging to the same name space or a separate
name space. Usually you would setup your 'wins server' option to
list one or more wins server per interface and use the interface
name as your tag, but you are free to use any tag you like.
*/
char **wins_srv_tags(void)
{
char **ret = NULL;
int count=0, i, j;
char **list;
if (lp_wins_support()) {
/* give the caller something to chew on. This makes
the rest of the logic simpler (ie. less special cases) */
ret = (char **)malloc(sizeof(char *)*2);
if (!ret) return NULL;
ret[0] = strdup("*");
ret[1] = NULL;
return ret;
}
list = lp_wins_server_list();
if (!list) return NULL;
/* yes, this is O(n^2) but n is very small */
for (i=0;list[i];i++) {
struct tagged_ip t_ip;
parse_ip(&t_ip, list[i]);
/* see if we already have it */
for (j=0;j<count;j++) {
if (strcmp(ret[j], t_ip.tag) == 0) {
break;
}
}
if (j != count) {
/* we already have it. Move along */
continue;
}
/* add it to the list */
ret = (char **)Realloc(ret, (count+1) * sizeof(char *));
ret[count] = strdup(t_ip.tag);
if (!ret[count]) break;
count++;
}
if (count) {
/* make sure we null terminate */
ret[count] = NULL;
}
return ret;
}
/* free a list of wins server tags given by wins_srv_tags */
void wins_srv_tags_free(char **list)
{
int i;
if (!list) return;
for (i=0; list[i]; i++) {
free(list[i]);
}
free(list);
}
/*
return the IP of the currently active wins server for the given tag,
or the zero IP otherwise
*/
struct in_addr wins_srv_ip_tag(const char *tag)
{
char **list;
int i;
struct tagged_ip t_ip;
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
extern struct in_addr loopback_ip;
return loopback_ip;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
struct in_addr ip;
zero_ip(&ip);
return ip;
}
/* find the first live one for this tag */
for (i=0; list[i]; i++) {
parse_ip(&t_ip, list[i]);
if (strcmp(tag, t_ip.tag) != 0) {
/* not for the right tag. Move along */
continue;
}
if (!wins_srv_is_dead(t_ip.ip)) {
DEBUG(6,("Current wins server for tag '%s' is %s\n", tag, inet_ntoa(t_ip.ip)));
return t_ip.ip;
}
}
/* they're all dead - try the first one until they revive */
for (i=0; list[i]; i++) {
parse_ip(&t_ip, list[i]);
if (strcmp(tag, t_ip.tag) != 0) {
continue;
}
return t_ip.ip;
}
/* this can't happen?? */
zero_ip(&t_ip.ip);
return t_ip.ip;
}
/*
return a count of the number of IPs for a particular tag, including
dead ones
*/
unsigned wins_srv_count_tag(const char *tag)
{
char **list;
int i, count=0;
/* if we are a wins server then we always just talk to ourselves */
if (lp_wins_support()) {
return 1;
}
list = lp_wins_server_list();
if (!list || !list[0]) {
return 0;
}
/* find the first live one for this tag */
for (i=0; list[i]; i++) {
struct tagged_ip t_ip;
parse_ip(&t_ip, list[i]);
if (strcmp(tag, t_ip.tag) == 0) {
count++;
}
}
return count;
}

View File

@ -302,10 +302,12 @@ BOOL name_register(int fd, const char *name, int name_type,
Do a netbios name query to find someones IP.
Returns an array of IP addresses or NULL if none.
*count will be set to the number of addresses returned.
*timed_out is set if we failed by timing out
****************************************************************************/
struct in_addr *name_query(int fd,const char *name,int name_type,
BOOL bcast,BOOL recurse,
struct in_addr to_ip, int *count, int *flags)
struct in_addr to_ip, int *count, int *flags,
BOOL *timed_out)
{
BOOL found=False;
int i, retries = 3;
@ -315,6 +317,10 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
struct packet_struct *p2;
struct nmb_packet *nmb = &p.packet.nmb;
struct in_addr *ip_list = NULL;
if (timed_out) {
*timed_out = False;
}
memset((char *)&p,'\0',sizeof(p));
(*count) = 0;
@ -465,10 +471,8 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
}
}
/* Reach here if we've timed out waiting for replies.. */
if (!bcast && !found) {
/* Timed out wating for WINS server to respond. Mark it dead. */
wins_srv_died( to_ip );
if (timed_out) {
*timed_out = True;
}
return ip_list;
@ -619,7 +623,7 @@ BOOL name_resolve_bcast(const char *name, int name_type,
/* Done this way to fix compiler error on IRIX 5.x */
sendto_ip = *iface_n_bcast(i);
*return_ip_list = name_query(sock, name, name_type, True,
True, sendto_ip, return_count, &flags);
True, sendto_ip, return_count, &flags, NULL);
if(*return_ip_list != NULL) {
close(sock);
return True;
@ -637,59 +641,80 @@ BOOL name_resolve_bcast(const char *name, int name_type,
static BOOL resolve_wins(const char *name, int name_type,
struct in_addr **return_iplist, int *return_count)
{
int sock;
struct in_addr wins_ip;
BOOL wins_ismyip;
int sock, t, i;
char **wins_tags;
*return_iplist = NULL;
*return_count = 0;
/*
* "wins" means do a unicast lookup to the WINS server.
* Ignore if there is no WINS server specified or if the
* WINS server is one of our interfaces (if we're being
* called from within nmbd - we can't do this call as we
* would then block).
*/
DEBUG(3,("resolve_wins: Attempting wins lookup for name %s<0x%x>\n", name, name_type));
if (lp_wins_support()) {
/*
* We're providing WINS support. Call ourselves so
* long as we're not nmbd.
*/
extern struct in_addr loopback_ip;
wins_ip = loopback_ip;
wins_ismyip = True;
} else if( wins_srv_count() < 1 ) {
if (wins_srv_count() < 1) {
DEBUG(3,("resolve_wins: WINS server resolution selected and no WINS servers listed.\n"));
return False;
} else {
wins_ip = wins_srv_ip();
wins_ismyip = ismyip(wins_ip);
}
DEBUG(3, ("resolve_wins: WINS server == <%s>\n", inet_ntoa(wins_ip)) );
if((wins_ismyip && !global_in_nmbd) || !wins_ismyip) {
int flags;
sock = open_socket_in( SOCK_DGRAM, 0, 3,
interpret_addr(lp_socket_address()),
True );
if (sock != -1) {
*return_iplist = name_query( sock, name,
name_type, False,
True, wins_ip,
return_count, &flags);
if(*return_iplist != NULL) {
close(sock);
return True;
/* we try a lookup on each of the WINS tags in turn */
wins_tags = wins_srv_tags();
if (!wins_tags) {
/* huh? no tags?? give up in disgust */
return False;
}
/* in the worst case we will try every wins server with every
tag! */
for (t=0; wins_tags && wins_tags[t]; t++) {
for (i=0; i<wins_srv_count_tag(wins_tags[t]); i++) {
struct in_addr wins_ip;
int flags;
BOOL timed_out;
wins_ip = wins_srv_ip_tag(wins_tags[t]);
if (global_in_nmbd && ismyip(wins_ip)) {
/* yikes! we'll loop forever */
continue;
}
/* skip any that have been unresponsive lately */
if (wins_srv_is_dead(wins_ip)) {
continue;
}
DEBUG(3,("resolve_wins: using WINS server %s and tag '%s'\n", inet_ntoa(wins_ip), wins_tags[t]));
sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True);
if (sock == -1) {
continue;
}
*return_iplist = name_query(sock,name,name_type, False,
True, wins_ip, return_count, &flags,
&timed_out);
if (*return_iplist != NULL) {
goto success;
}
close(sock);
if (timed_out) {
/* Timed out wating for WINS server to respond. Mark it dead. */
wins_srv_died(wins_ip);
} else {
/* The name definately isn't in this
group of WINS servers. goto the next group */
break;
}
}
}
wins_srv_tags_free(wins_tags);
return False;
success:
wins_srv_tags_free(wins_tags);
close(sock);
return True;
}
/********************************************************

View File

@ -155,131 +155,193 @@ name %s on subnet %s.\n", inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->su
remove_response_record(subrec, rrec);
}
/****************************************************************************
Deal with a timeout of a WINS registration request
****************************************************************************/
static void wins_registration_timeout(struct subnet_record *subrec,
struct response_record *rrec)
{
struct userdata_struct *userdata = rrec->userdata;
DEBUG(2,("register_name_timeout_response: WINS server at address %s is not responding.\n",
inet_ntoa(rrec->packet->ip)));
/* mark it temporarily dead */
wins_srv_died(rrec->packet->ip);
/* if we have some userdata then use that to work out what
wins server to try next */
if (userdata) {
const char *tag = (const char *)userdata->data;
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
struct nmb_name *nmbname = &sent_nmb->question.question_name;
/* and try the next wins server in our failover list */
rrec->packet->ip = wins_srv_ip_tag(tag);
/* also update the UNICODE subnet IPs */
subrec->bcast_ip = subrec->mask_ip = subrec->myip = rrec->packet->ip;
DEBUG(6,("Retrying register of name %s with WINS server %s using tag '%s'\n",
nmb_namestr(nmbname), inet_ntoa(rrec->packet->ip), tag));
}
/* Keep trying to contact the WINS server periodically. This allows
us to work correctly if the WINS server is down temporarily when
we come up. */
/* Reset the number of attempts to zero and double the interval between
retries. Max out at 5 minutes. */
rrec->repeat_count = 3;
rrec->repeat_interval *= 2;
if(rrec->repeat_interval > (5 * 60))
rrec->repeat_interval = (5 * 60);
rrec->repeat_time = time(NULL) + rrec->repeat_interval;
rrec->in_expiration_processing = False;
DEBUG(5,("register_name_timeout_response: increasing WINS timeout to %d seconds.\n",
(int)rrec->repeat_interval));
/* notice that we don't remove the response record. This keeps
us trying to register with each of our failover wins
servers until we succeed */
}
/****************************************************************************
Deal with a timeout when registering one of our names.
****************************************************************************/
static void register_name_timeout_response(struct subnet_record *subrec,
struct response_record *rrec)
struct response_record *rrec)
{
/*
* If we are registering unicast, then NOT getting a response is an
* error - we do not have the name. If we are registering broadcast,
* then we don't expect to get a response.
*/
/*
* If we are registering unicast, then NOT getting a response is an
* error - we do not have the name. If we are registering broadcast,
* then we don't expect to get a response.
*/
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
BOOL bcast = sent_nmb->header.nm_flags.bcast;
BOOL success = False;
struct nmb_name *question_name = &sent_nmb->question.question_name;
uint16 nb_flags = 0;
int ttl = 0;
struct in_addr registered_ip;
struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
BOOL bcast = sent_nmb->header.nm_flags.bcast;
BOOL success = False;
struct nmb_name *question_name = &sent_nmb->question.question_name;
uint16 nb_flags = 0;
int ttl = 0;
struct in_addr registered_ip;
if (bcast) {
if(rrec->num_msgs == 0) {
/* Not receiving a message is success for broadcast registration. */
success = True;
if(bcast)
{
if(rrec->num_msgs == 0)
{
/* Not receiving a message is success for broadcast registration. */
success = True;
/* Pull the success values from the original request packet. */
nb_flags = get_nb_flags(sent_nmb->additional->rdata);
ttl = sent_nmb->additional->ttl;
putip(&registered_ip,&sent_nmb->additional->rdata[2]);
}
} else {
/* Unicast - if no responses then it's an error. */
if(rrec->num_msgs == 0) {
wins_registration_timeout(subrec, rrec);
return;
}
/* Pull the success values from the original request packet. */
nb_flags = get_nb_flags(sent_nmb->additional->rdata);
ttl = sent_nmb->additional->ttl;
putip(&registered_ip,&sent_nmb->additional->rdata[2]);
}
}
else
{
/* Unicast - if no responses then it's an error. */
if(rrec->num_msgs == 0)
{
DEBUG(2,("register_name_timeout_response: WINS server at address %s is not \
responding.\n", inet_ntoa(rrec->packet->ip)));
/* we got responses, but timed out?? bizarre. Treat it as failure. */
}
/* mark it temporarily dead */
wins_srv_died(rrec->packet->ip);
DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
if(success) {
/* Enter the registered name into the subnet name database before calling
the success function. */
standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
if( rrec->success_fn)
(*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
} else {
if( rrec->fail_fn)
(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
/* Remove the name. */
standard_fail_register( subrec, rrec, question_name);
}
/* and try the next wins server in our failover list */
rrec->packet->ip = wins_srv_ip();
/* Ensure we don't retry. */
remove_response_record(subrec, rrec);
}
/* also update the UNICODE subnet IPs */
subrec->bcast_ip = subrec->mask_ip = subrec->myip = rrec->packet->ip;
/* Keep trying to contact the WINS server periodically. This allows
us to work correctly if the WINS server is down temporarily when
we come up. */
/****************************************************************************
initiate one multi-homed name registration packet
****************************************************************************/
static void multihomed_register_one(struct nmb_name *nmbname,
uint16 nb_flags,
register_name_success_function success_fn,
register_name_fail_function fail_fn,
struct in_addr ip,
const char *tag)
{
struct userdata_struct *userdata;
struct in_addr wins_ip = wins_srv_ip_tag(tag);
/* Reset the number of attempts to zero and double the interval between
retries. Max out at 5 minutes. */
rrec->repeat_count = 3;
rrec->repeat_interval *= 2;
if(rrec->repeat_interval > (5 * 60))
rrec->repeat_interval = (5 * 60);
rrec->repeat_time = time(NULL) + rrec->repeat_interval;
rrec->in_expiration_processing = False;
userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1);
if (!userdata) {
DEBUG(0,("Failed to allocate userdata structure!\n"));
return;
}
ZERO_STRUCTP(userdata);
userdata->userdata_len = strlen(tag) + 1;
strlcpy(userdata->data, tag, userdata->userdata_len);
DEBUG(5,("register_name_timeout_response: increasing WINS timeout to %d seconds.\n",
(int)rrec->repeat_interval));
return; /* Don't remove the response record. */
}
}
DEBUG(6,("Registering name %s with WINS server %s using tag '%s'\n",
nmb_namestr(nmbname), inet_ntoa(wins_ip), tag));
DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
if(success)
{
/* Enter the registered name into the subnet name database before calling
the success function. */
standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
if( rrec->success_fn)
(*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
}
else
{
if( rrec->fail_fn)
(*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
/* Remove the name. */
standard_fail_register( subrec, rrec, question_name);
}
/* Ensure we don't retry. */
remove_response_record(subrec, rrec);
if (queue_register_multihomed_name(unicast_subnet,
register_name_response,
register_name_timeout_response,
success_fn,
fail_fn,
userdata,
nmbname,
nb_flags,
ip,
wins_ip) == NULL) {
DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
nmb_namestr(nmbname), inet_ntoa(ip)));
}
}
/****************************************************************************
Try and register one of our names on the unicast subnet - multihomed.
****************************************************************************/
static BOOL multihomed_register_name( struct nmb_name *nmbname, uint16 nb_flags,
register_name_success_function success_fn,
register_name_fail_function fail_fn)
{
/*
If we are adding a group name, we just send multiple
register name packets to the WINS server (this is an
internet group name.
/*
If we are adding a group name, we just send multiple
register name packets to the WINS server (this is an
internet group name.
If we are adding a unique name, We need first to add
our names to the unicast subnet namelist. This is
because when a WINS server receives a multihomed
registration request, the first thing it does is to
send a name query to the registering machine, to see
if it has put the name in it's local namelist.
We need the name there so the query response code in
nmbd_incomingrequests.c will find it.
We are adding this name prematurely (we don't really
have it yet), but as this is on the unicast subnet
only we will get away with this (only the WINS server
will ever query names from us on this subnet).
*/
If we are adding a unique name, We need first to add
our names to the unicast subnet namelist. This is
because when a WINS server receives a multihomed
registration request, the first thing it does is to
send a name query to the registering machine, to see
if it has put the name in it's local namelist.
We need the name there so the query response code in
nmbd_incomingrequests.c will find it.
We are adding this name prematurely (we don't really
have it yet), but as this is on the unicast subnet
only we will get away with this (only the WINS server
will ever query names from us on this subnet).
*/
int num_ips=0;
int i;
int i, t;
struct in_addr *ip_list = NULL;
struct subnet_record *subrec;
char **wins_tags;
for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
num_ips++;
@ -288,7 +350,7 @@ static BOOL multihomed_register_name( struct nmb_name *nmbname, uint16 nb_flags,
return True;
}
for( subrec = FIRST_SUBNET, i = 0;
for (subrec = FIRST_SUBNET, i = 0;
subrec;
subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
ip_list[i] = subrec->myip;
@ -298,26 +360,20 @@ static BOOL multihomed_register_name( struct nmb_name *nmbname, uint16 nb_flags,
nb_flags, lp_max_ttl(), SELF_NAME,
num_ips, ip_list);
/* Now try and register the name, num_ips times. On the last time use
the given success and fail functions. */
for (i = 0; i < num_ips; i++) {
if (queue_register_multihomed_name( unicast_subnet,
register_name_response,
register_name_timeout_response,
(i == num_ips - 1) ? success_fn : NULL,
(i == num_ips - 1) ? fail_fn : NULL,
NULL,
nmbname,
nb_flags,
ip_list[i]) == NULL) {
DEBUG(0,("multihomed_register_name: Failed to send packet trying to \
register name %s IP %s\n", nmb_namestr(nmbname), inet_ntoa(ip_list[i]) ));
SAFE_FREE(ip_list);
return True;
/* get the list of wins tags - we try to register for each of them */
wins_tags = wins_srv_tags();
/* Now try and register the name, num_ips times for each wins tag. */
for (t=0; wins_tags[t]; t++) {
for (i = 0; i < num_ips; i++) {
multihomed_register_one(nmbname, nb_flags,
success_fn, fail_fn,
ip_list[i],
wins_tags[t]);
}
}
wins_srv_tags_free(wins_tags);
SAFE_FREE(ip_list);

View File

@ -519,64 +519,61 @@ struct response_record *queue_register_name( struct subnet_record *subrec,
}
/****************************************************************************
Queue a multihomed register name packet to the broadcast address of a subnet.
Queue a multihomed register name packet to a given WINS server IP
****************************************************************************/
struct response_record *queue_register_multihomed_name( struct subnet_record *subrec,
response_function resp_fn,
timeout_response_function timeout_fn,
register_name_success_function success_fn,
register_name_fail_function fail_fn,
struct userdata_struct *userdata,
struct nmb_name *nmbname,
uint16 nb_flags,
struct in_addr register_ip)
response_function resp_fn,
timeout_response_function timeout_fn,
register_name_success_function success_fn,
register_name_fail_function fail_fn,
struct userdata_struct *userdata,
struct nmb_name *nmbname,
uint16 nb_flags,
struct in_addr register_ip,
struct in_addr wins_ip)
{
struct packet_struct *p;
struct response_record *rrec;
BOOL ret;
/* Sanity check. */
if(subrec != unicast_subnet)
{
DEBUG(0,("queue_register_multihomed_name: should only be done on \
struct packet_struct *p;
struct response_record *rrec;
BOOL ret;
/* Sanity check. */
if(subrec != unicast_subnet) {
DEBUG(0,("queue_register_multihomed_name: should only be done on \
unicast subnet. subnet is %s\n.", subrec->subnet_name ));
return NULL;
}
return NULL;
}
if(assert_check_subnet(subrec))
return NULL;
if(assert_check_subnet(subrec))
return NULL;
if(( p = create_and_init_netbios_packet(nmbname, False, True,
subrec->bcast_ip)) == NULL)
return NULL;
if ((p = create_and_init_netbios_packet(nmbname, False, True, wins_ip)) == NULL)
return NULL;
if (nb_flags & NB_GROUP)
ret = initiate_name_register_packet( p, nb_flags, &register_ip);
else
ret = initiate_multihomed_name_register_packet( p, nb_flags, &register_ip);
if (nb_flags & NB_GROUP)
ret = initiate_name_register_packet( p, nb_flags, &register_ip);
else
ret = initiate_multihomed_name_register_packet(p, nb_flags, &register_ip);
if(ret == False)
{
p->locked = False;
free_packet(p);
return NULL;
}
if (ret == False) {
p->locked = False;
free_packet(p);
return NULL;
}
if((rrec = make_response_record(subrec, /* subnet record. */
p, /* packet we sent. */
resp_fn, /* function to call on response. */
timeout_fn, /* function to call on timeout. */
(success_function)success_fn, /* function to call on operation success. */
(fail_function)fail_fn, /* function to call on operation fail. */
userdata)) == NULL)
{
p->locked = False;
free_packet(p);
return NULL;
}
return rrec;
if ((rrec = make_response_record(subrec, /* subnet record. */
p, /* packet we sent. */
resp_fn, /* function to call on response. */
timeout_fn, /* function to call on timeout. */
(success_function)success_fn, /* function to call on operation success. */
(fail_function)fail_fn, /* function to call on operation fail. */
userdata)) == NULL) {
p->locked = False;
free_packet(p);
return NULL;
}
return rrec;
}
/****************************************************************************

View File

@ -92,20 +92,14 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
*count = 0;
fd = wins_lookup_open_socket_in();
if (fd == -1)
return NULL;
p = wins_srv_ip();
if( !is_zero_ip(p) ) {
ret = name_query(fd,name,0x20,False,True, p, count, &flags);
goto out;
/* always try with wins first */
if (resolve_wins(name,0x20,&ret,count)) {
return ret;
}
if (lp_wins_support()) {
/* we are our own WINS server */
ret = name_query(fd,name,0x20,False,True, *interpret_addr2("127.0.0.1"), count, &flags);
goto out;
fd = wins_lookup_open_socket_in();
if (fd == -1) {
return NULL;
}
/* uggh, we have to broadcast to each interface in turn */
@ -113,12 +107,11 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
j >= 0;
j--) {
struct in_addr *bcast = iface_n_bcast(j);
ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags);
ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL);
if (ret) break;
}
out:
close(fd);
return ret;
}

View File

@ -115,7 +115,7 @@ static struct node_status *lookup_byaddr_backend(char *addr, int *count)
static struct in_addr *lookup_byname_backend(const char *name, int *count)
{
int fd;
int fd = -1;
struct in_addr *ret = NULL;
struct in_addr p;
int j, flags = 0;
@ -126,33 +126,24 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count)
*count = 0;
fd = wins_lookup_open_socket_in();
if (fd == -1)
return NULL;
p = wins_srv_ip();
if( !is_zero_ip(p) ) {
ret = name_query(fd,name,0x20,False,True, p, count, &flags);
goto out;
/* always try with wins first */
if (resolve_wins(name,0x20,&ret,count)) {
return ret;
}
if (lp_wins_support()) {
/* we are our own WINS server */
ret = name_query(fd,name,0x20,False,True, *interpret_addr2("127.0.0.1"), count, &flags);
goto out;
fd = wins_lookup_open_socket_in();
if (fd == -1) {
return NULL;
}
/* uggh, we have to broadcast to each interface in turn */
for (j=iface_count() - 1;
j >= 0;
j--) {
for (j=iface_count() - 1;j >= 0;j--) {
struct in_addr *bcast = iface_n_bcast(j);
ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags);
ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL);
if (ret) break;
}
out:
out:
close(fd);
return ret;
}

View File

@ -159,7 +159,7 @@ static BOOL query_one(char *lookup, unsigned int lookup_type)
d_printf("querying %s on %s\n", lookup, inet_ntoa(bcast_addr));
ip_list = name_query(ServerFD,lookup,lookup_type,use_bcast,
use_bcast?True:recursion_desired,
bcast_addr,&count, &flags);
bcast_addr,&count, &flags, NULL);
} else {
struct in_addr *bcast;
for (j=iface_count() - 1;
@ -171,7 +171,7 @@ static BOOL query_one(char *lookup, unsigned int lookup_type)
ip_list = name_query(ServerFD,lookup,lookup_type,
use_bcast,
use_bcast?True:recursion_desired,
*bcast,&count, &flags);
*bcast,&count, &flags, NULL);
}
}

View File

@ -34,7 +34,7 @@ BOOL nmbd_running(void)
interpret_addr("127.0.0.1"), True)) != -1) {
if ((ip_list = name_query(fd, "__SAMBA__", 0,
True, True, loopback_ip,
&count, &flags)) != NULL) {
&count, &flags, NULL)) != NULL) {
SAFE_FREE(ip_list);
close(fd);
return True;