Maarten Pennings'
Playing with the big boys: hacking my NSLU2

Table of contents

1. The NSLU2     1.1. Being introduced to the NSLU2     1.2. Meeting the NSLU2     1.3. Finding a HD for my NSLU2 2. Sharing my NSLU2     2.1. Creating users     2.2. Directories and shares     2.3. Groups and shares 3. Compiling an application for the NSLU2     3.1. Getting access into my NSLU2 (coward version)     3.2. Poking around in my NSLU2     3.3. Getting Knoppix as a host system     3.4. Getting a cross compile to work (first try)     3.5. Getting access into my NSLU2 (big boy version)     3.6. Getting a cross compile to work (second try) 4. Going to Unslung     4.1. Flashing Unslung     4.2. Unslinging     4.3. Installing packages 5. Ssh     5.1. What is ssh?     5.2. Password authentication     5.3. Key-based authentication     5.4. Host based authentication     5.5. Tunneling 6. Some work to do, some open issues

1. The NSLU2

1.1. Being introduced to the NSLU2

Once every year the company I work for organizes The Software Conference. I nickname it The Software Reunion: the conference program has coffee breaks of 45 minutes and lunches of 2 hours where you meet collegues that are now doing different projects. I met Jan during lunch. He told me he was working on stand-alone media players that need a UPnP media server. That he bought a NAS that was hacked. And that TwonkyVision had ported its UPnP server to that hacked firmware.

Hold! Stop! Jan was going way too fast for me. What the hell is a NAS? I learned that NAS stood for network attached storage. Jan had bought the Linksys (a division of Cisco) NSLU2. I had him write that down for me once he explained the details. It is a small box with three plugs: one for power, one for my home network, and one for a USB hard disk (actually there is a second USB plug). And then you have a file server. Gone are the problems that the file I need is on the PC in my study when I use my laptop, or on my laptop when I use the PC in the living room. And the NSLU2 eats little power, and, it was hacked. Jan told me you could add a web server, an NFS server or, what he did, a UPnP server (to serve media files to e.g. the Philips SLA5500, a small audio device that enables users to wirelessly stream MP3 and WMA music from their UPnP server to a hi-fi system). I was definitely interested.

1.2. Meeting the NSLU2

The NSLU2 has a somewhat strange shop shelf personality. Non of the computer shops I normally visit have it on stock. But, to my big surprise, the Joe Sixpack multimedia shop Dixons had it. But at 125, I decided to try my luck elsewhere on the web: had it for 66.99 (ex tax) and it had an outlet near my work. I picked it up the next day (april 25th 2005).


It's a cute little box. It is a tower model: 2.5cm wide, 13cm high and 10cm deep. When the box is (soft switch) off my Watt meter could not measure power consumption (of the addapter and NSLU in standby together); when the box is on (without a HD attached) it consumes 5W.

I didn't have a USB hard disk yet so I started with a USB flash drive plugged in. Booting is rather slow (half a minute), but you see progres on the four leds and there is even a beeper (one beep at the end of boot if booted ok). Of course I tried to fire up the NSLU without reading manuals or using the wizard for windows, but at first I failed. When even the wizard failed I had some thinking to do; the problem was that the NSLU has a web interface at IP address, but I have a home network with a 10.x.x.x subnet.

So, I removed the ethernet plug of a PC, manually configured its IP address to (instead of using DHCP), and connected the NSLU2 with a cross-cable. Contact! Although the NSLU2 recommends a fixed IP address, I selected DHCP (and pressed Save, though not the first time...). I reset the IP address of the PC to 'obtain via DHCP', replugged cables, rebooted the PC and the NSLU2, and I was flying.

1.3. Finding a HD for my NSLU2

With a USB flash drive, the NSLU2 has restricted featuring on users/shares etc. I wanted a fast, large file server anyhow so I had to shop for a disk. I found three options to chose from:

So, I bought the extra hardware. When I got everything working in my study, a spent a sunday mounting it next to the ADSL box in the utility closet (meterkast – thanks Frans for the translation). The HD eats about 10W, so together with the NSLU that is 15W. With the ADSL box that sums up to 23W. One year always-on would thus mean 200kWh or 35.

The NSLU2 next to a USB HD box; their stands skrewed to a tray mounted to the wall. On the lower left the addapters for the NSLU2 and the HD (and for the ADSL box).

2. Sharing my NSLU2

2.1. Creating users

After formatting the hard disk via the NSLU2 web interface (which formats it in EXT3, a Linux file system), I created two users maarten and debbie. For both users I created a private share (without disk quota).

On the NSLU2 web interface, under Administration, Users, the user maarten is created with a private share on disk 1.

I did some extra tailoring: I changed the NSLU2 server name (in the NSLU2 system page under Administration) to Nas. I also decided to make my Nas a first class network citizen. I visited the web interface of my ADSL box, found the MAC address of the NSLU2 in its DHCP table, and created a static address ( for the NSLU2 in the DHCP table. I also added 'Nas' in the DNS table of the ADSL box.

I can now type //Nas in (internet) explorer and get the Nas' web interface. Or I can type \\Nas in (internet) explorer and I get its shares. We'll have four shares by now, as illustrated in the screenshot below.

The shares of my Nas.

The maarten share is the private share of user maarten, likewise, the debbie share is the private share of user debbie. The disk 1 share is the public share e.g. for guest logins (with usercode "guest" and the empty password), or even failed logins (any usercode with any password), if that has been enabled. The admin 1 share is for administrators; its contents were a surprise to me. See below for details.

On the NSLU2 web interface, under Administration, System, guest logins and even failed guest logins can be enabled.

2.2. Directories and shares

I have not yet been able to access admin 1 with Windows XP. But when I logged on my Windows 98 PC with admin (and the same password as I used for the NAS), and then clicked on network neighborhood, I was suddenly able to open the admin 1 share.

The admin 1 share shows its directories.

The diagram below shows (in blue) the root directory of the hard disk connected to USB port 1 and its subdirectories (validated by the examinations documented in the chapters below). The diagram shows (in red) the names under which these directories are shared. Typically, user maarten would map network drive M: to //Nas/maarten, and he would find all his files in M:\. Note that if an administrator would map network drive N: to //Nas/admin 1, then N:\ would have three directories: debbie, maarten, and public.

/             shared as admin 1 accessible by admin
+- debbie/    shared as debbie  accessible by admin, debbie (and later on also maarten)
+- maarten/   shared as maarten accessible by admin, maarten
+- public/    shared as disk 1  accessible by all users

Note that the share disk 1 has a very confusing name, it would have been much clearer if it were called public 1. I read a similar comment at tom's networking. The web interface of the NSLU2 is even more confusing. When clicking DISK 1(Public Data) the web interface immediately shows the contents (files and directories) of the disk 1 share (or should I say the /public/ directory). That's still ok. But when clicking User Log in (Private Data) the confusion really starts. That is because the web interface does not directly show the contents (that is files and directories) for that user. It first opens a different windows (that looks deceptively the same) where the user must first select the share to browse.

The public login and the private login entry points.

In other words, when clicking User Log in (Private Data) a usercode and password is required. The web interface then shows all private shares that the logged in person is allowed to see. This means that usually one share is shown, the one with the same name as the user (for example user maarten sees one share maarten). The user has to click his share and only then the web interface shows the files of the user.

The NSLU2 web interface, when user maarten has logged in (left) and when user maarten has selected the share maarten (right).

When doing a User Log in (Private Data) for user admin the web interface shows all private shares (thus ADMIN 1, debbie, and maarten). When the administrator then selects the ADMIN 1 share the web interface will then show the contents of that share which is the root of the first disk, i.e. the directories of all users and the public directory.

The NSLU2 web interface, when user admin has logged in (left) and when user admin has selected the share ADMIN 1 (right).

Note that after clicking the share, the table header in the web interface changes from Type-Name-Comment (shares view) to Type-Name-Size-ModifiedDate (file/directory view). Also note that the left margin label changes from Status to Browse. Finally, observe that in the file/directory view, directories that happen to be shared have a little hand on the lower left corner, just like they have in windows.

2.3. Groups and shares

So, why is this indirection of first showing shares after login and then files used for plain users? Because a plain user could have access rights to more than one share! To check this, go to the Users tab of the Administration tab of the web interface. As explained above, one may (and I have) create a private directory per user – with the same name as the user. What also happens behind the scenes is that for each user a (access rights) group is created – with the same name as the user. By default each group (that is named after a user) contains one user, the user with the same name as the group (besides the groups that are named after a user, there are some standard groups like guest, administrators, everyone). By the way, access to a share is granted to groups (not users), but users are part of zero or more groups.

The NSLU2 web interface, listing all users on my NAS.
We're about to press the Groups button to change rights for user maarten
[in the Users subtab of the Administration tab].

The windows that pops up shows all groups registered on my Nas. The left column shows all groups of which user maarten is part and the right column shows the groups of which which maarten is not part. Let us move group debbie to the left (making maarten part of that group).

The NSLU2 web interface, just after adding group debbie also to the member-of list of user maarten.

If we now do a User Log in (Private Data) for user maarten we see two shares to chose from!

The NSLU2 web interface, when user maarten has logged in.
Since user maarten is now part of group debbie he can now also browse the private share of user debbie.

If I had designed the web interface of the NSLU2, I would probably have made a single login button (that pops up a login dialog, which maybe hints that 'guest' logins exist), that would pop up a window with the main text 'Please select which share to browse' and below that would be a list of all accesible shares including the public one.

Finally, some security considerations. As long as the NSLU2 is behind a firewall, and no ports are forwarded to it, it's relatively secure. Still, I changed the default admin password for the admin user. Although I do not understand yet what 'UPnP support' means, I followed the advise to disable it. Some also claim to change the port of of the web interface from its default 80, but I decided to stick to not forwarding port 80 from my firewall to my NSLU2 (anyhow changing the port number is not very protective against port scanners).

It is a bit strange that without any password, one has access to the web interface, and with that to the Public Data. But it is possible to disable Guest logins, and some claim a password can be set for user guest. Of course, one can also leave the public share empty.

3. Compiling an application for the NSLU2

3.1. Getting access into my NSLU2 (coward version)

When searching the web for NSLU2 one soon stumbles on the intriging articles of Jim Buzbee on tom's networking "How to: Hacking the Linksys NSLU2" (Part 1, Part 2 – Adding NFS, Part 3 – iTunes Server, Part 4 – Customizing the Flash, Part 5 – Moving to Unslung, and Part 6 – Installing a Media Server). I wanted to do all of that too! I realized that my Unix experience dates back to 1990. Would I be able to play with the big boys? Would I be able to at least replicate Jims steps? It turned out to be feasible, though, being infected by Windows, with some slowdowns now and then.

Let start slowly. Jim talks about a telnet backdoor that must first be enabled through a webscript. So I typed http://Nas/Management (recall that I entered Nas as a DNS entry for my NSLU2 on and I found Jims telnet.cgi file. It seems that Linksys removed directory listing ability from the R25 firmware and telnet from R29 but fortunately I'm on V2.3R24 as my linksys home page tells me (I'm still planning to download R24 and R29 sources from Linksys gpl code site and run a diff)

Submitting a URL that requests a directory makes the NSLU web server return a listing of the directory contents. We find Jims telnet.cgi exploit.

Execution of the webscript returns a page that shows the current status of the telnet function and a button to toggle it. After pushing the button, a second http://Nas/Management confirms that telnet is enabled now. It should be noted that the telnet enabled setting does not survive a reboot of the NSLU2. So, if you're like me and power off the NSLU2 now and then, you must re-enable telnet via this web script after a power on.

The telnet.cgi backdoor show the status of the telnet function and a button to toggle the status.

As Jim found out, a newly created user has no login shell associated with it. Only root and ourtelnetrescueuser have that. Jim then mounted his USB disk on an other system and changed the password file. That is a big step for a PC boy like me at this moment, and fortunately, it is not necesary right now. On Trevor Man's Website you'll find a password generator for ourtelnetrescueuser (the NSLU2 generates the password at boot up based on the default hostname of the NSLU2, which is printed at the bottom of the NSLU2 – thank God, because I already changed it).

Nas login: ourtelnetrescueuser
Password: password from Trevor's site
No directory, logging in with HOME=/

BusyBox v0.60.4 (2004.07.01-03:05+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.


3.2. Poking around in my NSLU2

How do you explore a Linux system? From Jims articles, I learned the trick of catting the files in /proc. I tried all of them. Some of them reported results that somehow made some sense. They're listed below.

$ cd /proc
$ cat cpuinfo
Processor       : XScale-IXP425/IXC1100 rev 1 (v5b)
BogoMIPS        : 131.48
Features        : swp half thumb fastmult edsp

Hardware        : Intel IXDP425 Development Platform
Revision        : 0000
Serial          : 0000000000000000
$ cat version
Linux version 2.4.22-xfs (root@sure_linux) (gcc version 3.2.1) #377 Fri Jul 2 09
:02:32 CST 2004
$ cat cmdline
console=ttyS0,115200 root=/dev/ram0 initrd=0x01000000,10M mem=32M@0x00000000
$ cat mtd
dev:    size   erasesize  name
mtd0: 00040000 00020000 "RedBoot "
mtd1: 00020000 00020000 "System Configuration"
mtd2: 00100000 00020000 "Kernel"
mtd3: 006a0000 00020000 "Ramdisk"
$ cat partitions
major minor  #blocks  name

   8     0  195360984 sda
   8     1  195181686 sda1
   8     2     120487 sda2
   8     3      56227 sda3

This confirms that we're running Linux (2.4). The memory sizes (10M and 32M) coincide with what I found on the web: 10M flash and 32M RAM. The result of mtd coincides with the four parts of the flash image explained by Jim. Since my 200G hard disk is known to the NSLU2 as sda, the output of partitions also drew my attention. The NSLU2 has created three partitions in the hard disk! Running mount shows that two of them are actually mounted.

$ mount
rootfs on / type rootfs (rw)
/dev/ram0 on / type ext2 (rw)
/proc on /proc type proc (rw)
none on /var/lock/samba type ramfs (rw)
none on /var/log type ramfs (rw)
/dev/sda1 on /share/hdd/data type ext3 (rw)
/dev/sda2 on /share/hdd/conf type ext3 (rw,sync)
none on /tmp type ramfs (rw)

The sda2 partition is thus mounted as /share/hdd/conf. It contains configuration files (user lists with access rights). For example /etc/passwd is linked to /share/hdd/conf/passwd. The sda1 partition is mounted as /share/hdd/data. It seems to have a top level directory per user and one general directory public. The share maarten maps to directory /share/hdd/data/maarten, the share disk 1 to directory /share/hdd/data/public, and share admin 1 to /share/hdd/data (i.e. the root of partition sda1). I still don't know what's in sda3.

+- share/
   +- flash/
   |  +- conf/         mount point for sdb2 (2nd hard disk, 2nd partition)
   |  +- data/         mount point for sdb1 (2nd hard disk, 1st partition)
   +- hdd/
      +- conf/         mount point for sda2 (1st hard disk, 2nd partition)
      |  +- .dongle
      |  +- .htpasswd
      |  +- backup_sh.conf
      |  +- config/
      |  +- config.bin
      |  +- group
      |  +- group.ttt
      |  +- lost+found/
      |  +- passwd
      |  +- passwd.ttt
      |  +- server.log
      |  +- share/
      |  +-
      |  +-
      |  +- smb.conf
      |  +- smb.conf.ttt
      |  +- smbpasswd
      |  +- smbpasswd.ttt
      |  +- tmp/
      |  +- upgrade/
      |  +-
      |  +-
      +- data/         mount point for sda1 (1st hard disk, 1s partition)
         |             shared as admin 1 (not all entries exposed by SMB)
         +- debbie/    shared as debbie
         +- lost+found/
         +- maarten/   shared as maarten
         +- public/    shared as disk 1
         +- quota.user
         +- quota.user~

I explored the Linux file system using plain cd's and ls's (sometimes with the -R option). An interesting directory is /bin. It contains the available binaries. An ls -l shows that Linksys uses a trick to reduce memory footprint. They installed busybox, which implements many ordinary shell commands (like ls and mv) and one executable tinylogin that handles user authentication (like su and passwd). Most binaries are actually links into busybox or tinylogin (a common trick in Unix: more than one link to the same binary, which changes behavior depending on argv[0]).

-rwxr-xr-x    1 root     root        11648 Jul  2  2004 agetty
lrwxrwxrwx    1 root     root            7 Jul  2  2004 ash -> busybox
-rwxr-xr-x    1 root     root       197292 Jul  2  2004 busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 cat -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 chmod -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 chown -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 cp -> busybox
-rwxr-xr-x    1 root     root        12884 Jul  2  2004 date
lrwxrwxrwx    1 root     root            7 Jul  2  2004 dd -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 df -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 dmesg -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 echo -> busybox
-rwxr-xr-x    1 root     root        64780 Jul  2  2004 ftp
lrwxrwxrwx    1 root     root            7 Jul  2  2004 hostname -> busybox
-rwxr-xr-x    1 root     root         8148 Jul  2  2004 inetd
-rwxr-xr-x    1 root     root        15796 Jul  2  2004 init
lrwxrwxrwx    1 root     root            7 Jul  2  2004 kill -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 killall -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 ln -> busybox
lrwxrwxrwx    1 root     root            9 Jul  2  2004 login -> tinylogin
lrwxrwxrwx    1 root     root            7 Jul  2  2004 ls -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 mkdir -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 mknod -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 mount -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 mv -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 pidof -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 ping -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 ps -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 pwd -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 rm -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 sh -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 sleep -> busybox
lrwxrwxrwx    1 root     root            9 Jul  2  2004 su -> tinylogin
lrwxrwxrwx    1 root     root            7 Jul  2  2004 sync -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 tar -> busybox
-rwsr-sr-x    1 root     root        45624 Jul  2  2004 tinylogin
lrwxrwxrwx    1 root     root            7 Jul  2  2004 touch -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 umount -> busybox
lrwxrwxrwx    1 root     root            7 Jul  2  2004 vi -> busybox

Some last directories are worth mentioning. There is /home/httpd/html which is the web root of the built-in webserver ("http demon"). And thus /home/httpd/html/Management is where we find the web script telnet.cgi that gave us access. The webserver itself (thttpd) can be found under /usr/sbin. Directory /lib is where we find Linux' shared objects such as libc.s0.6. We find mke2fs (creates an ext2 file system on an empty hard disk) in directory /usr/bin. The tree below gives an overview.

+- bin/
|  +- busybox
|  +- ls -> busybox
+- dev/
+- etc/
|  +- passwd -> /share/hdd/conf/passwd
|  +- rc.d/
|  +- samba
|     +- smb.conf -> /share/hdd/conf/share/smb.conf
|     +- smbpasswd -> /share/hdd/conf/smbpasswd
+- home/
|  +- httpd/
|     +- html/
|        +- Management/
|           +- telnet.cgi
+- lib/
|  +-
+- lost+found/
+- mnt/
+- proc/
|  +- cpuinfo
|  +- version
+- sbin/
|  +- e2fsck
|  +- fdisk
|  +- fsck.ext3 -> e2fsck
|  +- ifconfig -> ../bin/busybox
+- share
|  +- flash/
|  |  +- conf/
|  |  +- data/
|  +- hdd/
|     +- conf/
|     |  +- passwd
|     |  +- smb.conf
|     +- data/
|        +- debbie/
|        +- maarten/
|        +- public/
+- tmp/
+- upload/
+- usr/
+  +- bin/
|  |  +- Set_Led
|  |  +- id -> ../../bin/busybox
|  |  +- mke2fs
|  |  +- mkfs.ext3 -> mke2fs
|  +- sbin/
|     +- thttpd
+- var/

As a final step I had a look at all processes running.

  PID TTY     Uid        Size State Command
    1         root       1212   S   init
    2         root          0   S   [keventd]
    3         root          0   S   [ksoftirqd_CPU0]
    4         root          0   S   [kswapd]
    5         root          0   S   [bdflush]
    6         root          0   S   [kupdated]
    7         root          0   S   [cifsoplockd]
    8         root          0   S   [mtdblockd]
    9         root          0   S   [khubd]
   18         root          0   S   [usb-storage-1]
   19         root          0   S   [scsi_eh_1]
   22         root          0   D   [ixp425_csr]
   24         root          0   S   [ixp425 ixp1]
   26 ttyS0   root       1916   S   /bin/sh
   27         root       1932   S   /sbin/syslogd -n
   29         root       1924   S   /sbin/klogd -n
  105         root       1216   S   /sbin/udhcpc -H Nas
  127         root          0   S   [kjournald]
  139         root          0   S   [kjournald]
  270         root       2136   S   /usr/sbin/thttpd -C /etc/thttpd.conf
  292         root       3924   S   /usr/sbin/smbd -D
  294         root       3128   S   /usr/sbin/nmbd -D
  297         root       1240   S   /usr/sbin/download
  315         root       1932   S   /usr/sbin/QuickSet
  320         root       1880   S   /usr/sbin/USB_Detect
  324         root       1876   S   /usr/sbin/USB_Detect
  331         root       1296   S   /usr/sbin/crond
  337         root       1908   S   /usr/sbin/CheckResetButton
  339         root       1196   S   /usr/sbin/CheckPowerButton
  341         root       1196   S   /usr/sbin/do_umount
  403         root       2136   S   /usr/sbin/thttpd -C /etc/thttpd.conf
  415         root       1276   S   /bin/inetd
  416         root       1256   S   /usr/sbin/telnetd
  417 ttyp0   root       1928   S   -sh
  427         root       4364   S   /usr/sbin/smbd -D
  432 ttyp0   root       1988   R   ps

3.3. Getting Knoppix as a host system

Now that I was somewhat comfortable with the NSLU2 (or should I say Linux...) I was prepared to take the next step of Jim's article: running the file command on telnet.cgi (that I uploaded from my NSLU2 under telnet control to an ftp server "Cerberus FTP Server" – which I had just downloaded and started).

I figured I had two options: keep on using Windows and try to get a file.exe clone under Windows or start using Linux. The mere thought of hunting for some Linux distribution, fiddling with the partitions on my hard disk and installing Linux made me nervous. However, for the next step on the horizon (running a cross compiler for ARM) I would probably be better off with the Linux option anyhow. Then, I remembered my Knoppix CD. That was it! Definitly option two: Linux.

Knoppix, that is a Linux for Wimps like me. It comes on a bootable CD, so all you have to do is change the boot order in the BIOS of your PC to first check the CD drive, before trying the HD drive. Insert the Knoppix CD in the drive, (re)start the PC and Knoppix boots. It creates a RAM disk as main disk and does not touch your (windows) hard disk at all. And having played with the NSLU2, I realized the Knoppix was very likely able to mount not only my Nas, but probably also my windows hard disk so that I could keep some data persistent.

I fired-up internet explorer, Googled for Knoppix and Bingo on the first link:! I downloaded the 3.8.1 release, an ISO image of 702738kB, which took me 75 minutes. On the same ftp site, I found an md5 file, which contained some sort of checksum for the ISO file: 08d96d6b4772b71b04729127368d013d. Googling for md5 proved comparatively harder, but I soon found To be honest, the user interface sucked, but after I understood what I was supposed to do, my downloaded ISO proved ok. Next step was buring a CD – which, on my old Win98 machine with a (don't laugh) 2x burner, takes nearly an hour.

I put my new hot Knoppix in the CD rom drive and restarted. There is one prompt where Wimps like me can press [enter] and after some waiting there is a quite familiar desktop. I had one problem: it was slooowww (not Knoppix' fault of course). I guessed that it should be possible to boot Knoppix, but just a console and not the cycle eating desktop stuff. I somewhere read about "cheatcodes for Knoppix" (what was I thinking; Knoppix is a game...) and I soon found what I needed (later I found the same list of cheatcodes simply linked from the autorun html file on the CD created from the iso image...):

                     CHEATCODES AND HINTS FOR KNOPPIX V3.8
                         (last update: 22.02.2005)

These options (can be combined) work from the ISOLINUX bootprompt:

knoppix lang=cn|de|da|es|fr|it|nl   specify language/keyboard
knoppix lang=pl|ru|sk|tr|tw|us      specify language/keyboard
knoppix gmt                         Use GMT-based time
knoppix tz=Europe/Berlin            Use this timezone for TZ
knoppix desktop=fluxbox|icewm       Use specified WM instead of KDE (1)
knoppix desktop=kde|larswm|twm      Use specified WM instead of KDE (2)
knoppix desktop=wmaker|xfce         Use specified WM instead of KDE (3)
knoppix screen=1280x1024            Use specified Screen resolution for X
knoppix xvrefresh=60 (or vsync=60)  Use 60 Hz vertical refresh rate for X
knoppix xhrefresh=80 (or hsync=80)  Use 80 kHz horizontal refresh rate for X
knoppix xserver=XFree86|XF86_SVGA   Use specified X-Server
knoppix xmodule=ati|fbdev|i810|mga  Use specified XFree4-Module (1)
knoppix xmodule=nv|radeon|savage|s3 Use specified XFree4-Module (2)
knoppix xmodule=radeon|svga|i810    Use specified XFree4-Module (3)
knoppix 2                           Runlevel 2, Textmode only
knoppix floppyconfig                Run "" from a floppy
... much more cheatcodes ommited...
During the Knoppix boot a prompt appears. When you wait a couple of seconds or press return, the normal boot (with a desktop) happens. Instead I entered
boot: knoppix 2

Phew, that's better: "text mode only" has a speed that is actually usable. And we're root.

# id
uid=0(root) gid=0(root)
However, without the desktop stuff I did't get a mounted Windows hard disk for free. How do you do mount? Where? Stupid me started looking in /share but so much for consistency in Linux systems: knoppix had them in /mnt. From over 15 years ago I remembered man, so I entered man mount (I believe that these days you're supposed to do info mount instead, but old habbits die hard). Those man pages are very hard to read when you do not understand the concepts, but one line struck me:

(ii) When mounting a file system mentioned in fstab,
it suffices to give only the device, or only the mount point.

So, I entered

# cd /mnt
# ls
.  ..  auto  cdrom  floppy  hda1
# ls hda1
an empty directory, so this could be a mount point for the hard disk
# mount hda1
# ls hda1  recycled       User          temp       io.sys
windows      Program Files  autoexec.bat  msdos.sys  GateFtp

Wow, I was proud of myself! My first succesful mount. Intoxicated by this success, I decided to try mounting my Nas. I guessed that Nas would not be in my "fstab", so here I would have to become more creative. I remembered people complain that on one hand the NSLU2 formats the disk as a (Linux) ext3 file system and not (Windows) NTFS, but on the otherhand the NSLU2 does not provide (Linux style) NFS it provides (Windows style) shares. From Jim's article, I equated "Windows shares" with SMB (Server Message Block – seems to be pronounced as samba). I remembered from the man page of mount that the major part was seperate sections devoted to different kinds of file systems (sections in the chapter "FILESYSTEM SPECIFIC MOUNT OPTIONS"). Would SMB by one of them? Sure enough, I found a puzzling section "Mount options for smbfs", which didn't help me much. However, the word smbfs was also listed as a supported "vfstype" for -t! Going back to the top of the man page I found

The standard form of the mount command, is

    mount  -t type  device  dir

so I figured I had to use -t smbfs, create an empty directory for placeholder dir, and somehow identify my Nas device. Could that identification be the same as when using "map network drive" under Windows? I tried

# cd /mnt
# mkdir nas
# mount  -t smbfs  '// 1' nas
Password: The "anonymous guest" presses [enter] here
# ls nas
KnoppixBackup  nslu2trials  mp3s

My second mount!

Would it be possible to mount the Admin 1 share?

# mount  -t smbfs  '//nas/Admin 1'  admin  -o username=admin  //option  ,password=xxx
Password: the admin password
# cd admin
# ls -l
total 12
drwxr-xr-x  1 root root 4096 May 12 17:37 debbie
drwxr-xr-x  1 root root 4096 May 12 17:34 maarten
drwxr-xr-x  1 root root 4096 May 25 17:33 public

My third mount!

But wait a minute, our goal was to run file telnet.cgi, we didn't need to mount the Nas for that. I could simply go to the ftp directory on the Windows hard disk (where the ftp server had stored the upload).

# cd /mnt/hda1/GateFtp
# file telnet.cgi
telnet.cgi: ELF 32-bit MSB executable, ARM, version 1 (ARM),
for GNU/Linux 2.0.0, dynamically linked (uses shared libs), stripped

And that is the same as what Jim reported.

At one moment in time, I wanted to telnet into the Nas. But I had forgotten to enable telnet. And my PC was not running Windows with internet explorer. It was not even running Linux with the Konqueror, I was working in console mode! Would I really have to reboot my PC under Windows for browsing to the web interface of the Nas? Wait, wasn't there this Lynx thing, a text based browser? Would that be part of a standard Linux installation. Let's try...

Using the Lynx browser to access the web interface of my Nas; links are green and the selected link is yellow.

Lynx takes some time to get used to (especially to only use up and down to navigate to the desired link – moving right selects the link), but it does the job!

Enough accomplished for today. Let's go to sleep.
How do you stop a Knoppix machine (in console mode, in desktop mode it is like in Windows: Start|Stop)?
I won't disclose how long it took to come up with

# shutdown -h now

but I didn't get much sleep that night.

Later René told me that ctrl-alt-del would also work – who would have guessed that of a Linux machine...

3.4. Getting a cross compile to work (first try)

Recap. I'm trying to follow Jim Buzbees arcticles on hacking the NSLU2. I bought the hardware, I set it up, I know how to telnet into it, I even have developed some feeling for its Linux system (the target). I downloaded and installed Knoppix and developed some feeling for that as well (the host system). Okay, I'm much slower than Jim. I'm now at page two of his second article (and I've written 16 up till here) and the next hurdle is to get "Hello world" to compile (i.e. a cross compile on the host system for the target system).

Fortunately, as Jim exmplains, Linksys has a (binary) release of a toolchain for the Intel IXDP425 platform on their gpl support site. For some strange reason, its not included in the NSLU2 releases, but it is in the WRV54G Firmware Version 2.03 release.

So I downloaded the file wrv54g-v203.tar.bz2 (an impressive 130 804 866 bytes). I did some [un]tar-ring 15 years ago, but what is this bz2 extension. Since a tar file is nothing but a smart concatenation of files in directories, this is probably a compressed tar file using a "bz2" algorithm. Would I have to download that, would that be part of the Knoppix installation or is that even part of tar?

I rebooted my PC with the Knoppix CD in the cdrom tray, entered the cheatcode for console mode, and mounted the PC hard disk and the nas. I did a man tar and a search /bz2 and found a promising option -j, --bzip2 with specification filter archive through bzip2, use to decompress .bz2 files. So bunzip2 is "done" by tar. Let's create a directory Linux on the hard disk and then untar the downloaded file.

# cd  /mnt/hda1
# mkdir  Linux
# cd  Linux
# cp  /mnt/nas/wrv54g-v203.tar.bz2  .
# tar  -xjvf  wrv54g-v203.tar.bz2
... implausibly old time stamp 1969-12-31 18:59:59
... Cannot change ownership to uid 0, gid 0: Operation not permitted
... ans several others
# ls
gpl_code_2.03  wrv54g-v203.tar.bz2
# cd gpl_code_2.03
# ls  -al
total 422204
drwxr-xr-x  3 root root      4096 Sep 12  2003 .
drwxr-xr-x  4 root root      4096 May 21 22:52 ..
-rw-rw-rw-  1 root root     32224 Dec 31  1969 DDNS.tgz
-rw-rw-rw-  1 root root 411217920 Dec 31  1969 gpl_code_wrv54g_2.03.tar
-rw-rw-rw-  1 root root       288 Dec 31  1969 howto.txt
drwxr-xr-x  2 root root      4096 Sep 15  2003 montevista-glibc
-rw-rw-rw-  1 root root  20634318 Dec 31  1969 toolchain.tgz

So, the wrv54g-v203.tar.bz2 unpacks in a single directory gpl_code_2.03 where we find what we are looking for: toolchain.tgz (plus the sources for the WRV54G firmware). From studying the man page of tar just before, I remembered that tgz is for gzip'ed tar files, and that you need the -z option.

# tar  -xzvf toolchain.tgz
... Cannot change ownership to uid 0, gid 0: Operation not permitted
... Cannot create symlink to '': Operation not permitted
... and many, many others

# ls  -al
total 461400
drwxr-xr-x  3 root root      4096 Sep 12  2003 .
drwxr-xr-x  4 root root      4096 May 21 22:52 ..
-rw-rw-rw-  1 root root     32224 Dec 31  1969 DDNS.tgz
-rw-rw-rw-  1 root root 411217920 Dec 31  1969 gpl_code_wrv54g_2.03.tar
-rw-rw-rw-  1 root root       288 Dec 31  1969 howto.txt
drwxr-xr-x  2 root root      4096 Sep 15  2003 montevista-glibc
-rw-rw-rw-  1 root root  20634318 Dec 31  1969 toolchain.tgz
drwxr-xr-x  1 root root      4096 May 21 23:25 usr

I got a lot of warnings during the untar, but I didn't think much of it (during this first try!)

The figure below sketches how such a cross-compile tree is populated (do all you unix guys understand which binary to store in which bin directory?).

  +- local/
    +- openreg/
       +- armsaeb/
       |  |
       |  +- armv4b-hardhat-linux/               The target tools, headers, libs
       |  |  +- bin/ with files
       |  |  +- etc/ with files and dirs
       |  |  +- include/
       |  |  |  +- stdio.h                       A target header file
       |  |  |  +- stdlib.h
       |  |  |  +- many others
       |  |  +- lib/
       |  |  |  +-
       |  |  |  +- libc.a                        A target library
       |  |  |  +-                       A target shared object
       |  |  |  +- ->    Was missing (in first try)
       |  |  |  +- libc_nonshared.a
       |  |  |  +- many others
       |  |  +- sbin/ with files
       |  |  +- usr/ with dirs
       |  |
       |  +- bin/                                Host tools
       |  |  +- armv4b-hardhat-linux-addr2line
       |  |  +- armv4b-hardhat-linux-ar
       |  |  +- armv4b-hardhat-linux-as
       |  |  +- armv4b-hardhat-linux-c++filt
       |  |  +- armv4b-hardhat-linux-cpp
       |  |  +- armv4b-hardhat-linux-g++
       |  |  +- armv4b-hardhat-linux-gasp
       |  |  +- armv4b-hardhat-linux-gcc         The cross compiler
       |  |  +- armv4b-hardhat-linux-gcov
       |  |  +- armv4b-hardhat-linux-gdb
       |  |  +- armv4b-hardhat-linux-ld
       |  |  +- armv4b-hardhat-linux-nm
       |  |  +- armv4b-hardhat-linux-objcopy
       |  |  +- armv4b-hardhat-linux-objdump
       |  |  +- armv4b-hardhat-linux-ranlib
       |  |  +- armv4b-hardhat-linux-readelf
       |  |  +- armv4b-hardhat-linux-size
       |  |  +- armv4b-hardhat-linux-strings
       |  |  +- armv4b-hardhat-linux-strip
       |  |
       |  +- doc/ with files                     Host tools
       |  |
       |  +- lib/                                Host libraries
       |  |  +- gcc-lib/
       |  |     +- armv4b-hardhat-linux/
       |  |        +- 2.95.3/
       |  |           +- crtbegin.o              Startup code added by gcc
       |  |           +- many others
       |  |
       |  +- man/ with a dir                     Host man pages
       +- bin/ with files (that are irrelevant?)
       +- share/ with a dir (that is irrelevant?)

I added the hello world program in the Linux root of my hard disk (that is /mnt/hda1/Linux/hello.c).

#include <stdio.h>

int main(int argc, char * argv[])
    printf("hello, world!\n");
    return 0;

I followed the export trick of Jim and...

# export PATH=/mnt/hda1/Linux/gpl_code_2.03/usr/local/openrg/armsaeb/bin/:$PATH
# armv4b-hardhat-linux-gcc  hello.c  -o hello
cannot find
collect2: ld returned 1 exit status

... damn.

Some days later Chritiene gave me the tip of trying option -static. His claim was that "static" builds are more stand-alone than "dynamic" builds (less dependencies) so that they tend to work sooner. Running out of options a gave it a try.

# armv4b-hardhat-linux-gcc  -static  hello.c  -o hello_s
# ls -al hello*
-rwxrwxrwx   1 knoppix knoppix     422660 May 22 00:28 hello_s
-rwxrwxrwx   1 knoppix knoppix        104 May 22 00:25 hello.c
# file  hello_s
hello: ELF 32-bit MSB executable, ARM, version 1 (ARM),
for GNU/Linux 2.0.0, statically linked, not stripped

I was not sure why this works, but I was already happy to get some results. The next hurdle is looming ahead: running this baby.

3.5. Getting access into my NSLU2 (big boy version)

I had an executable (ok, it was statically linked, but let that be a problem for later). So, let's run the baby. That couldn't be hard, could it? How wrong can you be...

Why had Jim used ftp to get the hello_s program on the Nas? We can simply copy it to a disk the Nas sees.

# cp /mnt/hda1/Linux/hello_s /mnt/nas
# telnet nas
Nas login: ourtelnetrescueuser
Password: password from Trevor's site
No directory, logging in with HOME=/

BusyBox v0.60.4 (2004.07.01-03:05+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

$ cd /share/hdd/data/public
$ ls -al hello_s
-rwxrw----    1 guest    everyone   422660 Jun  4  2005 hello_s
$ ./hello_s
./hello_s: Permission denied
$ chmod +x hello_s
hello_s: Operation not permitted

Oops. I was logged in as ourtelnetrescueuser who did not have the rights to execute the program nor did he have the rights to change the execute rights. Ahh. That's why Jim used ftp. But that proved a wrong assumption as well. User ourtelnetrescueuser does not have write rights in any directory nor does he own any directory (in order to enable writing). So 'getting' a file and storing that with ftp didn't work either.

Why did it work for Jim? After a couple of days (yes really, that long) it hit me. Jim had logged in as a powerfull root, not as do-nothing ourtelnetrescueuser.

Do I need to dismount my NSLU2 and bring it upstairs to hook it to my Knoppix PC so that I can mount the partition with the password file? No, on Jims private pages he has another nice trick: when you go the the NSLU2 web interface, Administration, Advanced, Backup, we'll find a 'Config Backup'. The 'Config' is actually the important files on the first partition (sda2, mounted as /share/hdd/conf): passwords, samba password, shares, etc. When we press the Download button (and wait some time), we are prompted to save the configuration backup.

Saving the backup of the configuration.

The trick is that this config.bin is actually a tar file. So, let's save it on the Nas' public share, make a backup, untar it and let's see what we've got.

# cp /mnt/nas
# ls -al
total 20
drwxr-xr-x  1 root root  4096 Jun  4 16:40 .
drwxr-xr-x  1 root root  4096 Jun  4 16:40 ..
-rwxr--r--  1 root root 11776 Jun  4 16:28 config.bin
# cp config.bin
# tar -xvf config.bin
# cd config/hdd           all files are in config/hdd
# ls -al
total 14
drwxr-xr-x  1 root root 4096 Jun  4 16:26 .
drwxr-xr-x  1 root root 4096 Jun  4 16:26 ..
-rwxr--r--  1 root root   20 Jun  4 16:26 .htpasswd
-rwxr--r--  1 root root 1146 Jun  4 16:26 CGI_ds.conf
-rwxr--r--  1 root root  201 Jun  4 16:26 group
-rwxr--r--  1 root root  459 Jun  4 16:26 passwd
-rwxr--r--  1 root root  170 Jun  4 16:26
-rwxr--r--  1 root root  798 Jun  4 16:26 smb.conf
-rwxr--r--  1 root root  422 Jun  4 16:26 smbpasswd
-rwxr--r--  1 root root  111 Jun  4 16:26

The files,, and passwd appear interesting (probably your passwords look more "random" :-).

# cat
debbie=debbie:0,maarten:0  So, a smb group debbie with users debbie and maarten
# cat
ADMIN=:/:administrators:7  So, our assumed mapping from shares to dirs seems ok
DISK=For everyone:/public/:administrators:7,everyone:7
# cat passwd
ftp:x:14:50:FTP User:/:

maarten:1122334455667:2000:501:Maarten Pennings::/dev/null
debbie:7889900AABBCC:2001:501:Debbie Ridders::/dev/null

I made two changes. I changed the shell (last fields) for maarten into /bin/sh. This would allow me to login (via telnet) with maarten, an ordinary user. Furthermore, I copied the password from maarten to root. This would change the root password into a known one, allowing me to login (via telnet) with root, a power user.

ftp:x:14:50:FTP User:/:

maarten:1122334455667:2000:501:Maarten Pennings::/bin/sh
debbie:7889900AABBCC:2001:501:Debbie Ridders::/dev/null

Probably you should be careful doing this; a corrupt file might make the NSLU2 go astray (we can always undo the change by mounting the disk on the Knoppix machine, and if worst comes to worst, we can reformat the disk and replug it in the NSLU2). What worries me a little is that .htpasswd and smbpasswd seem to have copies of the password of some users in passwd (but with a different encryption algorithm!). So I decided not to change too much. Let's repack.

# cd ../..
# tar -cvf config.bin config
# ls -al
total 44
drwxr-xr-x  1 root root  4096 Jun  4 17:02 .
drwxr-xr-x  1 root root  4096 Jun  4 16:43 ..
drwxr-xr-x  1 root root  4096 Jun  4 16:26 config
-rwxr--r--  1 root root 20480 Jun  4 23:07 config.bin
-rwxr--r--  1 root root 11776 Jun  4 16:28

What worried me was that the original ( was half the size of the patched one (config.bin). I did some visual checking (tar files are just a cat with some binary stuff in between, so tar'ed ascii files are somewhat readable) but they seemed equal except for the binary administration (Frans suggested that a different blocksize might help, using the -b option for tar). Let's plug it back and pray.

Uploading the patched configuration.

I noted the warning on the upload dialog. Immediately after clicking 'Upload' we get another warning.

It seems we're doing scarry things...

A couple of seconds later the upload seems successfull, but then we have two wait a nerve wrecking 30 seconds to see if the NSLU2 still boots. Pehh. It does. Let's check our hacked root account and our hello world program.

We're in, and it works!

Not bad. Let's go to sleep.

3.6. Getting a cross compile to work (second try)

I was rather happy with myself. I had an NSLU2 with a root password and I had knoppix with which I could write a "hello world". But what nagged me was that I only succeeded in doing a static build, not a dynamic build. Nevertheless, I had the same toolchain as Jim (downloaded from Linksys GPL site). What had Jim done different? This question haunted me for more than a week.

In my daytime job, some of my colleges are working with a gcc cross compiler for MIPS. I asked Hans if they knew something about this missing I got the following mail back:

I believe that:

	$ ln  -s

will help. We have (for MIPS)

	-rwxr-xr-x    1 1021     1000      1696014 Jul 16  2004
	-rw-r--r--    1 1021     1000      3369712 Jul 16  2004 libc.a
	-rw-r--r--    1 1021     1000          164 Jul 16  2004
	lrwxrwxrwx    1 1021     1000           13 Mar  4 16:59 ->

At that moment I knew what I'd done wrong. I had untar'ed the toolchain on my mounted FAT32 disk. Which does not support links. And tar files do. And, indeed, I got a tremendous amount of warnings during the untar. And most of them read "Cannot create symlink to ''". Stupid me.

But how to solve this problem. I liked Knoppix for the fact that I didn't have to change my hard disk (partitions). Would I have to do that just to be able to create an Ext2/Ext3 partition? But then I remembered reading somewhere that you could fool Linux in thinking that a file is a device. Googling around I found how to create a big empty file on my mounted FAT32 system.

# cd /mnt/Linux
# dd  if=/dev/zero  of=fs-in-file  bs=1M  count=1024
1024+0 records in
1024+0 records out
1073741824 bytes transferred in 214.532682 seconds (5005027 bytes/sec)

# ls -al
total 1048688
drwxrwxrwx   4 knoppix knoppix     16384 May 21 16:57 .
drwxrwxrwx  15 knoppix knoppix     16384 Dec 31  1969 ..
-rwxrwxrwx   1 knoppix knoppix 134217728 May 21 16:57 fs-in-file
files ommitted

That's 1G wasted on zero's. Now we tell mkfs to use those zeros to create a filesystem in. It replies with a Windows style question wether I'm sure on which I tend to answer 'yes'

# mkfs.ext3  fs-in-file
mke2fs 1.37 (21-Mar-2005)
fs-in-file is not a block special device.
Proceed anyway? (y,n) y
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
131072 inodes, 262144 blocks
13107 blocks (5.00%) reserved for the super user
First data block=0
8 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
	32768, 98304, 163840, 229376

Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 38 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

That output is probably very important and very informative (that's why I kept a copy in this web page :-). Next step is to mount this file system...

# cd /mnt
# mkdir  fsif
# mount  /mnt/hda1/Linux/fs-in-file  fsif  -o loop
# cd fsif
# ls -al
total 21
drwxr-xr-x  3 root root  1024 May 21 16:59 .
drwxr-xr-x  6 root root  1024 May 21 17:00 ..
drwx------  2 root root 12288 May 21 16:59 lost+found

The -o loop was not very evident at first. But when you leave it out mount complains that you can not mount a file, or did I forget to use -o loop? (and if you read Jim's arcticles carefully, you'll see -o loop used) We're done, we have a 1G ext3 file system.

In this directory, I repeated the untarring of wrv54g-v203.tar.bz2 and next of toolchain.tgz. Then let's see if we can find

# cd /mnt/fsif/gpl_code_2.03/usr/local/openrg/armsaeb/armv4b-hardhat-linux/lib
# ls -al libc*
-rwxr-xr-x  1 root root 1366516 Jan  8  2003
-rw-r--r--  1 root root 2791512 Jan  8  2003 libc.a
-rw-r--r--  1 root root     164 Jan  8  2003
lrwxrwxrwx  1 root root      13 May 21 23:25 ->
-rw-r--r--  1 root root    6936 Jan  8  2003 libc_nonshared.a
-rw-r--r--  1 root root   30306 Jan  8  2003
-rw-r--r--  1 root root   25142 Jan  8  2003 libcrypt.a
lrwxrwxrwx  1 root root      13 May 21 23:25 ->
lrwxrwxrwx  1 root root      17 May 21 23:25 ->

Indeed, a link! So, would this untar'ed toolchain work for a dynamically linked hello world?

# export PATH=/mnt/fsif/gpl_code_2.03/usr/local/openrg/armsaeb/bin:$PATH
# cd /mnt/hda1/Linux
# armv4b-hardhat-linux-gcc  hello.c  -o hello_d
# file hello_d
hello_d: ELF 32-bit MSB executable, ARM, version 1 (ARM),
for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped
# ls -al hello*
-rwxrwxrwx  1 knoppix knoppix    104 May 22 00:25 hello.c
-rwxrwxrwx  1 knoppix knoppix   5072 Jun  7 00:49 hello_d
-rwxrwxrwx  1 knoppix knoppix 422660 May 22 00:28 hello_s

Would stripping of the debug symbols make much difference?

# armv4b-hardhat-linux-strip  hello_d
# armv4b-hardhat-linux-strip  hello_s
# ls -al hello*
-rwxrwxrwx  1 knoppix knoppix    104 May 22 00:25 hello.c
-rwxrwxrwx  1 knoppix knoppix   2760 Jun  7 00:53 hello_d
-rwxrwxrwx  1 knoppix knoppix 369472 Jun  7 00:53 hello_s

Yes, it does! Let's compare the different sizes.

BUILD SIZESwith symbolsstrippedreduces to
static422 660369 47287%
dynamic5 0722 76054%

Size ratios for various builds (static/dynamic/stripped)

I copied the new executable to my nas, and tried it.

The dynamic stripped version also works!

A week later, together with a collegue, I did some pointless hacking resulting in a tetris application running via telnet on the nas.

Tetris on the NSLU2

4. Going to Unslung

4.1. Flashing Unslung

I've been playing with my NSLU2 for nearly 2 month now, and I still didn't dare to go over to unslung. Unslung is a firmware replacement from a world-wide developer community around the NSLU2. I was scared off by the fact that I could turn my box into a brick, and, frankly, the readme was a bit intimidating. On hindsight, there was no need to be scared (as usual).

Unslung replaces the Linksys firmware. When installed, you won't notice many (any?) changes, it stays very close to the standard Linksys firmware. Most people that install Unslung will also unsling it (actually, there is hardly any reason to install Unslung and not unsling it). Unslinging is the process of copying the root filesystem (that normally resides on the RAM disk – after being copied from the flash memory on startup) to an external hard disk (or USB flash disk for that matter). When an NSLU2 with Unslung boots, it checks if there is an external disk with a copy of the filesystem. If so, the NSLU2 will use the filesystem on the external disk instead of using the internal RAM for a ramdisk. This frees about 10M of internal RAM. The result of all this is that we can install several big programs on the disk (plenty of space there) and run them, because there is plenty of RAM available. We're talking about programs like Apache with MySql and PHP. The second great feature of Unslung is that it comes with ipkg – Itsy Package Management System, a tool that let's you install any package (like Apache) from a website onto your NSLU2 with a single command. And there are more than 300 packages. We definitly need to to go over to Unslung!

I visited the Unslung site, and was rather suprised by the offering: 5.5 Beta, 4.20 Beta, 3.18 Beta, 3.17 Beta, 3.16 Beta, 2.12 Beta, 1.11 Beta. Strangely jumping release numbers, and non of the releases ever leaving the 'beta' stage. If that's the way its, that's the way it is. I downloaded 5.5 beta zip file, unpacked it, and read the readme (a couple of times). I broke down my setup in the utility closet, took the hardware to my study so that I had everything under reach. Now, lets execute the readme (instead of reading it another time).

The first step in the readme is an insurance against corrupt flashes: test RedBoot telnet access. This is described in TelnetIntoRedBoot in the NSLU2 wiki. Unfortunately, this required patching my network setup (I hooked my NSLU2 with a crosscable to my PC, and gave my PC a fixed ethernet address of and a subnet mask of The trick with the continuous pinging, then connecting and then ^C worked like a charm as the following dump proves.

== Executing boot script in 1.200 seconds - enter ^C to abort
RedBoot> ^C        ok, ok, one ^C to many, I was a bit stressed
RedBoot> help
go to assign mode
Set/Query the system console baud rate
   baudrate [-b ]
sercomm boot flow
Manage machine caches
   cache [ON | OFF]
Display/switch console channel
   channel [-1|]
Compute a 32bit checksum [POSIX algorithm] for a range of memory
   cksum -b  -l 
Display (hex dump) a range of memory
   dump -b  [-l ] [-s] [-1|2|4]
Execute an image - with MMU off
   exec [-w timeout] [-b  [-l ]]
        [-r  [-s ]]
        [-c "kernel command line"] []
Manage FLASH images
   fis {cmds}
Execute code at a location
   go [-w ] [entry]
Help about help?
   help []
Set/change IP addresses
   ip_address [-l ] [-h ]
Load a file
   load [-r] [-v] [-d] [-h ] [-m ] [-c ]
        [-b ] 
Compare two blocks of memory
   mcmp -s  -d  -l  [-1|-2|-4]
Fill a block of memory with a pattern
   mfill -b  -l  -p  [-1|-2|-4]
move kernel&ramdisk to ram
Network connectivity test
   ping [-v] [-n ] [-l ] [-t ] [-r ]
        [-i ] -h 
Reset the system
Set/Read MAC address for NPE ethernet ports
   set_npe_mac [-p ] [xx:xx:xx:xx:xx:xx]
go to upgrade mode
Display RedBoot version information
Display (hex dump) a range of memory
   x -b  [-l ] [-s] [-1|2|4]

Let's give one harmless command.

RedBoot> version
RedBoot(tm) bootstrap and debug environment [ROMRAM]
Red Hat certified release, version 1.92 - built 15:16:07, Feb  3 2004

Platform: IXDP425 Development Platform (XScale)
Copyright (C) 2000, 2001, 2002, Red Hat, Inc.

RAM: 0x00000000-0x02000000, 0x000723a0-0x01ff3000 available
FLASH: 0x50000000 - 0x50800000, 64 blocks of 0x00020000 bytes each.

So, we're insured against corrupt flashes.

Preparation steps 2,3 4, and 5 are easy: I have a disk, it is formatted, it is working properly. Then the final prepartion step before flashing: making a backup of the configuration. That's easy, I did that already before (to hack the root password). Up to the real thing: flashing the Unslung firmware.

The readme is rather pressing on hard disks being attached or not. But the bottom line for me, with a fresh NSLU2 (V2.3R24), is: detach the disks before powering up the NSLU2, go to the "upgrade firmware" page (username/password is admin/admin since there is no disk attached) of the web interface select the Unslung bin file and press go.

The upgrade firmware page with the old firmware listed and the new firmware file chosen.

Then, there is a nerve wrecking extra confirmation.

Extra confirmation before falshing starts.

But after only 2.5 minutes a hopeful sign of life popped-up.

Flashing is done.

Next, we must wait another 30 seconds or so before the reboot finishes. Then, we can reload the web interface.

Flashing was successful!

That was easy. Is that all? Yes. Well, no, the readme wants us to shut the NSLU2 down, attach the disk, power it up and check whether the disk is working normally. It does. Remember, that we are not yet unsling, so the NSLU2 behaves like a stock Linksys device.

4.2. Unslinging

The unslinging is slightly harder than flashing. The reason for this is the three faces of the NSLU2: without a disk it runs from internal RAM disk (with admin having admin as password and root having uNSLUng as password), or, secondly, with the disk attached that has not yet been unsling (with admin having the password we choose weeks ago and root having an unknown password or, in my case, the hacked password copied from user maarten), or, thirdly, with the disk attached after unslinging.

The advice of the readme is to boot the NSLU2 without disks (so that the root password is known: uNSLUng). I guess that I could have booted with disks attached, since I know the root password on the disk. But why take risks :-). After booting, I enabled telnet with admin/admin, did a telnet login with root/uNSLUng, and only then hotplugged the harddisk. I reloaded the web interface several times until the disk became available. I checked the (pre-unsling) content of the hard disk in the telnet session, executed the unsling, and checked the (post-unsling) content:

Nas login: root
Password: uNSLUng
No directory, logging in with HOME=/

BusyBox v0.60.4 (2004.07.01-03:05+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

# cd /share/hdd/data
# ls
debbie          lost+found      maarten         public          quota.user
# /sbin/unsling  disk1
Target disk is /share/hdd/data
Copying the complete rootfs from / to /share/hdd/data.
19031 blocks
Linking /usr/bin/ipkg executable on target disk.
Creating /.sda1root to direct switchbox to boot from /share/hdd/data.
# ls            // the blue entries already existed
bin             debbie          dev             etc             home
initrd          lib             linuxrc         lost+found      maarten
mnt             opt             proc            public          quota.user
quota.user~     sbin            share           tmp             unslung
upload          usr             var

I was curious about the unsling program. It appeared to be a script.

# cat /sbin/unsling

usage="Usage: $0 disk1|disk2"

# Set target disk

if [ $# -gt 1 ] ; then
    echo $usage
    exit 1

if [ $# -eq 1 ] ; then
    if [ "$1" = "disk1" ] ; then
    elif [ "$1" = "disk2" ] ; then
    elif [ "$1" = "hdd-data" ] ; then
    elif [ "$1" = "hdd-conf" ] ; then
    elif [ "$1" = "flash-data" ] ; then
    elif [ "$1" = "flash-conf" ] ; then
        echo $usage
        exit 1
    echo $usage
    exit 1

# Check it's a real mount point

if grep $targ /proc/mounts >/dev/null 2>&1 ; then
    echo "Target disk is $targ"
    echo "Error: $targ is not a mounted disk"
    exit 1

# Start at the root directory

cd /

# Save the existing ipkg database.

rm -rf $targ/usr/lib/ipkg.old
if [ -f $targ/usr/lib/ipkg/status ] ; then
        mv $targ/usr/lib/ipkg $targ/usr/lib/ipkg.old

# Copy the complete rootfs to the target.

echo "Copying the complete rootfs from / to $targ."
/usr/bin/find / -print0 -mount | /usr/bin/cpio -p -0 -d -m -u $targ
rm -rf $targ/dev ; mv $targ/dev.state $targ/dev
rm -rf $targ/var ; mv $targ/var.state $targ/var

# Copy over the existing ipkg database.

if [ -f $targ/usr/lib/ipkg.old/status ] ; then
        echo "Preserving existing ipkg database on target disk."
        ( cd $targ/usr/lib/ipkg.old ; tar cf - . ) | ( cd $targ/usr/lib/ipkg ; t
ar xf - )

echo "Linking /usr/bin/ipkg executable on target disk."
rm -f $targ/usr/bin/ipkg ; ln -s /usr/bin/ipkg-cl $targ/usr/bin/ipkg

# Create the boot flag file.

rm -f /.sd??root $targ/.sd??root

echo "Creating /$flag to direct switchbox to boot from $targ."
echo > /$flag
echo > $targ/$flag

exit 0

I had a password for root on my (now unslung) disk, I didn't have any "legacy" package install, so I was done. All I had to do was confirm succes. That is, reboot, enable telnet, login and check whether the external disk is now used as root file system.

Nas login: root
Password: uNSLUng
No directory, logging in with HOME=/

BusyBox v0.60.4 (2004.07.01-03:05+0000) Built-in shell (ash)
Enter 'help' for a list of built-in commands.

# df
Filesystem           1k-blocks      Used Available Use% Mounted on
rootfs               192117464   1363388 188802260   1% /
/dev/sda1                 6528      5312      1216  81% /initrd
/dev/sda1            192117464   1363388 188802260   1% /
/dev/sda1            192117464   1363388 188802260   1% /share/hdd/data
/dev/sda2               116661      4168    111289   4% /share/hdd/conf

The root file system is the same as the mounted external harddisk. That qualifies as a successful unsling! I visited the Yahoo group nslu2-linux and added record 49 to the "The 5.x Unslung" table in the "Database" section. Also remember to read the NOTES (as the readme explains). They can be found in /opt/doc/.

4.3. Installing packages

Let's see if we can install some permanent SSH server. This would free us from enabling telnet each time the NSLU2 is rebooted (but that seems also possible with a Unslung diversion script). And, since SSH is more secure than telnet, it opens the possibility to expose the NSLU2 to the internet (rather than just my local network).

The NOTES file from Unslung (/share/hdd/data/opt/doc) gives an introduction to ipkg. The first step it suggests is to check for network connectivity from the NSLU2 to the package repository on

# ping
PING ( 56 data bytes
64 bytes from icmp_seq=0 ttl=47 time=162.8 ms
64 bytes from icmp_seq=1 ttl=47 time=160.9 ms
64 bytes from icmp_seq=2 ttl=47 time=168.2 ms
64 bytes from icmp_seq=3 ttl=47 time=161.1 ms

Great! The NSLU2 can reach the package repository.
Next, we have to update the list of available packages.

# ipkg  update
Updated list of available packages in /usr/lib/ipkg/lists/cross
Updated list of available packages in /usr/lib/ipkg/lists/native
Updated list of available packages in /usr/lib/ipkg/lists/oe

It looks like three groups of packages are updated.
Let's see which packages are installed on my "virgin" Unslung NSLU2.

# ipkg  list_installed
cpio - 2.5-r2 -
devio - r1-r0 -
findutils - 4.1.20-r1 -
ipkg - 0.99.148-r0 -
kernel-image-2.4.22-xfs - 2.3r29-r2 -
kernel-module-ftdi-sio - 2.3r29-r2 - ftdi-sio kernel module; USB FTDI Serial Converters Driver
kernel-module-kaweth - 2.3r29-r2 - kaweth kernel module; KL5USB101 USB Ethernetdriver
kernel-module-pegasus - 2.3r29-r2 - pegasus kernel module; Pegasus/Pegasus II USB Ethernet driver
kernel-module-pl2303 - 2.3r29-r2 - pl2303 kernel module; Prolific PL2303 USB toserial adaptor driver
kernel-module-usbnet - 2.3r29-r2 - usbnet kernel module; USB Host-to-Host Link Drivers (numerous vendors)
kernel-module-usbserial - 2.3r29-r2 - usbserial kernel module; USB Serial Driver core
libc6-unslung - 2.2.5-r5 -
libgcc - 3.4.4-r0 -
libipkg - 0.99.148-r0 -
nslu2-linksys-libs - 2.3r29-r2 -
portmap-unslung - 5-9-r1 -
slingbox - 1.00-r6 -
unslung-rootfs - 2.3r29-r9 -
update-modules - 1.0-r3 -
wget - 1.9.1-r1 -

Wow, that's much more than I expected (which was 0).
Let's see which packages are available for install.

# ipkg  list
abook - 0.5.3-1 - Abook is a text-based addressbook program designed to use with mutt mail client.
adduser - 1.00-4 - a multi-call binary for login and user account administration
adns - 1.1-1 - Asynchronous resolver library and DNS resolver utilities.
alac-decoder - 0.1.0-1 - A decoder for the apple lossless file format
apache - 2.0.54-2 - The most popular web server on the internet
...  many skipped ...
unslung-feeds - 3.0-1 - A list of sanctioned Unslung package feeds.
...  many skipped ...
xvid - 20050214-2 - Xvid is MPEG4 codec
zlib - 1.2.2-2 - zlib is a library implementing the 'deflate' compression system.

That's more than 400 packages!
On the wiki for Unslung packages, the package unslung-feeds is installed, and an extra update is done.

# ipkg  install  unslung-feeds
Installing unslung-feeds (3.0-1) to root...
Configuring kernel-module-ftdi-sio
Configuring unslung-feeds
Configuring update-modules
# ipkg  update
Updated list of available packages in /usr/lib/ipkg/lists/cross

Updated list of available packages in /usr/lib/ipkg/lists/native

Updated list of available packages in /usr/lib/ipkg/lists/oe

Updated list of available packages in /usr/lib/ipkg/lists/unslung-cross

Updated list of available packages in /usr/lib/ipkg/lists/unslung-native

I'm not sure what the unslung-feeds package does, and the help text "A list of sanctioned Unslung package feeds" doesn't help much. One thing I notice is that unslung-feeds has added extra lists of packages.

Let's install SSH. Which package is that?

# ipkg  list  |  grep  -i  ssh
dropbear - 0.44test4-3 - Lightweight SSH client and server system
openssh - 3.8p1-3 - The OpenSSH distribution.

There are two SSH packages: dropbear and openssh! The wiki for Unslung packages calls openssh "the recommended SSH server", and it has a HowTo, so let's pick that one instead of dropbear.

# ipkg  install  openssh
Installing openssh (3.8p1-3) to root...
Installing openssl (0.9.7d-3) to root...
Installing zlib (1.2.2-2) to root...
Configuring openssh

Generating RSA Key...
Generating public/private rsa1 key pair.
Your identification has been saved in /opt/etc/openssh/ssh_host_key.
Your public key has been saved in /opt/etc/openssh/
The key fingerprint is:
Generating RSA Key...
Generating public/private rsa key pair.
Your identification has been saved in /opt/etc/openssh/ssh_host_rsa_key.
Your public key has been saved in /opt/etc/openssh/
The key fingerprint is:
Generating DSA Key...
Generating public/private dsa key pair.
Your identification has been saved in /opt/etc/openssh/ssh_host_dsa_key.
Your public key has been saved in /opt/etc/openssh/
The key fingerprint is:
Fixing permissions on the /tmp directory...
Configuring openssl
Configuring zlib

This tells us that actually three packages have been installed (marked in red): openssh, openssl, and zlib (a rerun of ipkg list_installed confirms this, and also shows that unslung-feeds was installed). The fingerprint in blue will pop-up in a later chapter.

Let's see if the server is running.

# ps  -ef  |  grep  sshd
  573         root       3168   S   /opt/sbin/sshd
  590 ttyp0   root       2696   S   grep sshd

Yes, it is!
Would that survive a reboot? I could press the power switch on the NSLU2, but for that I have to descend to the utility closet. So, instead, I do it from the telnet session.

Sync to flush the file system buffers, and then a reboot.

Wait for the reboot to complete, enable telnet again, login via telnet en check the ssh server.

# ps  -ef  |  grep  sshd
  423         root       3168   S   /opt/sbin/sshd
  452 ttyp0   root       1528   D   grep sshd

That looks good.
No more telnet enabling...
We only need an ssh client.

In the next chapter, we'll have a look at an ssh client and at setting up the openssh server. But as a last step of this chapter "Installing packages" let's have a look what installing means. I did a ls -alR / before and after running ipkg install openssh. A diff shows that the following files have been added to the filesystem.

+- opt
|  +- bin
|  |  +- openssl
|  |  +- scp
|  |  +- sftp
|  |  +- slogin -> ./ssh
|  |  +- ssh
|  |  +- ssh-add
|  |  +- ssh-agent
|  |  +- ssh-keygen
|  |  +- ssh-keyscan
|  +- etc
|  |  +- init.d
|  |  |  +- S40sshd
|  |  +- openssh
|  |     +- moduli
|  |     +- ssh_config
|  |     +- ssh_host_dsa_key
|  |     +-
|  |     +- ssh_host_key
|  |     +-
|  |     +- ssh_host_rsa_key
|  |     +-
|  |     +- sshd_config
|  +- include
|  |  +- openssl
|  |  |  +- aes.h
|  |  |  +- blowfish.h
|  |  |  +- opensslconf.h
|  |  |  +- x509v3.h
|  |  |  +- ... many others ...
|  |  +- zconf.h
|  |  +- zlib.h
|  +- lib
|  |  +- ->
|  |  +- ->
|  |  +-
|  |  +- ->
|  |  +- ->
|  |  +-
|  |  +- ->
|  |  +- ->
|  |  +-
|  +- libexec
|  |  +- sftp-server
|  |  +- ssh-keysign
|  +- man
|  |  +- man1
|  |  |  +- scp.1
|  |  |  +- sftp.1
|  |  |  +- slogin.1 -> ./ssh.1
|  |  |  +- ssh-add.1
|  |  |  +- ssh-agent.1
|  |  |  +- ssh-keygen.1
|  |  |  +- ssh-keyscan.1
|  |  |  +- ssh.1
|  |  +- man5
|  |  |  +- ssh_config.5
|  |  |  +- sshd_config.5
|  |  +- man8
|  |     +- sftp-server.8
|  |     +- ssh-keysign.8
|  |     +- sshd.8
|  +- sbin
|  |  +- sshd
|  +- share
|     +- openssl
|        +- openssl.cnf
+- usr
|  +- lib
|     +- ipkg
|        +- info
|           +- openssh.control
|           +- openssh.list
|           +- openssh.postinst
|           +- openssh.prerm
|           +- openssl.conffiles
|           +- openssl.control
|           +- openssl.list
|           +- zlib.control
|           +- zlib.list
+- var
   +- run

Note that all files added by the installation end up under /opt (the file /var/run/ contains the process id of the running ssh daemon; it is not created by the installation, it appears when running the daemon; the files under /usr/lib/ipkg are not part of ssh, they form the administration of the package program). The openssh server is started at boot time due to the entry in /opt/etc/init.d. The /opt/doc/NOTES file explains another mechanism: diversion scripts. Diversion scripts go in the /unslung directory (you may have to create that directory first). Note that the NOTES file advises to use diversion scripts rather than editing system files directly as this will allow us to upgrade the Unslung firmware in the future without having to make all of your changes again. Suddenly the cryptic sentence from the readme The unsling script will not touch anything in /unslung or /opt on your disk, so make sure all your file modifications are in those directories, as you were warned in the README file in all previous Unslung versions :-) makes sense: all packages are installed in /opt and all diversion scripts in /unslung.

Note also that the openssh package not only installs the server (/opt/sbin/sshd, the ssh daemon) but als a client: /opt/bin/ssh.

5. Ssh

5.1. What is ssh?

So, what is this ssh actually?
Ssh is about a secure connection between a server (like the just installed sshd) and a client (like ssh on unix and for example putty on Windows). The focus here is on client and server and a secure connection. But once the server is running several possibilities for secure "clienting" arise

How is the security established? The answer is not at all simple. The ssh protocol has two versions. Each version supports several ways of authentication, and the actual security is achieved through one of several encryption algorithms. So, far from easy. Let's review the groundworks.

The security relies on what is known as public and private key pairs. The trick is that a message encrypted with a public key can only be decrypted with the private key. So system X could publish a public key, and any other system could use that to encrypt a message and send it to system X. Many taps might be on the line, but only system X has the private key that enables decrypting the message again.

Roughly, the following steps are taken to set-up an ssh connection (version 1 and version 2 differ in "details"):

Except for two items, we can forget about all of the above. The two important things are: checking the fingerprint of the server by the client, and the fact that there are several ways of authentication. The fingerprint checking is a one-time semi-scary dialogue. But the autentication has to be setup! The good news is that the default is traditional password authentication. The bad news is that setting up one of the other means is relatively complex.

Password authentication is the same in ssh as it is in telnet. The client machine provides the server with a password (entered by the user), and the server authenticates the user using its internal password-checking routines based on /etc/passwd. The remote server checks the password, which means the password needs to travel over the connection from client to server. With ssh, the connection is encrypted, so this is secure. However, the password must be manually entered, which makes this unsuitable for automated processes, lazy people or the paranoid ones that fear keyboard sniffers.

Key-based authentication works differently. It is a system where every user has a public and private key. The public key is distributed to every server the user wants to connect to. The private part is kept private (on a secure laptop, or on removable USB flash disk if the user wants to work on multiple clients). Usually, the private key is stored encrypted, protected by a passphrase (which is just another term for password, but it should not be confused with the password in the "password authentication" scenario). Note that neither the private key nor the passphase used to encrypt it ever leave the client machine. Ssh takes this one (optional) step further: a key manager (agent) handling key requests. If the user is running an agent (having entered the passphrase once) then the user is never prompted at all, and authentication is transparent, but no less secure.

Host based authentication does not require users to authenticate. Rather, servers list which client machines they trust (ip numbers or dns names) and which users they trust (user names as managed by the client machine). This means that there is a file on the server (typically .rhosts) where each line contains two names, a client machine name and a user name. Host based authentication is a security danger in that it does not require interactive authentication and is therefore strongly discouraged. OpenSSH with host-based authentication only improves security from the encrypted channel standpoint - it does not lessen the inherent security risk which authentication-less access creates!

5.2. Password authentication

Let's download an ssh client: putty seems to be the favorite. When running it, an impressive dialog is started with many faces (selectable on the left). Each "face" has many settings (where to log, how to backspace/bell, window size, cursor style, font colors, proxies, tunnels) that are typically saved under a session name on the first "face" appropriately called Session.

Running putty for the first time: one must enter host name and protocol (red), and optionally one may save this session (blue).

We start simple. We make a session to host 'Nas' and port 'SSH' (in red) and save that under session name "Nas" (in blue). After pressing "open" the very first time, we get a warning from putty. This is the check if the host that responds is indeed the intended host. recall from the install of openssh, that three fingerprints were listed (used in various scenario's). The one used now is the one that I colored blue above.

The warning from putty, but the fingerprint matches the one from the server.

Since the fingerprint matches (the blue output when installing openssh), we'll press "yes".

Our first ssh login.

We're in!
It's that simple.

5.3. Key-based authentication

Not yet tried.

5.4. Host based authentication

In general, host based authentication should not be used. As a result, it's hard to find easy documentation of how to set it up, so I had this urge to get it running. Both the client and the server should be set-up correctly. Note that for this exercise, I used my Nas both as client and as server.

Settings on server for user maarten

Per user, the server should be configured correctly. I'll take myself as an example.

Settings on server for sshd

The server has a one-time setup for host based authetication

Settings on a client

On the client side (recall: also the Nas) I have

Looking back

I'll be honest, I don't use the "Host based authentication" but stick to the simple "Password authentication". My Nas is the server, putty on a PC my client. What's worse, it was a nightmare to get host based authentication running. The following helped. For the purpose of testing, on the server run:

# /opt/sbin/sshd -d -p 3333

and on the client (logged in as 'maarten'):

% ssh -p 3333 -v Nas /bin/date

5.5. Tunneling

Ssh is able to act as a tunnel, for amongst others tcp/ip connections. What this means is that one choses a fresh port on the client that must be securely tunneled by ssh to some port on the server.

For example, let us try to access the web interface of the Nas via an ssh tunnel. This is helpfull since it allows us to remotely login as administrator with sending our password in the clear over the internet. On the remote (the Nas), the service (web interface) sits behind port 80. We pick a free port on the local (the PC) say 3456. And we configure the ssh client so that messages to local port 3456 are forwarded to remote port 80.

To add a "Forwarded port" to our session enter the following three fields: forward local port 3456 to destination Nas:80 (a host name followed by a colon and a port number on the host) and then press Add. The forwarded port "L3456 Nas:80" is added to the list (one session could have multiple forwarded ports).

After the tunnel definition, we connect to the remote in the usual way.

With that session, simply do an ssh login.

We can inspect the event log to confirm that a tunnel is being maintained by ssh.

Confirm (ctrl-right click, or press system menu) by searching the event log for a port forwarding.

But the proof of the pudding is in the eating. On the local PC, we now browse to our own PC (localhost) and port 3456.

By browsing the local port 3456, ssh tunnels the http requests through a secure tunnel.

And we're in. The tunnel is working.

Below this line is under construction

6. Some work to do, some open issues

6.1. Misc

What does the log_server.cgi link on the hidden /Management page do? I do not see much in my syslog server running on my PC.

Getting TwonkyVision

Goto enter e.g. 'ssh' and 'Search on: Package name and description' (see screenshots)

# smbmount //pc2/Gate /share/pc2 -o username=guest,password=""
Still to do... (remove telnet, add ftp server)

6.2. Disk with spin-down

I want spindown of the HD when it is not used for a while. I tried removing the disk from the USB box, putting it in my PC, booting with knoppix, running hdparm -S5 /dev/hdb. This switched of the disk after 25 seconds. Hoever, after booting, the -S5 option was lost. The Hitachy Feature Tool mentioned on the nslu2 wiki, had the standby feature grayed out.

In december 2006 I bought a '_digiconnect portable 2.5" hard disk drive' at aragorn (18.05). I also bought a pretty expensive harddisk to go with it. It is a HTS548060M9AT00 (2.5" 60G Travelstar) from Hitachi for 97 at computerland. Via marktplaats, I bought a 3.5" to 2.5" ide convertor. The whole idea was to get a drive that would spin down. Unfortunately, the drive doesn't do what I expect it to do (spin down wise). In any of the APM modes 0..7F ("Standby") it spins down after 20 seconds, and in modes 80..BF ("low power idle") or C0..FE ("active idle") it does not spin down. One positive aspect is that (altough power consumption over USB exceeds the 500mA during spin up – my laptop refuses it) the NSLU2 is able to power it without an external power supply.

6.3. Memory map

cat /proc/mtd

Running 'cat /proc/mtd' on R24 produces the following output.

  dev:  size       erasesize name
  mtd0: 0004.0000  0002.0000 "RedBoot "
  mtd1: 0002.0000  0002.0000 "System Configuration"
  mtd2: 0010.0000  0002.0000 "Kernel"
  mtd3: 006a.0000  0002.0000 "Ramdisk"

Sizes: 4.0000+2.0000+10.0000+6a.0000 = 80.0000(hex) = 8M(dec). Note that the firmware bin file is 8M.

Memory map

The Info/MemoryMap of the wiki provides the following CPU memory map

  Physical Addr  Size (MB)  Description
  0x00000000        32      SDRAM (cached) [The lowest 256MB is configurable]
  0x10000000        32      SDRAM (alias)
  0x20000000        32      SDRAM (uncached)
  0x48000000        64      PCI Data
  0x50000000        16      Flash (CS0)
  0x51000000       112      CS1 - CS7
  0x60000000        64      Queue Manager
  0xC0000000         1      PCI Controller
  0xC4000000         1      Exp. Bus Config
  0xC8000000         1      Misc IXP425 IO
  0xCC000000         1      SDRAM Config

So, the flash starts at 0x5000.0000, and SDRAM at 0x0000.0000.

RedBoot load

load -r -v -b 0x01000000 NSLU2_V23R25.bin

  -r           Boolean  Raw (or binary) data
  -v           Boolean  Display an indicator while the downloading
  -b location  Number   Address in memory to load the data.
                        Formatted data streams will have an implied
                        load address which this option may override.

Let us assume that NSLU2_V23R25.bin is a plain binary file whose layout is the same (using padding to give the blocks a fixed size) as the 4 blocks the resulting from /proc/mtd on R24.

Since NSLU2_V23R25.bin is loaded at base 0x0100.0000 we get the following memory map in SDRAM "buffer":

  start     size      name
  0100.0000 0004.0000 "RedBoot "
  0104.0000 0002.0000 "System Configuration"
  0106.0000 0010.0000 "Kernel"
  0116.0000 006a.0000 "Ramdisk"

So, after 'load' the SDRAM contains an image of NSLU2_V23R25.bin. At 0106.0000 starts the kernel and the ramdisk. These two block together have size 7a.0000.

RedBoot fis write

fis write -f 0x50060000 -b 0x01060000 -l 0x7a0000

fis write {-b mem_address} {-l length} {-f flash_address}
 -b mem_address    Number  Address of data to be written to flash.
 -l length         Number  Length of data to be writtem.
 -f flash_address  Number  Address of flash to write to.

The -b and -l options are explained by the SDRAM memory map above. The -f option is explained by the flash starting at 0x5000.000 from the CPU memory map.

  Flash start  RAM start  size       name
  0x5000.0000  0100.0000  0004.0000  "RedBoot "
  0x5004.0000  0104.0000  0002.0000  "System Configuration"
  0x5006.0000  0106.0000  0010.0000  "Kernel"
  0x5016.0000  0116.0000  006a.0000  "Ramdisk"
  0x5080.0000  0180.0000

Reset system configuration

In the "HowTo ResetSysConf" we read

  You can force the NSLU2 to recreate the SysConf area by erasing
  it from RedBoot. Follow the instructions to TelnetIntoRedBoot and
  then type the following in:
  fis erase -f 0x50040000 -l 0x20000

This howto matches our mental model.


The Info/BootFlash on the wiki explains

The Flash memory is partitioned into 4 "/dev/mtdblock" devices:

  Linux device   Type     Start addr Length   Description
  /dev/mtdblock0 RedBoot  0x50000000 0x03FFB0 Code from which the IXP420 boots.
                 MAC Addr 0x5003FFB0 0x000006 MAC address for NPE0 is stored here.
                 Unknown  0x5003FFB6 0x000004 Unknown
                 Trailer  0x5003FFBA 0x000046 Sercomm RedBoot trailer
  /dev/mtdblock1 SysConf  0x50040000 0x020000 NSLU2 config (eg IP address)
  /dev/mtdblock2 Kernel   0x50060000 0x100000 The Linux kernel
  /dev/mtdblock3 Ramdisk  0x50160000 0x69FFF0 The ramdisk image for /
                 Trailer  0x507FFFF0 0x000010 Sercomm flash trailer

6.4. Writing to flash?

I ssh-ed to my slug. Then I did 'cd /initrd' en 'touch POEP'. I executed 'sync' and 'reboot'.

Next, I did another ssh, en POEP was still in /initrd.

Now for the real work: a 'halt', unplugged the HDD, and switched on the slug. Via webinterface I enabled telnet, loged-in with root/uNSLUng. The /initrd is empty.

But! In / there is a file POEP.

6.5 Studying Twonky Vision

From a mail exchange with Tim.
>Having looked at the scripts used by NASSetup I can see that they enable
>Telnet on their own (no need to go to /Management/telnet.cgi in the NSLU2
>GUI). They use the default username (root) and password (uNSLUng), which
>explains why no drive can be attached.  Then they appear to use FTP to do
>other stuff, and several scripts are employed (this is all way over my

I guess that NASSetup is some sort of script interpreter that twonky wrote
with some nslu2 specific commands. NASSetup presumably executes install.nas,
which has the nslu2 specific 'ENABLE TELNET'. It then logs in (indeed with
the uNSLUng password), stops the twonky server (I guess they kill the processes
using 4 different names -- names that have been used in the past for their
media and/or music servers), remove the executabels (again 4 tries), then
create the directories where the twonky stuff is stored (/opt/etc/init.d),
and then they upload four executables in /opt ( [see below],
twonkymedia [the twonky server], lame [mp3 encoder probably for on-the-fly
conversion of internet radio to mp3], jpegscale [probably a run-time scaler
to addapt big jpgs to a tv screen resolution]). The last thing the NASSetup
does (the windows pc does!) is to tell the nslu2 to execute the
(so that script is not run by the pc but by the nslu2!).
This ends the install.nas script.

What does the script do? Its a plain unix shell script.
On the first line it defines the name of a file (yet another script) that
will startup the twonky server: /opt/etc/init.d/S99mediaserver.
The next line is a very criptic but also powerfull script trick.
The lines from 'cat < /dev/null
  /bin/mount -t vfat /dev/sdb1 /share/flash/data > /dev/null

  route add -net netmask dev eth0 2>/dev/null

  chdir /opt
  /opt/twonkymedia -D
are directed (copied) to that startup script. So, the startup script is
generated in /opt/etc/init.d (I believe that when linux boots, it runs all script
in /opt/etc/init.d, starting with the lowest numbers first). The next line makes
the script indeed executable.
Then there is another example of the criptic trick: the ini-file in generated
for twonky (/opt/twonkyvision-mediaserver.ini). Then a copy is made for the
music server (/opt/twonkyvision-musicserver.ini). Finally, the twonky server
startup script is executed (prevents a reboot of linux).

So, this looks understandable.

And this look like something I would do on an unsling system.
Would this work on an non-unsling system?
I'm not sure.
On a non-unsling system, linux uses the RAM disk as root filesystem
(which is created by extracting the flash to a ram disk upon startup).
The script creates the crucial script /opt/etc/init.d/S99mediaserver.
I'm not sure whether this ends up in the flash and not just the ram disk.
If it ends up on the ram disk only, it will not be there after a reboot.
Have you tried this?

>Insofar as "unslinging" (I say the following to seek confirmation from you),
>my impression is at this point that the "uNSLUng community" considers this
>essential so that multiple apps can be installed, scripts run, and other
>Linux operations performed.  When TV support calls it optional I think they
>mean that if you don't want to use NASSetup and install TwonkyMedia ("TM")
>in RAM, then go the unsling route and install TM manually onto the hard
>In other words, "unslinging is optional" in this case is short for "take a
>whole other approach to installing and using TM."

Possible cases:
(1) NASSetup (actually copies the crucial script (S99mediaserver) to
/opt/etc/init.d which is on the ram disk. After a reboot of the nlsu2 it is gone.
But running NASSetup puts it back and active. The media data would reside on the harddisk anyhow!

(2) NASSetup (actually copies the crucial script (S99mediaserver) to
/opt/etc/init.d which somehow is actually in the flash memory. After a reboot of
the nlsu2 the flash is remounted and the script is started, restarting twonky
(accessing the media on the harddisk).

(3) NASSetup (actually copies the crucial script (S99mediaserver) to
/opt/etc/init.d which is on the harddisk (this is another way of saying,
the system is unsling). After a reboot of the nlsu2 the harddisk is remounted
and the script is started, restarting twonky.

>Would even make any sense to unsling the system AFTER using NASSetup and
>installing TM in RAM??
If (1) is the case, the setup is lost, but after rerunning NASSetup it would
be parmanent.
If (2) is the case, the crucial script would be copied by the unsling process
(because that copies the whole flash image to tha harddisk).
If (3) is tha case, you're already unsling, and a second unsling doesn't harm
(is my understanding :-).

>About the TM database. I wrote them back this morning asking how to do this
>but perhaps you can tell me.  At the moment one of my test NSLU2's has TM
>installed in RAM
what do you mean here?

> and the hard drive was freshly formatted by the NSLU2. It
>has just two folders on it: "Admin 1" and "Disk 1". Inside of those I see no
>database so I am baffled about how to find much less move the database. I
>had hoped/assumed that TM might create the database on the drive
>automatically, perhaps at a location one enters in its GUI configuration but
>as yet I've found nothing about this.  Any suggestions?
The script script makes a default ini file for the server
(/opt/twonkyvision-mediaserver.ini). We see in the ini file
so this seems to me the location of the database.

What you have to know here is that unix/linux has the notion of a "root file system"
that may have some subdirectories corresponding to harddisks (any disk can be "mounted"
on any subdirectory of the file system -- read my website of examples).
The nslu2 typically mounts disks in /share.

The second thing you have to know is that the nslu2 has confusing names for the disks!
the first disk is mounted in subdirectory hdd (so "ls /share/hdd" gives the content
of the disk in usb port 1), the second disk is mounted in flash (so /share/flash).
What you refer to as "Disk 1" is actually the name under which the samba file server of
the nslu2 shares /share/hdd/data/public (i.e. the subdirectory /data/public on the
harddisk in the first usb slot). This is all pretty complex isn't it? That's why I've
written my webpage documenting my findings -- this was all new to me.

Bottom line, the media server looks by default for its database on the harddisk connected
to the second usb port! Change /opt/twonkyvision-mediaserver.ini if you want it differently.

I've not played much with twonky yet, but I believe that once the server is running
you can connect to it with a webbrowser and configure it from there (hopefully,
the server will modify the ini file for you, when you fill out the webform).
I would guess that connects to the webserver of twonky
(where is the ip address of the nslu2, it may be different for you;
the 9000 is the port I fond in the ini file).

>One other question I have is about the use of paths in this situation.
>Their GUI says the default search path for "media" (photos, music, etc.) is
>"/share".  I think I've figured out that this really just means "any and all
>drives attached to the NSLU2" and is not a specific folder.
It seems you're right.
The ini file reads
and as I explained above, the nslu2 uses the /share directory as the place to mount all its disks.
You could change this to

mail to Maarten


Maarten Pennings
Last change:
8 june 2007