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:
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.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); }
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:
oleg: can you patch this into your next release, please?Code: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); }




Reply With Quote