net-wire 0.1.0

Allocation-free no_std wire views and codecs for network protocols.
Documentation
# Raw IPv4 DNS query (Linux)

A small, synchronous DNS client that builds the DNS message, UDP datagram, and IPv4 packet itself, then sends it through a Linux raw socket. It is an example, not a resolver.

> [!WARNING]
> **Linux only.** It uses `AF_INET`/`SOCK_RAW` and needs `CAP_NET_RAW` (normally root). It deliberately has no BSD, macOS, or Windows socket implementation.

## Run it

Use a source address actually configured on a local interface; it is not an address to invent for the occasion.

```sh
cargo run --example dns-query --features ipv4,udp -- 192.0.2.10 1.1.1.1 example.com
sudo cargo run --example dns-query --features ipv4,udp -- 192.0.2.10 1.1.1.1 example.com AAAA
```

Alternatively, grant only the built executable the capability:

```sh
cargo build --example dns-query --features ipv4,udp
sudo setcap cap_net_raw+ep target/debug/examples/dns-query
./target/debug/examples/dns-query 192.0.2.10 1.1.1.1 example.com A
```

Exact CLI:

```text
dns-query <source-ip> <server-ip> <name> [A|AAAA]
```

`A` is the default. Names are ASCII DNS wire labels only; there is no IDNA conversion.

> [!NOTE]
> The commands above are usage instructions, not evidence of a network run here. Raw I/O cannot be exercised on the current macOS host.

Representative output (illustrative):

```text
response id=0x4a19 rcode=0 answers=1 truncated=false recursion-available=true
example.com	300	IN	A	93.184.216.34
```

## Packet flow

```text
CLI -> dns.rs: DNS payload (<= 484 bytes in this example)
    -> packet.rs: UDP checksum, then IPv4 header
    -> raw_socket.rs: Linux raw IPv4 socket
    -> network: IPv4 + UDP + DNS
    <- raw socket: IPv4 packet (no Ethernet frame)
    <- packet.rs: address/port/checksum/transaction-ID filter
    <- dns.rs: header and answers in wire order
```

The builder order matters: DNS first, then UDP (whose checksum covers its payload and IPv4 pseudo-header), then IPv4. `net-wire` builds and parses those wire structures; local `dns.rs` owns the deliberately small RFC 1035 codec; `socket2` owns Linux socket calls.

## Linux raw-socket behavior

The socket is created as IPv4 raw UDP and uses `IP_HDRINCL`. The application supplies the IPv4 header. Linux still fills the IPv4 total length and header checksum on send. UDP's checksum remains the caller's responsibility, so `packet.rs` computes it.

The bind and connected raw sockaddr use port zero. Connecting narrows received traffic, but the example still validates IPv4 source/destination, UDP ports, IPv4 checksum, UDP checksum, and the DNS transaction ID. Unrelated valid UDP datagrams are ignored until the finite read timeout; malformed packets that otherwise match the flow are reported.

There is no Ethernet header in an `AF_INET` raw socket packet. Link-layer framing belongs below this socket API, so manufacturing an Ethernet frame here would be wrong.

## Troubleshooting

- `Operation not permitted`: run through `sudo`, or apply `cap_net_raw+ep` to the built binary.
- `Cannot assign requested address`: the supplied source IP is not configured locally.
- Timeout: check routing, firewall rules, the source IP, and that the server accepts ordinary UDP DNS.
- `response packet rejected`: traffic reached the raw socket but failed a checksum or expected-flow check.
- `rcode` is nonzero: DNS replied with a protocol failure such as NXDOMAIN; the response is still shown rather than being pretended away.

> [!TIP]
> Start with a public resolver and a real local unicast address. `0.0.0.0` is rejected because it does not identify a configured source.

## Deliberate limits

No TCP fallback, EDNS, DNSSEC, cache, resolver search rules, retries, async I/O, IDNA, or general DNS record decoding. Unsupported records retain and report their class, type, and RDATA length. The receive buffer fits one complete IPv4 datagram; the complete outbound IPv4 packet is bounded to 512 bytes.