This is a follow-up to my last post, where I talked about my efforts to reverse engineer the protocols used in the Outernet L-band signal. Here I will describe the L3 and L4 protocols that are used in Outernet.
This description is solely based upon my reverse engineering efforts. As there is no documentation available for this protocols, I get to name them as I like. Also, I’ll describe the protocols just from how they appear to work. Probably the developers at Outernet had something a bit different in mind. In any case, my understanding of how the protocols work seems quite good, as I have now a functional file receiver called free-outernet. In my next post I’ll talk about how the Outernet time service and file service work.
I would like to thank Scott K4KDR, Jerome F4GMU and Primesh Pinto for sending me KISS recordings of Outernet frames, done with gr-outernet.
In my previous post, I speculated with the possibility that the Outernet frames are Ethernet L2 frames (without the CRC-32 at the end). Now I’m pretty sure about this. The packets recorded by Jerome from Alphasat (the satellite broadcasting Outernet over Europe and Africa) have an origin MAC of 00:30:23:90:01:05
, which is a valid MAC with an OUI assigned to Cogent Computer Systems, Inc. Recall that the frames broadcast by I-4 F3 over the Americas have an origin MAC of 00:30:18:c1:dc:a8
, which corresponds to Jetway Information. It seems that these are MACs from real Ethernet cards used in the computer systems at each of the groundstations to send packets to the satellite modem. The ethertype is 0x8fff
, which is an ad-hoc ethertype that indicates the OP protocol.
I call OP (Outernet Protocol) the L3 protocol used for Outernet (pun intended). Since Outernet is a broadcast network, the only function of OP is to provide packet fragmentation, which is used for some packets. The MTU of Outernet is 262 bytes (not counting the Ethernet frame header, as is usual in IP). Thus, fragmentation splits a large L4 packet into chunks of 262 bytes or less.
I call LDP (Lightweight Datagram Protocol) the L4 protocol used in Outernet. It is very similar to UDP (pun intended again). It performs service multiplexing using some kind of port concept and it also does packet checksumming. It seems that there is other L4 protocol that is used in a few of the packets, but I have no clue about what these packets are supposed to do (see below for more information).
The endianness of all the Outernet protocols is big-endian.
OP (Outernet Protocol)
The OP header is 6 bytes long. The first 2 bytes indicate the packet length, not taking into account these 2 bytes. Thus, the maximum (and usual) value of this field is 0x0104
, which indicates a 262 byte OP packet. The next byte serves as a fragmentation flag, but it also seems to indicate the L4 protocol of the payload. Its value is 0x3c
if the packet is the last fragment (also if the whole packet fits in one fragment) and 0xc3
if there are more fragments remaining. However, the weird packets that do not seem to be LDP have a value of 0x69
in all the fragments (they are split in 3 fragments).
I have no clue what the fourth byte in the OP header is. Its value is always 0x02
, except in time service packets, where it is 0x00
.
The fifth byte in the header indicates the fragment number of the last fragment, so for instance its value is 0x00
if the packet is not fragmented or 0x05
if there are a total of 6 fragments. The sixth byte is the fragment number of this fragment. It increases from 0x00
until are fragments are sent. Since Outernet frames are always transmitted in order, fragmentation is much simpler than in the IP protocol.
LDP (Lightweight Datagram Protocol)
An LDP packet has a 6 byte header, then the payload and finally a 4 byte checksum. I haven’t reverse engineered the checksum yet, but it should be easy to do. Recall that L2 frames are protected by the CRC-16CCITT checksum of HLDC, which, while not infallible, provides a good degree of security against errors.
I don’t understand completely how ports are used in LDP. Probably there is a source port and a destination port. However, all the packets corresponding to a particular service always have the same “source port” and “destination port”. Therefore, I call these “ports” fields A and B. In the free-outernet receiver, the service that receives the packet is identified by both the fields A and B. If I would have to guess, I would say that field A is the destination port and field B is the source port, but it seems a bit useless to have a source port in a downlink-only application such as Outernet.
The first two bytes of the LDP header are the A field. The last two bytes of the LDP header are the B field. The third and fourth byte of the header indicate the length of the LDP packet (taking into account the LDP header and the 4 byte checksum). For instance, file blocks are transmitted in LDP packets that have a value of 0x0100
in this field, indicating a 256 byte LDP packet, which is the maximum that can be transmitted without fragmentation with the Outernet MTU of 262 bytes. Larger values can appear if fragmentation is used. For instance, file announcements are transmitted on larger LDP packets that usually take 6 OP fragments.
Worked example
Recall the time service packet from the previous post:
pdu_length = 60 contents = 0000: ff ff ff ff ff ff 00 30 18 c1 dc a8 8f ff 00 1c 0010: 3c 00 00 00 81 00 00 18 01 04 6f 64 63 32 02 08 0020: 00 00 00 00 57 f6 94 20 48 3a ca 8d 00 00 00 00 0030: 00 00 00 00 00 00 00 00 00 00 00 00
This is an Ethernet frame with broadcast destination and source 00:30:18:c1:dc:a8
(the Americas groundstation MAC). The ethertype is 0x8fff
indicating an OP packet. The OP packet length field is 0x001c
, indicating a 30 byte OP packet. Note that the Ethernet frame is longer and padded with zeros. It seems that Outernet has a mTU (minimum transfer unit) of 46 bytes. The OP packet fragmentation byte is 0x3c
, indicating no more fragments. The next byte indicates that the last fragment is fragment number 0 and the following byte indicates that this fragment is fragment number 0 (as we expect in a small packet without fragmentation).
The LDP packet has an A field of 0x8100
and a B field of 0x0104
. These are the A and B fields that are always used for time service packets. The length field is 0x0018
, indicating a length of 24 bytes, which as you can check, is correct. In unfragmented packets, the value of the LDP length field is always equal to the value of the OP length field minus 4 (for the obvious reason). The payload of the LDP packet starts with the bytes 0x6f 0x64
and ends with the bytes 0xf6 0x94
. The checksum of the LDP packet is 0x483aca8d
(I still don’t know which checksum algorithm is used and which bytes are checksummed).
Weird packets
There are a few packets that do not fall under this scheme. They seem to be OP packets, but the L4 protocol is not LDP (the LDP length field would be incorrect). They are fragmented in 3 OP packets and they use the fragmentation byte 0x69
, which I don’t know how to interpret. Here you have the 3 OP fragments corresponding to one of these packets (the Ethernet headers are not shown):
0000 01 04 69 02 02 00 e9 35 bb 18 03 fc c8 4c c6 04 0010 5f 63 68 36 72 27 db e5 ae 1b e2 5c ea 45 ed fc 0020 d7 9b 09 7e 13 92 13 72 78 3f d0 44 f1 85 15 44 0030 c1 33 e9 58 fc d5 71 64 10 3d cb 30 80 4f 04 b1 0040 78 be c1 6a 98 69 4b 37 87 8d aa b7 77 f6 2a 77 0050 4f 25 19 ae ab 5e 53 ec 8f 69 22 ef 58 50 87 06 0060 67 1c cc ec 07 42 cb 13 e5 77 9a 03 b0 47 35 b4 0070 58 c1 0e c1 ca c0 02 56 aa ab 58 d9 7e bc 02 a9 0080 9a c5 cb 4e 1a a9 99 57 e7 45 4b 00 1c a7 ce 1a 0090 9a c0 25 12 67 ec a6 0b 53 e9 2d bf 4d 87 42 9f 00a0 a7 79 a5 84 5d 2a 14 a8 65 ec 57 d0 a3 8d aa b7 00b0 cc 84 9f 6e ac 93 9a b0 f3 25 34 dd bc e6 db 3e 00c0 e3 86 d7 a6 19 23 ec e8 aa cf 97 b9 f9 5c 6b fb 00d0 7c 16 23 e6 8e a6 af 7a 9e 86 29 e5 b6 1a 9a 69 00e0 bd d3 0f b3 b8 83 a6 81 0a af 5c dd 0b 43 77 27 00f0 3b 34 0b 99 c2 5d 6e cc 2a 81 b6 39 98 b1 e0 d3 0100 97 5e ac bb 9e 11 0000 01 04 69 02 02 01 d4 82 98 43 a6 31 42 30 50 ad 0010 7a d4 77 b2 cb df 30 4e 4b e7 e8 43 d2 69 62 57 0020 c7 92 8b da 7f a8 03 26 4f 6a 61 c4 0e 35 98 23 0030 4f 7c 04 9d ef 3c 54 4e 5c 24 c4 d2 95 1f 6a cf 0040 09 0c d1 30 82 8d 0d b8 85 5d ee 8f f8 b5 49 66 0050 b3 27 10 82 bc d6 2a de 69 5d 00 be 80 e6 d3 e2 0060 53 7b 24 e3 4b ef 10 2b a1 b0 18 20 14 f1 36 bc 0070 97 a2 6d e2 c0 30 41 09 49 c3 1b f5 90 af 5f 54 0080 1c cc 59 53 c6 f3 e4 71 08 4a 72 19 ed 74 c0 f6 0090 25 26 34 80 73 a7 3c 94 ca 6f 26 9e 83 2b ce de 00a0 68 3d fd 78 fc 53 7d b0 8a 6f e9 29 5d 4b de a9 00b0 72 d9 a5 69 5b 88 66 94 48 3e 89 44 02 6c 48 2f 00c0 e7 98 19 9a b7 59 c4 ba 73 03 8e 58 76 55 b4 a6 00d0 3a 2b b5 2b 17 f1 cd c4 4a 89 bb 53 ff 48 83 93 00e0 f7 ed 50 11 be 77 54 a7 c9 9b 67 43 37 09 55 2a 00f0 02 5a 1e 7e 8f a0 8c 9c 61 ab f4 16 85 24 f2 1c 0100 9e dc 47 70 f3 01 0000 01 04 69 02 02 02 85 c5 2e 01 aa f4 95 1e ca a7 0010 38 74 46 d0 2c 71 b0 f1 90 33 fd eb d7 18 ea fc 0020 96 d2 35 1d f6 92 77 17 e5 72 1a 62 2e 2c 8b 1f 0030 a2 f1 67 00 74 e1 e5 a6 4d 93 c9 17 7f 4b 64 fb 0040 42 0a 9c e6 2f af 33 05 60 72 cf 31 2b 79 a1 77 0050 06 70 e5 c7 51 df 2f 0d 41 fa 5e a4 ca 6b cd 7b 0060 9e a0 9e 3d e0 3b 61 dd 7e 69 4d 39 ba 4f 03 c0 0070 63 43 ac c1 73 be d7 16 3a b2 4e ed e1 bb 57 10 0080 e0 c2 2e ee bc 09 c2 05 b5 cb 5f da 8a a8 5c 4e 0090 53 d2 67 b8 46 36 20 bd 39 0c c4 ce dd 1e da ed 00a0 6f 7c 27 c1 32 58 c6 bf 86 b4 4c 50 c0 9f 4a 64 00b0 fd ff 88 36 0d 03 30 75 0a 5d 9e c7 9d 71 6c 38 00c0 8d b6 1c 43 be 74 98 57 68 1b 25 ec a1 15 98 40 00d0 30 aa 66 11 5b 51 dd 0f c1 b0 34 63 21 5b f9 ef 00e0 a0 0f b6 ca bd 37 29 bb fd 01 dc 35 83 de 92 29 00f0 2a be 29 30 09 63 ba da a3 26 b6 a1 b7 5c 58 74 0100 79 d8 57 05 df 7b
They seem to be transmitted always after a file announcement, before the transmission of the file blocks starts. I don’t know what they are, but they don’t seem very important.
2 comments