⟵ Home

Tickling a Sun Ray 2 - It Speaks!

December 15, 2025 ∙ 11 minute read

This is the second post on a series I’m working on, regarding the black-box reverse-engineering of a Sun Microsystems Ray 2 Desktop Unit. The first post can be found here: Tickling a Sun Ray 2 - DHCP Discovery.

New Findings

In the last post, I mentioned that I had omitted a few DHCPACK and DHCPINFORM packets, assuming they weren’t particularly important. My DHCP knowledge is a bit rusty, and I naïvely thought: “DHCPINFORM? The client already has an IP. No big deal.”

That assumption was completely wrong.

What was actually happening is that the Ray was requesting someone to inform it about some knobs so it could finish bootstrapping and start the boot sequence! That should have been obvious, especially given that it was retrying the same packet over and over since no one was answering it, but yes, I missed that. Oops!

Now, back on track. The packet clearly indicated what it was looking for:

The choices there are interesting indeed! MTU makes sense, but, XDM? Odd at least.

At this point, we know that:

Looking for some information on the Web I could find some piece of documentation that Oracle haven’t burned yet, and oh my, it’s telling. For pure archival purposes, I’m mirroring it here: Sun Ray Client Initialization Requirements Using DHCP, but what’s interesting there is the Alternate Vendor-Specific DHCP Options section, listing exactly what we need. The response for the DHCPINFORM SHOULD carry a bit of extra information in the Vendor-Specific Information TLV, but the Ray could piggyback on “Standard” DHCP Options, if your DHCP server didn’t support them. Clever, very Sun-ish.

What’s relevant for us is this: We could add a Vendor-Specific Information to the DHCPACK of the DHCPINFORM packet, and the Ray would just use it. And we also have A LOT of knobs that can be turned. Below is a quick summary:

Lots of interesting stuff, but let’s begin with what can really help us: Logging. It seems the Ray is capable of emitting log data to a Syslog server, and we can set the level for several facilities, including firmware application, network, and kernel! That’s just awesome! Thanks, Sun!

Now, given it wants a Syslog server, one can assume that the log levels are also standardised to the levels Syslog supports, and one would be absolutely right. From RFC 3164 - The BSD syslog Protocol, page 9 contains Table 2. syslog Message Severities, listing from 0 (Emergency) up to 7 (Debug). I think the box may use 6 (Informational) as default, so setting it to 7 may make it be more chatty!

Encoding Vendor-Specific Information

The archived page also explains with less-than-desired details the encoding format, but it’s nothing more, nothing less than a plain old TLV structure. Adorable!

The structure is composed of repeated TLVs: one byte for the tag, one byte for the length, followed by n bytes of value. The only important thing to keep in mind is that any IP type is a simple representation of the IP octets, meaning that 192.168.100.1 becomes 0xC0, 0xA8, 0x64, 0x01.

Now let’s make the Ray talk to us through syslog, and make it chatty. The DHCP Option payload for Vendor-Specific Information would then be:

I don’t want to bring up a full syslog daemon, so listening to UDP port 514 is enough.

And surely, we got the little box to talk with us:

[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Network: soff 0 n 1
[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Network: GetNextAltAuth 0 0 0
[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Application: Stop tokens 8009df20
[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Application: sessionMonitor TcpOpen timeout to 0.0.0.0:7009
[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Network: soff 0 n 1
[syslog from 192.168.100.50:514] <15> 0x0.0x48b 0:14:4f:85:f2:b Network: GetNextAltAuth 0 0 0
[syslog from 192.168.100.50:514] <15> 0x0.0x873 0:14:4f:85:f2:b Application: getNextServer: no message - timeout

Gorgeous! It can talk, and the log levels do map cleanly to syslog severities. That <15> is a PRI value in the syslog protocol, obtained by (facility * 8) + severity, as defined by the spec. Working backwards:

15 / 8 = 1 remainder 7

Meaning:

The Authentication Server

It seems to be trying to do something, but failing. That’s expected, since the essential value is still missing from the Vendor TLV: AuthSrvr. It’s even marked as mandatory! One funny detail about that table is that, although the BarrierLevel is also marked as mandatory, the client continues the process normally. More on that later.

Now let’s set the AuthSrvr value. It’s the same as LogHost, but with a different tag:

After updating what’s mimicking the DHCP server the Ray expects and adding the potentially last flag it wants, we have new stuff on the syslog!

[syslog from 192.168.100.50:514] <15> 0x0.0x1e9 0:14:4f:85:f2:b Network: GetNextAltAuth 0 c0a86401 0
[syslog from 192.168.100.50:514] <15> 0x0.0x1e9 0:14:4f:85:f2:b Application: Stop tokens 8009df20
[syslog from 192.168.100.50:514] <15> 0x0.0x1e9 0:14:4f:85:f2:b Application: sessionMonitor TcpOpen timeout to 192.168.100.1:7009
[syslog from 192.168.100.50:514] <15> 0x0.0x1e9 0:14:4f:85:f2:b Network: GetNextAltAuth 0 c0a86401 0
[syslog from 192.168.100.50:514] <15> 0x0.0x1fd 0:14:4f:85:f2:b Network: GetNewtBandwidth: status down speed 100000000 mode full

There’s one little thing that may catch your eye: Application: sessionMonitor TcpOpen timeout to 192.168.100.1:7009. TCPOpen? To the IP of the AuthSrvr? Port 7009? That’s oddly familiar! We had a mysterious UDP packet going to that port in the last post!

The Mysterious serverQ

To be honest, serverQ was a dead-end. I couldn’t find any references on what it means, how it should respond, and why that happens. But hey! Now we have the Ray trying to open a full-fledged TCP connection with us! I mean, it’s trying, and that’s progress! I’m calling this out explicitly because the previous post ended on a bit of a cliffhanger, and I hate those as much as you probably do. For now, serverQ remains unexplained, but it no longer blocks progress.

Moving on!

A Sun Ray walks into a bar…

Since the Ray wants to speak, let it speak! Let’s spin a TCP server listening on port 7009 and dump whatever we get there. Here’s a few bytes of output from the hacky TCP server:

DummyAuthSrvr: 696e666f526571204d54553d31353...

For the well-trained eye, that hex looks an awful lot like an ASCII blob. And guess what? It is! Here’s the ASCII version of it:

infoReq MTU=1500 _=1 barrierLevel=310 cause=insert clientRand=nrlifRNCnn4xe.F5Be/DA7gkwFF9cOXQOmxxzu8SM3e ddcconfig=1 event=insert firstServer=c0a86401 fw=MfgPkg_4.15_2006.07.20.16.57 hw=SunRayP8 id=00144f85f20b initState=1 namespace=IEEE802 pn=53622 realIP=c0a86432 sn=00144f85f20b startRes=1400x1050:1400x1050 state=disconnected tokenSeq=1 type=pseudo

And that’s A LOT! Holy guacamole!

Let’s try to break it up:

Then, it immediately sends another packet:

DummyAuthSrvr: 6b656570416c697665526571205f3...

Again, more ASCII:

keepAliveReq _=1 fw=MfgPkg_4.15_2006.07.20.16.57 hw=SunRayP8 namespace=IEEE802 pn=53622 sn=00144f85f20b state=disconnected

And we have more details now!

  1. Seems like we have another operation: keepAliveReq
  2. pn is the same across both messages. Possibly not a packet number!
  3. Everything else stays the same.

Since we’re not answering after that point it just eventually times out and retries:

[syslog from 192.168.100.50:514] <15> 0x0.0x16ca1 0:14:4f:85:f2:b Network: TcpReceive: FIN received 805bdd78 1
[syslog from 192.168.100.50:514] <15> 0x0.0x16ca1 0:14:4f:85:f2:b Application: restartAuth
[syslog from 192.168.100.50:514] <15> 0x0.0x16ca1 0:14:4f:85:f2:b Network: TcpClose: 805bdd78
[syslog from 192.168.100.50:514] <15> 0x0.0x16ca1 0:14:4f:85:f2:b Application: TcpClose1 failed
[syslog from 192.168.100.50:514] <14> 0x0.0x16ca1 0:14:4f:85:f2:b Network: FreeTcb:Freeing Tcb before the connection is closed

It’s not rebooting, though. Only restarting the authentication phase. It may be worth noticing that whenever it retries, even without rebooting both clientRand and pn changes, but everything else stays the same. There’s one small detail, though! Here’s a new detail in syslog:

[syslog from 192.168.100.50:514] <13> 0x0.0x544 0:14:4f:85:f2:b USB: rdd: unable to contact device manager on 192.168.100.1:7011  retrying

It’s ALSO trying to establish a connection to port 7011! Looking at my packet dumps, it tried to open a TCP connection to that port. Let’s also see what happens if we let it! It seems to be something called a Device Manager, so let’s do the same we did with the AuthSrvr:

DummyDeviceManager: 636f6e6e6563740a
[syslog from 192.168.100.50:514] <15> 0x0.0x1f270 0:14:4f:85:f2:b Network: TcpClose: 8059c538
[syslog from 192.168.100.50:514] <15> 0x0.0x1f270 0:14:4f:85:f2:b Network: TcpReceive: FIN received 8059c538 8
[syslog from 192.168.100.50:514] <14> 0x0.0x1f2d8 0:14:4f:85:f2:b Network: TCBDaemon: packet receive error
[syslog from 192.168.100.50:514] <14> 0x0.0x1f33c 0:14:4f:85:f2:b Network: TCBDaemon: packet receive error
[syslog from 192.168.100.50:514] <14> 0x0.0x1f3a0 0:14:4f:85:f2:b Network: TCBDaemon: packet receive error
...

Yeah, it’s not happy. Again, an ASCII payload. This time it only says connect, followed by a newline.

Eventually it will close the connection and send another connect, while the AuthSrvr continues receiving keepAliveReq.

For now, that’s it. I’ll eventually rewrite the C stuff in Golang just for the sake of it, and keep it updated in a Git repository. This way we can isolate the AuthSrvr, Device Manager, and the hacky DHCP server in a single place.

I said I hate cliffhangers, and I meant it, but unfortunately the Sun Ray just gave me a really good one.

In the next post, we’ll respond to its requests and see what happens when we get it wrong.