Why xor() does not work on openwrt

0

We are porting openwrt to our device which is a mips platform. But we found the service "dnsmasq" can't be started correctly on our device.

Then we found the root cause, "/etc/init.d/dnsmasq" used the script "/bin/ipcalc.sh" generating the wrong configuration for "dnsmasq" and "dnsmasq" failed to parse the configuration.

Here is the link to the original code of "/bin/ipcalc.sh" in github https://github.com/respeaker/openwrt/blob/master/package/base-files/files/bin/ipcalc.sh

Then we replace all the invoke of compl32() with compl(), then it works. As we investigate the script, and find compl32() is a very simple function, which just invoke xor(). But looks like xor() can't produce what we were expecting.

Here is the code of /bin/ipcalc.sh that we are using, and I add some debug in it:

#!/bin/sh

awk -f - $* <<EOF
function bitcount(c) {
    c=and(rshift(c, 1),0x55555555)+and(c,0x55555555)
    c=and(rshift(c, 2),0x33333333)+and(c,0x33333333)
    c=and(rshift(c, 4),0x0f0f0f0f)+and(c,0x0f0f0f0f)
    c=and(rshift(c, 8),0x00ff00ff)+and(c,0x00ff00ff)
    c=and(rshift(c,16),0x0000ffff)+and(c,0x0000ffff)
    return c
}

function ip2int(ip) {
    for (ret=0,n=split(ip,a,"\."),x=1;x<=n;x++)    ret=or(lshift(ret,8),a[x])
    return ret
}

function int2ip(ip,ret,x) {
    ret=and(ip,255)
    ip=rshift(ip,8)
    for(;x<3;ret=and(ip,255)"."ret,ip=rshift(ip,8),x++);
    return ret
}

function compl32(v) {
    ret=xor(v, 0xffffffff)
    return ret
}

BEGIN {
    print "var1="compl32(255)
    print "var2="compl(0xff)
    print "var3="xor(0xff,0xffffffff)
    print "var4="xor(255,0xffffffff)
    slpos=index(ARGV[1],"/")
    if (slpos == 0) {
            ipaddr=ip2int(ARGV[1])
            dotpos=index(ARGV[2],".")
            if (dotpos == 0)
                    netmask=compl(2**(32-int(ARGV[2]))-1)
            else
                    netmask=ip2int(ARGV[2])
    } else {
            ipaddr=ip2int(substr(ARGV[1],0,slpos-1))
            netmask=compl(2**(32-int(substr(ARGV[1],slpos+1)))-1)
            ARGV[4]=ARGV[3]
            ARGV[3]=ARGV[2]
    }

    network=and(ipaddr,netmask)
    broadcast=or(network,compl(netmask))

    start=or(network,and(ip2int(ARGV[3]),compl(netmask)))
    limit=network+1
    if (start<limit) start=limit

    end=start+ARGV[4]
    limit=or(network,compl(netmask))-1
    if (end>limit) end=limit

    print "IP="int2ip(ipaddr)
    print "NETMASK="int2ip(netmask)
    print "BROADCAST="int2ip(broadcast)
    print "NETWORK="int2ip(network)
    print "PREFIX="32-bitcount(compl(netmask))

    # range calculations:
    # ipcalc <ip> <netmask> <start> <num>

    if (ARGC > 3) {
            print "START="int2ip(start)
            print "END="int2ip(end)
    }
}
EOF

Here is the running result:

root@OpenWrt:/tmp# ipcalc.sh 192.168.1.1/24 100 50
var1=255
var2=4294967295
var3=0
var4=255
IP=192.168.1.1
NETMASK=255.255.255.0
BROADCAST=192.168.1.255
NETWORK=192.168.1.0
PREFIX=32
START=192.168.1.100
END=192.168.1.150
root@OpenWrt:/tmp#

This is very strange. Why xor() does not work?

awk
xor
openwrt
dnsmasq
asked on Stack Overflow Jun 14, 2017 by Art • edited Jun 14, 2017 by melpomene

2 Answers

0

Your expression in BEGIN for var3 produces var3=4294967040 on my system (GNU Awk 4.1.4). Looks like you are using an broken Awk- please try a different version.

answered on Stack Overflow Jun 22, 2017 by Justin Wozniak
0

$ man awk

STANDARDS The awk utility is compliant with the IEEE Std 1003.1-2008 (''POSIX.1'') specification, except awk does not support {n,m} pattern matching.

The flags [-dV] and [-safe], as well as the commands fflush,compl, and,or, xor, lshift, rshift, are extensions to that specification

In my experience some implementations like in FreeBSD do not fully implement those extensions.

answered on Stack Overflow Feb 17, 2018 by user9374540

User contributions licensed under CC BY-SA 3.0