summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}
/****************************************************************************