The DSM 320

Last updated: 31/05/05

Great hardware, great idea, crap implementation.

On the plus side, it's linux. So lets see about "fixing" it.

Telnet access

You can gain telnet access without installing a new image.

Turn the device off, and once it is off, run this command:

IP=x.x.x.x ping -c 1 -w 60 $IP && echo 'cp /usr/sbin/utelnetd /tmp/telnetd.new &&  /tmp/telnetd.new -p 24 -l /bin/sh -d' | nc $IP 23

Now turn the device back on again.

When the command returns to the prompt, telnet to the DSM's IP, on port 24.

Uploading binaries

So you've got console access - now what? We need a way to copy files to it. There is no wget, or such - so we do it using a rather perverse method.

First, save this simple little program, encode.c:

/* encode.c *(/
#include <unistd.h>
int main()
{
  unsigned char c;
  while (read(STDIN_FILENO, &c, 1) == 1) {
    printf("\\\\%03o\n", c);
  }
}

Then compile it:

gcc -o encode encode.c

On the DSM, run the following:

echo '#!/bin/sh' > /tmp/run.sh
echo 'cat - > /tmp/data.oct' >> /tmp/run.sh
chmod 755 /tmp/run.sh
/tmp/telnetd.new -p 25 -l /tmp/run.sh -d

Back on the machine with the ARM toolchain on, create decode.c:

/* decode.c */
#include <unistd.h>

int main()
{
  char buf[5];
  while (read(STDIN_FILENO, &buf, 6) == 6) {
    buf[5] = 0;
    char * s = buf + 1;
    int c;
    while ((c = *s++)) {
      if (c == '\\' && *s) {
        switch (c = *s++) {
          case '0': case '1': case '2': case '3':
          case '4': case '5': case '6': case '7':
          c -= '0';
          if (*s >= '0' && *s <= '7')
            c = c * 8 + (*s++ - '0');
          if (*s >= '0' && *s <= '7')
            c = c * 8 + (*s++ - '0');
          break;
        }
      }
      putchar(c);
    }
  }
}

Compile, and upload:

arm-linux-gcc -o decode-arm decode.c
arm-linux-strip decode-arm
./encode < decode-arm | nc $IP 25
## Hit ctrl-C when this last line stops oututting anything.

Then run this on the DSM:

while read C; do echo -n -e "$C"; done < /tmp/data.oct > /tmp/decode
chmod 755 /tmp/decode
echo '#!/bin/sh' > /tmp/run.sh
echo '/tmp/decode > /tmp/a.out' >> /tmp/run.sh
echo 'chmod 755 /tmp/a.out' >> /tmp/run.sh
chmod 755 /tmp/run.sh
    

You are now in a position where you simply use the encode method above to send binaries to the DSM, and they appear as /tmp/a.out. I've not quiet worked out why netcat needs a ctrl-c when it's finished sending - but it seems to work so doesn't bother me.

More playing...

After spending a couple of hours playing with the device, a lot of information has been gleaned. First up, i rekon it's going to be fairly easy to get the device running new software for menuing, displaying images, playing movies and music, etc.

I'll document everyhtign there as and when i get time to play for a few horus here and there.

So far, i've discovered:

  • The device uses UPnP internally over loopback to control the rendering process (Get/Set Position, fast forward, rewind, etc). This is good, as it means we can write a remote client to control it directly even if we don't write our own software.
  • To display static images, simply copy into memory, then call ioctl(fd[/dev/mdx.a], 0x9fff9fff, &ptr) - where ptr is a pointer to the image in memory.
  • The screensaver is simply a static image randomly moved around the screen. No reason why you couldn't make it something more funky though.
  • Remote Control is simply reading from /dev/irda.
  • Streaming video/music is also fairly simple. Open /dev/mdx.a, call a couple of ioctl()'s (not worked out exactly what yet), then feed stream in. this means we can write some sensible buffering, and add some more supported protocols (RTSP would be nice).