diff options
-rw-r--r-- | source3/include/proto.h | 1 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 44 | ||||
-rw-r--r-- | source3/nmbd/nmbd_incomingrequests.c | 3 | ||||
-rw-r--r-- | source3/nmbd/nmbd_winsserver.c | 42 |
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. */ |