[Dnsmasq-discuss] [PATCH 1/2] Fix endianness bug in local-service option

Richard Genoud richard.genoud at gmail.com
Wed Sep 17 14:05:51 BST 2014


The masks used to check if an address is from a local network was not
using the htonl() function, so when they where used in is_same_net(),
the address (network order) was compared to the mask (host order).
That failed for little endian machines.

Moreover, left shifting int values is a undefined behaviour in C.
So we cast explicitly in in_addr_t (uint32_t) the value to be shifted.

Signed-off-by: Richard Genoud <richard.genoud at gmail.com>
---
 Hi,
 I ran into this bug while I was testing the local-service option
 on a arm little-endian machine. It was acting weirdly, refusing to answer
 to queries that where in the same network, but sometimes did.
 (ex: 192.168.7.1 was served because it matched 127.0.0.1/8 with a mask in
 the wrong order : 0.0.0.255 (so 0.0.0.1 matched...))

 Please consider applying it.
 (applies on top of 00c0f69aa5ad Debian bug closure.)

 Regards,
 Richard.
 src/forward.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/forward.c b/src/forward.c
index 3afd1b197d39..4895efeba89a 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -1118,7 +1118,7 @@ void receive_query(struct listener *listen, time_t now)
 	  struct in_addr netmask;
 	  for (addr = daemon->interface_addrs; addr; addr = addr->next)
 	    {
-	      netmask.s_addr = 0xffffffff << (32 - addr->prefixlen);
+	      netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
 	      if (!(addr->flags & ADDRLIST_IPV6) &&
 		  is_same_net(addr->addr.addr.addr4, source_addr.in.sin_addr, netmask))
 		break;
@@ -1652,7 +1652,7 @@ unsigned char *tcp_request(int confd, time_t now,
 	  struct in_addr netmask;
 	  for (addr = daemon->interface_addrs; addr; addr = addr->next)
 	    {
-	      netmask.s_addr = 0xffffffff << (32 - addr->prefixlen);
+	      netmask.s_addr = htonl(~(in_addr_t)0 << (32 - addr->prefixlen));
 	      if (!(addr->flags & ADDRLIST_IPV6) && 
 		  is_same_net(addr->addr.addr.addr4, peer_addr.in.sin_addr, netmask))
 		break;
-- 
2.0.0




More information about the Dnsmasq-discuss mailing list