Hacking the WNDR3700

The WNDR3700 is a nice piece of hardware. It has a four-port gigabit switch, dual-band radio interfaces, and can do the new draft-standard 802.11n.

It has a MIPS (Atheros ar7100) processor running at 680MHz, 64G RAM and 8G flash.

While pricey, it doesn't cost the earth — around $200 from eBay

So what's the problem?

My network uses ipv6, and there's no facility for running gateway or router-advertising daemons. Moreover, the firmware uses squashfs which is read-only, so I can't just build and install additional packages.

Also, although the router comes with a USB port for sharing file storage, it does not do NFS.

The GUI doesn't allow access to everything that the firmware can do: in particular you can't forward from one port on the outside to another on the inside.

No ip6tables.

No sshd, and telnetd has to be enabled on the local network with a magic packet. This means no remote admin.

Where next?

I decided to try to modify the open-source firmware provided by Netgear, to add g26c, radvd, ip6tables, and an nfs server (and portmap, etc).

First step was to build the firmware as-is, and install it. This required some modifications to the source; and when it was installed I had no GUI any longer. Also it's really unclear without the GUI how to flash a new image (the uhttpd server has built-in cgi code to do it; and although I know you end up writing the image to /dev/mtd/2, just doing that ended up with a broken router that I had to go to recovery mode to fix.).

So then I extracted the missing packages from a Netgear binary firmware, and created package files for them. This built, and I could install it, and worked apparently identically to the binary firmware. Hurrah!

Next step was to reconfigure with dropbear, NFS server, gw6c and radvd, and rebuild. One difficulty is that tcpwrapper.c in the NFS utils needs a more recent sys/queue.h than the one in the image, but that's easily fixed.

On booting this image, I could see dropbear, etc., trying to run but they didn't succeed. The problem is that / is not writable, so there was no way to create the keys in /etc/dropbear. I created a link and reflashed; then things work. However, that doesn't fix the other things in /etc/config, nor the gw6c config file.

The way to fix things more properly is to overlay a writable filesystem on the read-only squashfs. OpenWRT usually uses mini_fo. The patches to enable mini_fo are in target/linux/generic-2.6/patches/209-mini_fo.patch — symlink that into target/linux/wndr3700u-2.6/patches and rebuild (again). There's about a gigabyte free at the end of the squashFS root partition; that's enough for the variable data.

The partition structure of the flash is soft: uBoot assumes a squashFS at 448M, and will always flash a full 0x720000 bytes; Linux has a hard-coded command line that looks like this:

 mtdparts=ar7100-nor0:320k(uboot),128k(env),7296k(rootfs),64k(config),64k(config_bak),64k(pot),64k(traffic_meter),128k(language),64k(caldata),7471040@458816(mount_fs)
    

If we pad the squashfs to a 16k boundary (to move to an erase boundary of the flash) we can fit in a gig like this:

 mtdparts=ar7100-nor0:320k(uboot),128k(env),7296k(rootfs),64k(config),64k(config_bak),64k(pot),64k(traffic_meter),128k(language),64k(caldata),6271k@458816(mount_fs),1024k@6720k(root_rw)
    

Then we just have to put some code into the initramfs to mount the read-write partition over the read-only partition, and then pivot-root to the union filesystem.

Tried this, and bricked the router. Time to get a serial port? Or no!! According to the U-Boot code, there's a way to unbrick the router: see NMRP.

Hooked up a serial port, and managed to reflash a better image. There are some issues though — result worked fine from an initramfs, but when I flashed the image, the router locked up totally — no power light, no nothing. Time get out the JTAG stuff.

JP3 on the board is a JTAG header. It's a set of 14 flat pads, so I need to find or work out a way to connect to them.

Step by Step.

  1. Get the firmware image from Netgear's site, from here or if that link's broken, search the Netgear site.
  2. Get the bits missing from the firmware image from the firmware on your device. If you have a copy of unsquashfs-lzma you can use that on the image from Netgear (there's a 192 byte offset at the start); or the simple way is to plug a USB key into the router, telnet to it, and copy the files listed in /usr/lib/ipkg/info/net-web.list and /usr/lib/ipkg/info/artmtd.info onto the key. This is slightly complicated by the lack of a working CPIO, and using busybox tar. I ended up copying the whole root filesystem using
              tar -X ./proc/ -X ./sys/ -X ./tmp/mnt/sda1/ -cf /mnt/sda1/root.tar .
            
    and then extracting that archive on my desktop.
  3. I found four issues with the firmware source as supplied by Netgear.
    1. Embedded in a couple of places were references to an internal mirror for various sources. Get rid of them by
      1. In configs/defconfig-wndr3700u (change the line CONFIG_LOCAL_MIRROR to be "")
      2. In toolchain/uClibc/patches/160-* (just delete this file
    2. The cross-compiler will not build with recent autoconf. You must use autoconf2.59. Edit toolchain/gcc/Makefile and replace the occurrence of ‘autconf’ in line 121 with ‘autoconf2.59’
    3. I like to use ccache to speed recompilation after configuration and other changes. The libjpeg libtool variant doesn't like this. 001-allow-ccache.patch can be put into WNDR3700-V1.0.4.35-GPL-src/package/libjpeg/patches to fix the problem.
      The patch's contents are:
      --- jpeg-6b/makefile.cfg_orig	2009-11-09 11:30:08.228630079 +1100
      +++ jpeg-6b/makefile.cfg	2009-11-09 11:30:26.116630029 +1100
      @@ -169,7 +169,7 @@
       
       # with libtool:
       libjpeg.la: @A2K_DEPS@ $(LIBOBJECTS)
      -	$(LIBTOOL) --mode=link $(CC) -o libjpeg.la $(LIBOBJECTS) \
      +	$(LIBTOOL) --mode=link "$(CC)" -o libjpeg.la $(LIBOBJECTS) \
       		-rpath $(libdir) -version-info $(JPEG_LIB_VERSION)
       
       # sample programs:
      
    4. The firmware is incomplete. Two packages (net-web and artmtd) installed on the router had neither source code nor binary package available, I fixed this by repackaging the contents of those packages from the router firmware.

    Getting in with Telnet

    Get telnetenable.py from http://code.google.com/p/netgear-telnetenable/, then I use this script which finds the mac address, does the appropriate magic, and lets you in.

    More later


    Last modified: Fri Feb 5 14:33:07 EST 2010