summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-06-26 12:17:11 +0000
committerAndrew Tridgell <tridge@samba.org>2002-06-26 12:17:11 +0000
commitcaeaa0acb02f681be6025e3eafded223983960a0 (patch)
tree392e7175718940eff1ebc0ba769a488494e4e9bb /source3/libsmb
parent38bd5bf9eb18bfd4312ff81d566b4e9c90d7e07d (diff)
downloadsamba-caeaa0acb02f681be6025e3eafded223983960a0.tar.gz
samba-caeaa0acb02f681be6025e3eafded223983960a0.tar.bz2
samba-caeaa0acb02f681be6025e3eafded223983960a0.zip
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)
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/namequery.c111
1 files changed, 68 insertions, 43 deletions
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index c85c8c48df..2cdcd49b91 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -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;
}
/********************************************************