# SecLink Proxy -- Linux Serial Bridge

Linux-hosted proxy that bridges an emulated DOS serial port to a
remote telnet BBS. Part of the DVX GUI project.

The DOS side communicates using the SecLink protocol (HDLC packet
framing, CRC-16, DH key exchange, XTEA-CTR encryption). The BBS side
is plain telnet over TCP. All crypto is transparent to the BBS -- it
sees a normal telnet client.


## Architecture

```
DOS side (terminal app)                           Remote BBS
       |                                              |
  emulated modem                                  telnet
       |                                              |
    TCP:2323                                       TCP:23
       |                                              |
       +--- secproxy ----------------------------------+
            secLink <-> plaintext
            (encrypted, reliable)
```

The proxy accepts a single TCP connection from the DOS side, performs
the SecLink handshake (Diffie-Hellman key exchange), then connects to
the BBS. All traffic between the DOS side and the proxy is encrypted
via XTEA-CTR on channel 0. Traffic between the proxy and the BBS is
unencrypted telnet with IAC negotiation handling.


## Usage

```
secproxy [listen_port] [bbs_host] [bbs_port]
```

| Argument      | Default      | Description                      |
|---------------|--------------|----------------------------------|
| `listen_port` | 2323         | TCP port for the DOS connection  |
| `bbs_host`    | 10.1.0.244   | BBS hostname or IP               |
| `bbs_port`    | 2023         | BBS TCP port                     |

Examples:

```
secproxy                              # all defaults
secproxy 5000                         # listen on port 5000
secproxy 2323 bbs.example.com 23      # different BBS
secproxy --help                       # show usage
```


## Startup Sequence

1. Listen on the configured TCP port.
2. Wait for the DOS side to connect (polls with Ctrl+C support).
3. Map the TCP socket to COM0 via the socket shim.
4. Seed the RNG from `/dev/urandom`.
5. Open SecLink and perform the DH handshake (blocks until the DOS
   side completes its handshake).
6. Wait for the terminal to send ENTER (so the user can confirm the
   connection is working before BBS output starts).
7. Connect to the remote BBS.
8. Enter the proxy loop.


## Proxy Loop

The main loop uses `poll()` with a 10ms timeout to multiplex between
the two TCP connections:

- **DOS -> BBS**: `secLinkPoll()` reads from the DOS-side socket via
  the socket shim, decrypts incoming packets, and the receive callback
  writes plaintext to the BBS socket.
- **BBS -> DOS**: `read()` from the BBS socket, then the telnet
  filter strips IAC sequences, then `secLinkSend()` encrypts and sends
  to the DOS side via the socket shim. If the send window is full, the
  loop retries with ACK processing until the data goes through.
- **Maintenance**: `secLinkPoll()` also handles packet-layer
  retransmit timers on every iteration.

The proxy exits cleanly on Ctrl+C (SIGINT), SIGTERM, or when either
side disconnects.


## Telnet Negotiation

The proxy handles RFC 854 telnet IAC sequences from the BBS so they
do not corrupt the terminal display. A state machine parser strips
IAC sequences from the data stream, persisting state across TCP
segment boundaries.

Accepted options:

- ECHO (option 1) -- server echoes characters
- SGA (option 3) -- suppress go-ahead for character-at-a-time mode
- TTYPE (option 24) -- terminal type negotiation
- NAWS (option 31) -- window size negotiation

All other options are refused. Subnegotiations (SB...SE) are consumed
silently.


## Socket Shim

The proxy reuses the same packet, security, and secLink source code as
the DOS build. A socket shim (`sockShim.h` / `sockShim.c`) provides
rs232-compatible functions backed by TCP sockets instead of UART
hardware:

| rs232 function | Socket shim behavior                             |
|----------------|--------------------------------------------------|
| `rs232Open()`  | Validates socket assigned; ignores serial params |
| `rs232Close()` | Marks port closed (socket lifecycle is caller's) |
| `rs232Read()`  | Non-blocking `recv()` with `MSG_DONTWAIT`        |
| `rs232Write()` | Blocking `send()` loop with `MSG_NOSIGNAL`       |

The shim maps COM port indices (0-3) to socket file descriptors via
`sockShimSetFd()`, which must be called before opening the SecLink
layer. Up to 4 ports are supported.

The Makefile uses `-include sockShim.h` when compiling the packet and
secLink layers, which defines `RS232_H` to prevent the real `rs232.h`
from being included.


## Platform Stubs

DOS-specific headers required by the security library are replaced by
minimal stubs in `stubs/`:

| Stub                 | Replaces               | Contents          |
|----------------------|------------------------|-------------------|
| `stubs/pc.h`         | `<pc.h>`               | No-op definitions |
| `stubs/go32.h`       | `<go32.h>`             | No-op definitions |
| `stubs/sys/farptr.h` | `<sys/farptr.h>`       | No-op definitions |

The security library's hardware entropy function returns zeros on
Linux, which is harmless since the proxy seeds the RNG from
`/dev/urandom` before the handshake.


## Emulator Configuration

Configure the emulated DOS machine's serial port to connect to the
proxy:

1. Point a COM port at the proxy's listen port (default 2323) in TCP
   client mode.
2. Disable any built-in telnet negotiation so raw bytes pass through.
3. The DOS terminal application running in the emulator uses SecLink
   over this serial port.


## Building

```
make            # builds ../bin/secproxy
make clean      # removes objects and binary
```

Objects are placed in `../obj/proxy/`, the binary in `../bin/`.

Requires only a standard Linux C toolchain (gcc, libc). No external
dependencies beyond the project's own packet, security, and secLink
source files, which are compiled directly from their source directories.


## Files

```
proxy/
  proxy.c              main proxy program
  sockShim.h           rs232-compatible socket API (header)
  sockShim.c           socket shim implementation
  Makefile             Linux native build
  stubs/
    pc.h               stub for <pc.h>
    go32.h             stub for <go32.h>
    sys/
      farptr.h         stub for <sys/farptr.h>
```
