nsupdate Bad for Embedded Applications

I thought I'd port the nsupdate utility to the WRT54G environment and use that to manage the DNS updates. Once the router boots and discovers what address has been assigned to it, it can issue a DNS update notice containing the assigned address. That seemed like a good idea at the time. Turns out, it wasn't.

I was surprised at how easily the BIND suite ported to the WRT54G environment. That seemed like a good omen. There were only two small glitches on the way. The first was figuring out the (non-trivial) command to configure the package. Here is what I used:

export CC="$TOOLCHAIN_ROOT/bin/mipsel-linux-uclibc-gcc"
export AR="$TOOLCHAIN_ROOT/bin/mipsel-linux-uclibc-ar"
export RANLIB="$TOOLCHAIN_ROOT/bin/mipsel-linux-uclibc-ranlib"
export LDFLAGS="-s"

sh configure \
        --host=mipsel-unknown-linux \
        --with-openssl=$TOOLCHAIN_ROOT/usr \
        --with-randomdev=/dev/random \
        --disable-largefile \

The second glitch happend during the build. The lib/dns/Makefile file tries to build gen to run in the target environment, but it needs to run on the build host. I needed a one-line fix to work around that. (I can send a patch if you need it.)

Other than those two glitches, the build ran fine. When the build completed, however, I saw the first major problem. The size of the binary was out of control.

$ size nsupdate
   text    data     bss     dec     hex filename
1491167   10236    2284 1503687  16f1c7 nsupdate

That's a humongous 1.4MB just for a utility to send a "my address is" message to the nameserver. For comparison, the busybox utility, which provides the complete Linux command environment, is only 0.5MB. The router only has about 4MB of flash memory. This is completely unacceptable for a small, embedded system.

There are tricks you can play to reduce executable size. You can link with shared libraries rather than building static libraries into the executable. You can strip out the symbol table, which is useful mainly in a debug environment. All of those things had been done already. This bloated turdball was as small as it was going to get.

Still, after having done all the work, I thought I'd give it a shot. I loaded nsupdate onto the router, tested it, and it worked great.

I was ready to shrug off my concern about file size when I encountered another problem. Although nsupdate was alright on the running system, it failed during router initialization. It turns out that nsupdate requires a good clock in the running system. While computers have good clocks, embedded devices often don't. When you power up the WRT54G, it has no idea the date or time. Once the router is running, you can set the time from time source. This caused nsupdate to fail during router initialization, even though it worked later, once the router was running and the clock was set.

That was the last staw. I gave up on the idea of using nsupdate, feeling somewhat bemused at how distressingly overengineered the whole DNS update function appeared to be.

The solution I deployed was to stand up a small application on my web server. Now, when the router boots it sends a little, "Hi, it's me!" message to the web server. Then, on the web server, with hundreds of megabytes of memory and a clock syncronized with sub-second accuracy, I can run the bloated nsupdate utility to set the gateway address.

This solution is working great. I can easily access my network remotely.


Comments have been closed for this entry.

re: nsupdate Bad for Embedded Applications

Dear sir,

I have some problems about porting the nsupdate utility. I followed the steps you mentioned in article, but when I build libdns.a(lib/dns/) it show the following error message:

./gen -s . -t > include/dns/enumtype.h
/bin/sh: ./gen: cannot execute binary file
make: *** [include/dns/enumtype.h] Error 126

How can I solve this problem ? Thanks a lot.

Best Regards.