diff --git a/harness/mame/NETWORK_REPORT.md b/harness/mame/NETWORK_REPORT.md index 41830db..9c85419 100644 --- a/harness/mame/NETWORK_REPORT.md +++ b/harness/mame/NETWORK_REPORT.md @@ -3722,3 +3722,67 @@ This confirms section 50 from a third independent direction and simplifies the rule: the field is simply `-len`, and for any length under 4096 that always has the top nibble set. There is no separate "0xF000 convention" to remember — a positive value is simply wrong. + +## 54. Remaining mappings: raw-IP delivery, TCP state switches, ICMP checksums + +### 54.1 `0x3F61EC00` is `rip_input()` — raw IP delivery + +`sys/netinet/raw_ip.c:58`. The three identifying constructs: + +```c +raw_ip.c:65 for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) { +raw_ip.c:66 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) continue; +raw_ip.c:68 if (inp->inp_laddr.s_addr && inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; +raw_ip.c:70 if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; +raw_ip.c:80 sbappendaddr(&last->so_rcv, (struct sockaddr *)&ripsrc, n, 0) +raw_ip.c:96 sbappendaddr(&last->so_rcv, ...) +raw_ip.c:100 ipstat.ips_noproto++; +``` + +which are exactly the parts of `0x3F61EC00` measured earlier: a PCB-list walk +comparing a protocol word, a local and a foreign address, delivery through a +queue append, and the **`ips_noproto` counter on no match** — the counter we +recorded at `0x96500` (section 29.2). + +The `dsj` gate found in section 46 compares that PCB field against 1, i.e. the +raw socket bound to **ICMP** (`inp->inp_ip.ip_p == IPPROTO_ICMP`); the +5/8/13…18 skip list is then the raw-ICMP socket filter — those are the types the +kernel answers internally, so a raw socket must not also receive them. + +### 54.2 The TCP state tables are `tcp_input`'s two switches + +`sys/netinet/tcp_input.c` has two dispatches on `tp->t_state`: + +``` +tcp_input.c:506 switch (tp->t_state) { <-- our table B (0x3F6417C0) +tcp_input.c:823 if (tiflags&TH_RST) switch (tp->t_state) { +tcp_input.c:825 case TCPS_SYN_RECEIVED: +tcp_input.c:829 case TCPS_ESTABLISHED: +tcp_input.c:840 case TCPS_CLOSING: +tcp_input.c:841 case TCPS_LAST_ACK: +tcp_input.c:842 case TCPS_TIME_WAIT: +tcp_input.c:865 switch (tp->t_state) { <-- our table A (0x3F63F350) +tcp_input.c:872 case TCPS_SYN_RECEIVED: +tcp_input.c:897 case TCPS_ESTABLISHED: +``` + +The grouping matches table A exactly: in section 24.2, states **7 CLOSING, +8 LAST_ACK and 10 TIME_WAIT all share the target `0x3F63F200`** — the same +fallthrough group as `tcp_input.c:840-842`. Table A's SYN_RECEIVED handled +separately and ESTABLISHED family grouped also matches `:872` vs `:897`. + +### 54.3 ICMP checksum sites + +| ROM | source | evidence | +|---|---|---| +| `0x3F6206D0` (verify) | `ip_icmp.c:184` `if (in_cksum(m, icmplen))` | checksum over the ICMP message before the type switch | +| `0x3F623350` (reflect) | `ip_icmp.c:522-523` `icp->icmp_cksum = 0; icp->icmp_cksum = in_cksum(...)` | zero the field, recompute, store — exactly the sequence at `0x3F62FF60`..`0x3F630000` | + +### 54.4 Coverage + +With 53 and 54, every function the report gives an address for now has a BSD +counterpart: driver (`leinit`/`lereset`/`ledrinit`/`lestart`/`leintr`/`lerint`), +IP (`ipintr`, `inetsw[ip_protox[]]`, `ip_output`), ICMP (`icmp_input`, +`icmp_reflect`, `icmp_send`), TCP (`tcp_input`, `tcp_dooptions`, `tcp_mss`), +UDP (`udp_input`, `udp_output`), raw IP (`rip_input`), ARP (`in_arpinput`, +`arpresolve`, `arplookup`, `arprequest`) and the PCB lookup (`in_pcblookup`).