PDA

Bekijk de volledige versie : NAT broken in (at least) 1.9.2.7 & 1.9.5.0 - FIXED!



techno
06-09-2005, 13:25
Playing around with my WL500g.Deluxe i found out, that the NAT support is somehow broken.

NAT only works for /24 networks, regardless which netmask is configured for the LAN interface. The reason is a bug in src/router/rc/firewall_ex.c in the function ip2class. This function is invoked to calculate the numeric network class for the iptables configuration stored in /tmp/nat_rules.

This is the original ASUS code:


ip2class(char *lan_ip, char *netmask, char *buf)
{
unsigned int val, ip;
struct in_addr in;
int i=0;

// only handle class A,B,C
val = (unsigned int)inet_addr(netmask);
ip = (unsigned int)inet_addr(lan_ip);
in.s_addr = ip & val;
if (val==0xff00000) sprintf(buf, "%s/8", inet_ntoa(in));
else if (val==0xffff0000) sprintf(buf, "%s/16", inet_ntoa(in));
else sprintf(buf, "%s/24", inet_ntoa(in));
dprintf(buf);
}

It seems that this function supports only Class A,B and C (/8, /16 and /24) networks. But wait! The function inet_addr (from arpa/inet.h) returns the ip address in network byte order, so e.g. 255.255.255.0 will become 0x00ffffff (and not 0xffffff00). This means that the function ip2class above actually always returns "/24" because the else statement always matches.

I found this bug in the 1.9.2.7 source (I'm using oleg's 1.9.2.7-6b), but I just checked 1.9.5.0 from ASUS - the bug is still there. ASUS told me, to post into this forum rather than directly contacting the developers.

However, here is a fix. It also works with all possible netmasks:


ip2class(char *lan_ip, char *netmask, char *buf)
{
unsigned int val, ip;
struct in_addr in;
int i=0;

// should handle all classes now
val = (unsigned int)inet_addr(netmask);
ip = (unsigned int)inet_addr(lan_ip);
in.s_addr = ip & val;
val = ((val & 0xff000000) >> 24) + ((val & 0x00ff0000) >> 8) + ((val & 0x0000ff00) << 8) + (val & 0x000000ff) << 24);
while (val!=0)
{
val = val << 1;
i++;
}
sprintf(buf, "%s/%d", inet_ntoa(in), i);
dprintf(buf);
}


oleg: can you patch this into your next release, please?

Oleg
06-09-2005, 14:42
hm... yes, sure.

Oleg
20-09-2005, 19:36
Applied like this:


val = (unsigned int)inet_addr(netmask);

ip = (unsigned int)inet_addr(lan_ip);

in.s_addr = ip & val;


for (val = ntohl(val); val; i++)
val <<= 1;

sprintf(buf, "%s/%d", inet_ntoa(in), i);

techno
21-09-2005, 22:03
Yes... ntohl() is the function I was looking for (and the function the ASUS developers forgot) ;-)

zerocrash
18-10-2005, 15:06
Hi - where to get this fix?

Oleg
18-10-2005, 15:28
1.9.2.7-6c-pre5

zerocrash
18-10-2005, 19:36
1.9.2.7-6c-pre5

Thanks... :D