changed the way that name query records are sorted in replies. They
authorAndrew Tridgell <tridge@samba.org>
Sun, 30 Aug 1998 08:45:23 +0000 (08:45 +0000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 30 Aug 1998 08:45:23 +0000 (08:45 +0000)
are now sorted by the number of common leading bits in the IP address
with the address of the querying host.
(This used to be commit 4460a1bc6aa7666d1c71d32ba73855d6ed32320a)

source3/include/proto.h
source3/libsmb/nmblib.c
source3/nmbd/nmbd_incomingrequests.c
source3/nmbd/nmbd_winsserver.c

index 0312d25f86aeb0e7a8b947af5cfa62b5867c197b..56e7d7f88f0fd57b140bdf1e8db4c0f354bb2455 100644 (file)
@@ -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  */
 
index 81a9505d6b2c56795fc1008fc555e50af12a52bc..772938061528a375bfd881ee5d2e4a91525eafbd 100644 (file)
@@ -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);
+}
index c2b8be212f0987020d6d22536e5ce2ceac19dd08..97d223b29123231266e4706e8d8615da4d99fb15 100644 (file)
@@ -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;
     }
index e7c6d69cd6cb10a11b9b56350c5a68cb0fd789a8..d891124d06454ae4a402439288b395f038a34ddd 100644 (file)
@@ -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. */