summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h1
-rw-r--r--source3/libsmb/nmblib.c44
-rw-r--r--source3/nmbd/nmbd_incomingrequests.c3
-rw-r--r--source3/nmbd/nmbd_winsserver.c42
4 files changed, 54 insertions, 36 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0312d25f86a..56e7d7f88f0 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -458,6 +458,7 @@ void make_nmb_name( struct nmb_name *n, char *name, int type, char *this_scope )
BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2);
BOOL send_packet(struct packet_struct *p);
struct packet_struct *receive_packet(int fd,enum packet_type type,int t);
+void sort_query_replies(char *data, int n, struct in_addr ip);
/*The following definitions come from libsmb/nterr.c */
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index 81a9505d6b2..77293806152 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -908,3 +908,47 @@ struct packet_struct *receive_packet(int fd,enum packet_type type,int t)
}
+/****************************************************************************
+return the number of bits that match between two 4 character buffers
+ ***************************************************************************/
+static int matching_bits(uchar *p1, uchar *p2)
+{
+ int i, j, ret = 0;
+ for (i=0; i<4; i++) {
+ if (p1[i] != p2[i]) break;
+ ret += 8;
+ }
+
+ if (i==4) return ret;
+
+ for (j=0; j<8; j++) {
+ if ((p1[i] & (1<<(7-j))) != (p2[i] & (1<<(7-j)))) break;
+ ret++;
+ }
+
+ return ret;
+}
+
+
+static uchar sort_ip[4];
+
+/****************************************************************************
+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);
+}
+
+/****************************************************************************
+sort a set of 6 byte name query response records so that the IPs that
+have the most leading bits in common with the specified address come first
+ ***************************************************************************/
+void sort_query_replies(char *data, int n, struct in_addr ip)
+{
+ if (n <= 1) return;
+
+ putip(sort_ip, (char *)&ip);
+
+ qsort(data, n, 6, name_query_comp);
+}
diff --git a/source3/nmbd/nmbd_incomingrequests.c b/source3/nmbd/nmbd_incomingrequests.c
index c2b8be212f0..97d223b2912 100644
--- a/source3/nmbd/nmbd_incomingrequests.c
+++ b/source3/nmbd/nmbd_incomingrequests.c
@@ -555,6 +555,9 @@ on the same subnet (%s) as the requestor. Not replying.\n",
set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
}
+
+ sort_query_replies(prdata, i, p->ip);
+
reply_data_len = namerec->data.num_ips * 6;
success = True;
}
diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c
index e7c6d69cd6c..d891124d064 100644
--- a/source3/nmbd/nmbd_winsserver.c
+++ b/source3/nmbd/nmbd_winsserver.c
@@ -1261,15 +1261,12 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p,
char *prdata = rdata;
int reply_data_len = 0;
int ttl = 0;
- int i = 0;
- int j;
+ int i;
bzero(rdata,6);
if(rcode == 0)
{
- int same_net_index = -1;
-
ttl = (namerec->data.death_time != PERMANENT_TTL) ?
namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
@@ -1286,44 +1283,17 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p,
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->data.num_ips; j++)
- {
- if(same_net( namerec->data.ip[j], p->ip, *n_mask))
- {
- set_nb_flags(&prdata[0],namerec->data.nb_flags);
- putip((char *)&prdata[2], &namerec->data.ip[j]);
- same_net_index = j;
- i = 1;
- }
- }
- }
}
- for(j = 0; j < namerec->data.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->data.nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->data.ip[j]);
- i++;
+ putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
}
- reply_data_len = namerec->data.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. */