skynet

Skynet/Link32

Link32 is a tactical communication protocol inspired by VMF, LINK16, TSM, SRW, and MQTT, designed for military applications requiring low-latency, secure, and scalable data exchange in contested environments. It supports swarm coordination, real-time position location information (PLI), command and control (C2), and tactical chat over UDP-based multicast networks.

Skynet is the reference server implementing Link32 tactical battlefield protocol implemented in pure C99 with a single OpenSSL dependency (to be replaced in real applcations).

Properties

Principles

Link32 Protocol

S-Message Format

The Skynet Message structure is compact, designed for swarms of thousands of nodes:

typedef struct {
    uint8_t version : 4;         // Protocol version (current: 1)
    uint8_t type : 4;            // Message type (0-6)
    uint8_t qos : 4;             // Quality of Service (0-3)
    uint8_t hop_count : 4;       // Hop count for routing (0-15)
    uint32_t npg_id;             // Topic identifier (1-103)
    uint32_t node_id;            // Sender node ID (FNV-1a hash)
    uint32_t seq_no;             // Sequence number for deduplication
    uint8_t iv[16];              // AES-256-GCM initialization vector
    uint16_t payload_len;        // Payload length (0-32767)
    uint8_t payload[MAX_BUFFER]; // Encrypted payload + 16-byte GCM tag
} SkyNetMessage;

Message Types

Id Type Description
0 Key Exchange Exchanges ECC public keys for ECDH session setup.
1 Slot Request Requests a TDMA slot from the server.
2 Chat Sends tactical chat messages.
3 Ack Acknowledges slot assignments or other control messages.
4 Waypoint Specifies navigation waypoints for C2.
5 Status Reports position, velocity, or sensor data (e.g., PLI).
6 Formation Coordinates swarm formations.

Multicast Topics

NPG Name Multicast Purpose
1 npg_control 239.255.0.1 Handles key exchange and slot requests for network control.
6 npg_pli 239.255.0.6 Processes status messages for position information .
7 npg_surveillance 239.255.0.7 Forwards status messages with sensor data to subscribers.
29 npg_chat 239.255.0.29 Relays chat and ack messages for tactical communication.
100 npg_c2 239.255.0.100 Processes waypoint and formation messages for C2.
101 npg_alerts 239.255.0.101 Status messages for network alerts and self-healing.
102 npg_logistics 239.255.0.102 Handles status and chat for logistical coordination.
103 npg_coord 239.255.0.103 Relays chat, waypoint, and swarm coordination.

Slot Management

Link32 uses a minimalistic Time Division Multiple Access (TDMA)-like slot manager to reduce message collisions and emulate dynamic topics:

Implementation details:

Deduplication

To prevent message loops and duplicates, the server uses a fixed-size circular buffer seq_cache for deduplication:

Implementation details:

Security

Subscriptions

Nodes subscribe to topics based on their role, joining the corresponding multicast groups:

Role NPGs Subscribed Purpose
Infantry 1, 29 Network control and tactical chat.
Drone 1, 6, 7, 100, 101 Control, PLI, surveillance, C2, and alerts.
Air 1, 6, 7, 100, 101, 103 Control, PLI, surveillance, C2, alerts, and coordination.
Sea 1, 7, 29, 102, 103 Control, surveillance, chat, logistics, and coordination.
Ground 1, 7, 29, 102 Control, surveillance, chat, and logistics.
Relay 1, 6, 101 Control, PLI, and alerts for message relaying.
Controller 1, 6, 100, 101 Control, PLI, C2, and alerts for command posts.

Skynet

Dependencies

Build

$ git clone git@github.com:BitEdits/skynet
$ cd skynet
$ gcc -o skynet_client skynet_client.c skynet_proto.c -lcrypto
$ gcc -o skynet skynet.c skynet_proto.c -pthread -lcrypto

Installation

Link32 deploys via a provisioning script (skynet.sh), which generates ECC key pairs for all network nodes and topics. Public keys must be manually copied to client key stores for mutual authentication.

$ ./skynet.sh
Generated keys for node npg_control (hash: 06c5bc52) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_pli (hash: c9aef284) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_surveillance (hash: 4d128cdc) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_chat (hash: 9c69a767) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_c2 (hash: 89f28794) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_alerts (hash: 9f456bca) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_logistics (hash: 542105cc) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node npg_coord (hash: e46c0c22) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node server (hash: 40ac3dd2) in /home/user/.skynet/ecc/secp384r1/
Generated keys for node client (hash: 8f929c1e) in /home/user/.skynet_client/ecc/secp384r1/
$ cp ~/.skynet/ecc/secp384r1/*.ec_pub ~/.skynet_client/ecc/secp384r1/

Server Operation

The server skynet binds to UDP port 6566, joins multicast groups for all topics 239.255.0.<npg_id>, and processes incoming messages using a global network queue (MessageQueue mq). It spawns worker threads pinned to CPU cores for concurrent message handling.

Each topic has a dedicated subscriber queue topic_queues, and messages are forwarded to slot-specific multicast groups 239.255.1.<slot_id> for dynamic topics.

Example server output:

$ ./skynet server
Node 40ac3dd2 bound to 0.0.0.0:6566.
Joined multicast group 239.255.0.1 (NPG 1: control).
Joined multicast group 239.255.0.6 (NPG 6: PLI).
...
Message received, from=8f929c1e, to=1, size=231.
Decryption successful, from=8f929c1e, to=1, size=215.
Saved public key for client 8f929c1e.
Assigned slot 0 to node 8f929c1e.
Message received, from=8f929c1e, to=6, size=40.
Decryption successful, from=8f929c1e, to=6, size=24.
Message sent from=8f929c1e, to=6, seq=3, multicast=239.255.1.0, latency=36643.

Client Operation

The client skynet_client connects to port 6566, joins topic-specific multicast groups, and sends:

Example client output:

$ ./skynet_client client
Node 8f929c1e connecting to port 6566.
Joined multicast group 239.255.0.1 (NPG 1).
Joined multicast group 239.255.0.6 (NPG 6).
...
Sent key exchange message to server.
Sent slot request message to server.
Received slot assignment: slot=0.
Joined slot multicast group 239.255.1.0.
Sent status message: pos=[0.1, 0.1, 0.1], vel=[0.0, 0.0, 0.0], seq=2, multicast=239.255.1.0.

Usage

Skynet distribution contains 5 binary files.

skynet_keygen <node> [--server|--client]

Generates ECC secp384r1 key pairs for the specified node, storing them in ~/.skynet/ecc/secp384r1/ (server) or ~/.skynet_client/ecc/secp384r1/ (client).

skynet_encrypt <sender> <recipient> <file>

Encrypts a test message from <sender> to <recipient> for the specified NPG, producing <npg_id>.sky.

skynet_decrypt <sender> <recipient> <file.sky>

Decrypts <file> (e.g., <npg_id>.sky) using keys for <sender> and <recipient>.

skynet <node>

Runs the server named as <node>, FNV1A 32-bit hash is used. The server assigns a slot, forwards status messages to 239.255.1.<slot_id>, and logs all activity.

skynet_client <node>

Runs the client named as <node>, FNV1A 32-bit hash is used. The client sends key exchange, slot request, and status messages.

Limitations

Author