summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-07-01 05:09:29 +0000
committerAndrew Tridgell <tridge@samba.org>2002-07-01 05:09:29 +0000
commit2e917ea040d85f06b8e40b6fd178c08ee84797c9 (patch)
tree4ecdc6b6bb7757e92bbf8516bc670e967f7331f4
parentfd8d5e56af81277030137e4d59296ce133dd4906 (diff)
downloadsamba-2e917ea040d85f06b8e40b6fd178c08ee84797c9.tar.gz
samba-2e917ea040d85f06b8e40b6fd178c08ee84797c9.tar.bz2
samba-2e917ea040d85f06b8e40b6fd178c08ee84797c9.zip
sort name query responses by how far they are from our interface
broadcast addresses. This makes it far more likely that we will try to talk to an interface that is routable from one of our interfaces. (This used to be commit bc1a0506868266088ae585a7a5dcb1ac8ca3474d)
-rw-r--r--source3/libsmb/namequery.c41
-rw-r--r--source3/libsmb/nmblib.c4
2 files changed, 43 insertions, 2 deletions
diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c
index 75e2458964..242601d1da 100644
--- a/source3/libsmb/namequery.c
+++ b/source3/libsmb/namequery.c
@@ -298,6 +298,44 @@ BOOL name_register(int fd, const char *name, int name_type,
return True;
}
+
+/*
+ comparison function used by sort_ip_list
+*/
+static int ip_compare(struct in_addr *ip1, struct in_addr *ip2)
+{
+ int max_bits1=0, max_bits2=0;
+ int num_interfaces = iface_count();
+ int i;
+
+ for (i=0;i<num_interfaces;i++) {
+ struct in_addr ip;
+ int bits1, bits2;
+ ip = *iface_n_bcast(i);
+ bits1 = matching_quad_bits((uchar *)&ip1->s_addr, (uchar *)&ip.s_addr);
+ bits2 = matching_quad_bits((uchar *)&ip2->s_addr, (uchar *)&ip.s_addr);
+ max_bits1 = MAX(bits1, max_bits1);
+ max_bits2 = MAX(bits2, max_bits2);
+ }
+
+ return max_bits2 - max_bits1;
+}
+
+/*
+ sort an IP list so that names that are close to one of our interfaces
+ are at the top. This prevents the problem where a WINS server returns an IP that
+ is not reachable from our subnet as the first match
+*/
+static void sort_ip_list(struct in_addr *iplist, int count)
+{
+ if (count <= 1) {
+ return;
+ }
+
+ qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare);
+}
+
+
/****************************************************************************
Do a netbios name query to find someones IP.
Returns an array of IP addresses or NULL if none.
@@ -475,6 +513,9 @@ struct in_addr *name_query(int fd,const char *name,int name_type,
*timed_out = True;
}
+ /* sort the ip list so we choose close servers first if possible */
+ sort_ip_list(ip_list, *count);
+
return ip_list;
}
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 9a37b4252a..ba0d8cee5d 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -1045,7 +1045,7 @@ BOOL match_mailslot_name(struct packet_struct *p, char *mailslot_name)
/****************************************************************************
return the number of bits that match between two 4 character buffers
***************************************************************************/
-static int matching_bits(uchar *p1, uchar *p2)
+int matching_quad_bits(uchar *p1, uchar *p2)
{
int i, j, ret = 0;
for (i=0; i<4; i++) {
@@ -1071,7 +1071,7 @@ compare two query reply records
***************************************************************************/
static int name_query_comp(uchar *p1, uchar *p2)
{
- return matching_bits(p2+2, sort_ip) - matching_bits(p1+2, sort_ip);
+ return matching_quad_bits(p2+2, sort_ip) - matching_quad_bits(p1+2, sort_ip);
}
/****************************************************************************