Kernel Mods for Sweex LB000021 and EdiMax 6104

The named routers are widely sold at a low price. They run on Linux, and source code of most of it is available. I simply asked Sweex for the source code and they were so nice to send me a CD-ROM over the mail.
| posted on Wed, 02 Nov 2005, 15:34 | weblog | rss | spin-off | comments |

The source code includes a load of scripts that jointly build a vmlinuz kernel with built-in initrd. This can be uploaded to the firmware, which presents an upload boot option on the console interface. In addition, the build scripts build a firmware in the format to be uploaded over the web interface of the router.

Getting a true promiscuous mode

Normally, an ethernet interface in promiscuous mode displays loads of information. I wanted to use the device as a bridge, so this was really important for me. But this didn't work.

The story is that WAN and LAN and CPU all take part in one switch with 6 ports. This switch learns MAC addresses (and the ports on which they reside) from incoming traffic. Inasfar as a VLAN segment has been defined that incorporates the source and destination port of a frame, the switch can pass on the information.

Of course there is no VLAN defined to connect WAN and LAN. And I wanted to do filtering stuff in my bridge, so I didn't want that level of automation either. But the switch would drop traffic arriving on LAN and destined for WAN, and vice versa.

As it turns out, there is a bit that can be set to instruct the switch to relay such frames to the CPU. So when there is no VLAN that covers source and destination ports, the traffic gets relayed to the CPU instead of dropped on the floor.

In drivers/net/am5120sw/swdrv.c I changed

//      if (rxmode == IF_PROMISC_MODE)
        ADM5120_SW_REG(CPUp_conf_REG) &= ~((port & 0x3f) << 9);
//      else
//              ADM5120_SW_REG(CPUp_conf_REG) |= (port & 0x3f) << 9;

into

#ifdef CONFIG_BRIDGE
// Code by Rick van Rein, OpenFortress, http://openfortress.nl/
if (rxmode & IF_PROMISC_MODE) {
        ADM5120_SW_REG(CPUp_conf_REG) &= ~((port & 0x3f) << 9);
        ADM5120_SW_REG(CPUp_conf_REG) |= 0x04;  /* enter bridge mode */
} else {
        ADM5120_SW_REG(CPUp_conf_REG) &= ~0x04; /* leave bridge mode */
        ADM5120_SW_REG(CPUp_conf_REG) |= (port & 0x3f) << 9;
}
#else
        // Original code found in this driver
//      if (rxmode == IF_PROMISC_MODE)
                ADM5120_SW_REG(CPUp_conf_REG) &= ~((port & 0x3f) << 9);
//      else
//              ADM5120_SW_REG(CPUp_conf_REG) |= (port & 0x3f) << 9;
#endif

Problem solved :-D

Squeezing out entropy

As explained elsewhere, I value proper random generators, and the lack of support for /dev/random was not pleasant -- imagine running ssh on a system without a shred of entropy -- that would be devastating for the security! Lacking secure challenges, replay attacks and even outright guesswork becomes a practical way of breaking in.

The best source of entropy on a router is of course the interrupt from the switch, indication the completion of either reception or transmission of a frame. The kernel has standard facilities to squeeze entropy out of interrupt timing, but it must be switched on because not all interrupts are good sources of entropy. When an interrupt handler routine is installed, this can be set with a simple flag.

So, I edited drivers/net/am5120sw/if5120.c and replaced

request_irq(SW_IRQ,
        swdrv_ProcessInt,
        SA_SHIRQ,
        dev->name, dev);

with:

request_irq(SW_IRQ,
        swdrv_ProcessInt,
        SA_SHIRQ | SA_SAMPLE_RANDOM,
        dev->name, dev);

You may be interested in this forum discussion on this topic.

Enabling bridged firewalling

Normally, the iptables command will not recognise frames that are being bridged. So, to implement a bridged firewall with this device, I had to make one additional tweak. I downloaded the nf-bridging patch for the Linux kernel from the ebtables website and installed it on my kernel. This took some trivial messing around with .rej files because the provided kernel is not supported directly by ebtables.

Uploader script

To upload new kernels with new root file systems to the device, you cannot use minicom -- I don't know why, but it gets stuck doing its X-protocol thing. The lrzsz package did work well though. This was a relief, as most reports of success were about using HyperTerminal under Windows. And I didn't think an upload under Windows was a good follow-up for a building process under Linux.

I added a chat script and a few handy modifications to update the router as straightforwardly as possible. Edit the scripts to point to the proper locations in your working environment. After you run the sweexreboot.sh command it will try to send a reboot command to the router; if that fails you will have to reboot the router manually by unplugging it. You are given a minute to do that. After the upload (which takes about 3 minutes) your uploaded kernel will boot and you can start testing your firmware from the console!

The reboot script is:

#!/bin/bash
stty -F /dev/ttyS0 speed 115200 -ignbrk brkint
CHATSCRIPT=`dirname $0`/sweexreboot.chat
echo Syncing with router...
echo >/dev/ttyS0
echo >/dev/ttyS0 reboot
chat -s -f $CHATSCRIPT </dev/ttyS0 >/dev/ttyS0
if [ $? -ne 0 ]
then    echo 'Failed to synchronise with a router (did you reboot it?)'
        exit
fi
echo Sending to router...
lsz -Xb -vvvv EdiLinux/linux-2.4.18-adm/vmlinuz </dev/ttyS0 >/dev/ttyS0
if [ $? -ne 0 ]
then    echo 'Error while uploading...'
        exit
fi
echo 'Done uploading; now starting minicom...'
minicom -m

This uses the following chat script:

ECHO ON
ABORT "LINUX started"
TIMEOUT 60
# SAY "Please RESET your router now?\n"
"ADM5120 Boot" "   "
# SAY "Thank you for resetting your router\n"
# "Linux Loader Menu" ""
TIMEOUT 5
# SAY "Boot menu recognised\n"
"Please enter your key" b
# SAY "Trying to upload image to RAM\n"
# "Downloading" ""
SAY "The router is now waiting for an upload\n"
Vertaal naar het Nederlands Vertaal naar het Nederlands

Comments on this article