summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>1998-08-30 08:45:23 +0000
committerAndrew Tridgell <tridge@samba.org>1998-08-30 08:45:23 +0000
commit4460a1bc6aa7666d1c71d32ba73855d6ed32320a (patch)
treea7fb324a67d2bf3f36866fdcd0097d46847f1763 /source
parentf555a76df696a0625acc16fa365dc048e0c2447d (diff)
downloadsamba-4460a1bc6aa7666d1c71d32ba73855d6ed32320a.tar.gz
changed the way that name query records are sorted in replies. They
are now sorted by the number of common leading bits in the IP address with the address of the querying host.
Diffstat (limited to 'source')
-rw-r--r--source/include/proto.h1
-rw-r--r--source/libsmb/nmblib.c44
-rw-r--r--source/nmbd/nmbd_incomingrequests.c3
-rw-r--r--source/nmbd/nmbd_winsserver.c42
4 files changed, 54 insertions, 36 deletions
diff --git a/source/include/proto.h b/source/include/proto.h
index 0312d25f86a..56e7d7f88f0 100644
--- a/source/include/proto.h
+++ b/source/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/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index 81a9505d6b2..77293806152 100644
--- a/source/libsmb/nmblib.c
+++ b/source/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/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
index c2b8be212f0..97d223b2912 100644
--- a/source/nmbd/nmbd_incomingrequests.c
+++ b/source/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/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
index e7c6d69cd6c..d891124d064 100644
--- a/source/nmbd/nmbd_winsserver.c
+++ b/source/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. */