Skip to content

Commit 509ac76

Browse files
d3vi1claude
andauthored
Implement LLTD automata v1.0 for Darwin with session table and Repeat… (#10)
* Implement LLTD automata v1.0 for Darwin with session table and RepeatBand Core automata improvements: - Fix switch_state_session() to return session automaton instead of calling switch_state_mapping() which caused infinite recursion on timeout - Session automaton now starts in Nascent state (index 1) instead of Temporary (index 0) as per LLTD specification - Add mapping_state struct for charge timeout counter (ctc) and inactive timeout tracking (30s inactive timeout per spec) Session table implementation: - New session_table struct keyed by mapper MAC + generation/seq number - Supports up to 16 concurrent mapper sessions (SESSION_TABLE_MAX_ENTRIES) - Automatic eviction of oldest entries when table is full - Session entries track state, completion status, and timestamps - derive_session_event() analyzes frames to produce sess_* events: sess_discover_acking, sess_discover_noack, sess_discover_conflicting, _chgd_xid variants, sess_topo_reset, sess_reset, sess_hello RepeatBand algorithm: - band_state extended with hello_timeout_ts and block_timeout_ts (ms) - band_init_stats(): Initialize Ni=ALPHA, r=0, begun=false - band_update_stats(): Update Ni = min(NMAX, ALPHA * r^BETA) on block timeout - band_choose_hello_time(): Calculate next hello based on RepeatBand formula - band_do_hello(): Schedule next hello, mark begun=true - band_on_hello_received(): Increment r counter Periodic tick mechanism: - automata_tick() called every 100ms via select() timeout in lltdLoop - Handles mapping inactive/charge timeouts even without RX traffic - Processes session table timeouts (1s inactivity removal) - Triggers hello/block timeouts for enumeration RepeatBand Darwin integration: - network_interface_t gains sessionTable and MapperGeneration fields - sendHelloMessage() broadcasts Hello with RepeatBand timing - lltdLoop uses select() with 100ms timeout for tick-driven timeouts - Session table cleaned up in deviceDisappeared() TLV correctness fixes: - Fix setUuidTLV() to copy from machineUUID, not from TLV header pointer - setHardwareIdTLV() properly calls getHwId() on Darwin - setDetailedIconTLV() and setComponentTableTLV() call platform functions - All TLV stubs return 0 or proper data, maintaining frame validity Testing: - Extended test_lltd_tlv_ops.c with UUID size, endianness, EOP marker tests - Updated lltdTestShim.h with new network_interface_t fields - Added stub implementations for getHwId, getDetailedIconImage, getComponentTable Documentation: - Added Documentation/automata_runtime.md describing how the three automata (Mapping, Session, Enumeration) are wired into the Darwin runtime * Move platform-specific TLV code to platform ops pattern - Remove #ifdef __APPLE__ guards from lltdTlvOps.c, now calls platform ops functions unconditionally (getHwId, getDetailedIconImage, etc.) - Add sendHelloMessage stub to win32 stubs to fix Windows linker error - Follows project pattern: all OS-specific code in ${os}_ops.c * Fix getBSSID null pointer crash when Wi-Fi not associated - Check cfDATA is not NULL before using in getBSSID (darwin-ops.c) - Fix setBSSIDTLV to properly use allocated pointer from getBSSID, matching pattern used by setSSIDTLV and other TLV functions - Return 0 (skip TLV) when BSSID unavailable instead of crashing * Fix WiFi property lookup for Skywalk stack on Tahoe+ - Update copyWiFiProperty() to search parent nodes when property not found in children. On Skywalk, WiFi properties (IO80211BSSID, IO80211SSID, etc.) are on IOUserNetworkWLAN which is a parent of the BSD interface node. - Refactor getBSSID() to use copyWiFiProperty() for consistent behavior across legacy IOKit and Skywalk stacks - Add type and size validation for BSSID CFData * Fix automata issues: session timeout, RepeatBand transitions - Increase session timeout from 1s to 60s - sessions were expiring before any useful work could be done - Add transition Quiescent -> Pausing with enum_new_session so that receiving a Discover frame immediately starts enumeration - Change Wait -> Quiescent transition for enum_sess_complete so that empty session table returns to idle state - Add Wait -> Pausing transition for enum_new_session - Prevent tick spam by not sending inputs when already in Quiescent - Only transition Wait -> Quiescent when table is empty, not from Pausing * Fix RepeatBand infinite loop after Reset received - When session table becomes empty (Reset received), immediately return RepeatBand to Quiescent state from any active state (Pausing or Wait) - Reset hello and block timeouts when returning to Quiescent - Prevents infinite Hello sending loop after mapping session ends * Update .gitignore for XCode build artifacts * Clear session table when Mapping transitions to Quiescent on timeout The state-based timeout in switch_state_mapping (1s for Command state) was transitioning Mapping to Quiescent without clearing the session table. This caused RepeatBand to continue running indefinitely because it only stopped when the session table was empty. Now we track the previous state before calling switch_state_mapping and clear the session table if we just transitioned to Quiescent from any active state (Command or Emit). This handles both state-based timeouts and any other transition to Quiescent. * Fix inactive timeout spam, MTU retrieval, and Hello TLV building 1. Fix inactive timeout spam: Reset inactive_timeout_ts to 0 after triggering so it doesn't fire on every tick. 2. Fix MTU retrieval: Use kIOMaxPacketSize from IONetworkController instead of kIOMaxTransferUnit from IONetworkInterface. This is more reliable on modern macOS with Skywalk. Also fixed bug where IONetworkController was used after being released. 3. Enhance Hello TLV building: Add PhysicalMediumTLV for interface type identification, wireless-specific TLVs (WirelessTLV, BSSIDTLV, SSIDTLV, 80211MediumTLV) for 802.11 interfaces, and IconImageTLV and FriendlyNameTLV for station identification. * Increase Mapping Command state timeout from 1s to 5s The 1 second timeout was too short - the mapper can have gaps of more than 1 second between frames during the mapping process. This was causing the responder to timeout and clear the session table while the mapper was still active, resulting in the station not appearing on the network map. Increased to 5 seconds to allow adequate time for the complete mapping sequence (Discover -> Query -> Train -> Probe -> etc). * Set IANA ifType for PhysicalMediumTLV The ifType field was never being initialized, causing PhysicalMediumTLV to send 0 instead of the correct IANA interface type. This likely caused Windows to not properly identify the device on the network map. Now sets ifType alongside interfaceType: - 71 for ieee80211 (WiFi) - 6 for ethernetCsmacd (Ethernet) * Fix multiple TLV encoding issues found via Wireshark - setPerfCounterTLV: Fix pointer arithmetic bug (was writing 4 bytes past TLV header instead of 2 due to pointer math on struct pointer) - setWifiMaxRateTLV: Fix length from uint32_t to uint16_t per LLTD spec, convert rate to 0.5 Mbps units - setWifiRssiTLV: Fix length from int8_t to int32_t per LLTD spec - setQosCharacteristicsTLV: Fix length from uint16_t to uint32_t per spec - Remove duplicate set80211MediumTLV call (was using same TLV type 0x03 as setPhysicalMediumTLV, causing duplicate Physical Medium TLVs) * Fix more TLV encoding issues per Wireshark analysis - Characteristics TLV: Change to uint32_t, flags in upper 16 bits - Performance Counter TLV: Change to uint64_t (8 bytes) per LLTD spec - QoS Characteristics TLV: Shift flags to upper 16 bits - Remove duplicate set80211MediumTLV call from answerHello - Remove Hardware ID, Detailed Icon, Component Table from Hello frame (these are QueryLargeTLV-only, not meant to be in Hello) Note: Link Speed, WiFi Max Rate, and RSSI showing 0 are macOS IORegistry property retrieval issues, not TLV encoding bugs. * Unify Hello TLVs and remove broken UUID - Remove UUID TLV (0x12) from Hello frames - parsing issue to investigate - Update sendHelloMessage to include all TLVs matching answerHello: IPv4, IPv6, PerfCounter, LinkSpeed, Hostname, QoS Characteristics, and WiFi-specific TLVs (MaxRate, RSSI) - Both Hello implementations now send consistent TLV sets * Fix QueryLargeTLV handling and make helloSent per-interface QueryLargeTLV changes: - Refactor sendImage to generic sendLargeTlvResponse function - Add handling for Friendly Name (0x11) and Hardware ID (0x13) TLV types - Icon image retrieval uses existing caching mechanism - Add proper error handling when data is NULL or empty - Add debug logging for all QueryLargeTLV requests helloSent fix: - Move helloSent from global variable to per-interface field - Prevents Hello suppression issues with multiple interfaces - Add helloSent field to network_interface_t in all platform headers * Fix Hello Spam, correct sequence handling, Fix incorrect Discover offset Fixed Darwin responder: stopped enumeration “Hello spam” loop by transitioning the RepeatBand automaton from Pausing to Wait when the session table is complete, preventing endless periodic Hello retransmissions that kept the mapper from converging. Correct LLTD sequence number handling on outbound frames: Hello/Probe/Train now use the current MapperSeqNumber (derived from the active mapper session) instead of a constant 0x00, improving interoperability with Windows’ LLTD mapper. Repaired answerHello() frame parsing and validation: Fixed incorrect Discover-header offset calculation (pointer-size vs struct-size). Validated fields against the received frame header (not a freshly-built outbound buffer). Ensured replies preserve the active session sequence number (seqNumber) so responses remain in-session and are not ignored by the mapper. Notes This patch primarily addresses cases where mapping never populates because the responder continuously re-enters Hello timeouts and/or emits frames that the mapper treats as out-of-session. * More Darwin Hello Fixes - darwin: Reply to LLTD Quick Discovery Hello (TOS=0x01, opcode=0x01) instead of ignoring it, mirroring the mapper’s sequence/generation to prevent mapper Reset and allow the host to appear in Network Map. - darwin: Factor Hello transmission into sendHelloMessageEx() to support explicit mapper real/apparent MACs and per-exchange sequencing. * More Darwin Hello Fixes - darwin: Reply to LLTD Quick Discovery Hello (TOS=0x01, opcode=0x01) instead of ignoring it, mirroring the mapper’s sequence/generation to prevent mapper Reset and allow the host to appear in Network Map. - darwin: Factor Hello transmission into sendHelloMessageEx() to support explicit mapper real/apparent MACs and per-exchange sequencing. # Conflicts: # lltdDaemon/lltdBlock.c * More Darwin Hello Fixes - darwin: Reply to LLTD Quick Discovery Hello (TOS=0x01, opcode=0x01) instead of ignoring it, mirroring the mapper’s sequence/generation to prevent mapper Reset and allow the host to appear in Network Map. - darwin: Factor Hello transmission into sendHelloMessageEx() to support explicit mapper real/apparent MACs and per-exchange sequencing. # Conflicts: # lltdDaemon/lltdBlock.c * Attempt at fixing macOS build * Works for me New attempt * Fix building if there are SPACES in the path to the tree * Fix LLTD Discovery/Hello compliance behind bridges/APs Remove incorrect validation that dropped Discover frames when LLTD Real_Source_Address != Ethernet header source MAC. This mismatch is expected behavior behind bridges/APs where the Ethernet source is rewritten by the network infrastructure. Changes: - answerHello() no longer returns early on address mismatch - Keep diagnostic log (debug level) showing the mismatch for debugging - Add clarifying comments on Hello header construction: - apparentMapper = frameHeader.source (Ethernet src, may be bridge) - currentMapper = realSource (true mapper MAC from LLTD header) - Use memcpy for MapperHwAddress (cleaner than byte-by-byte) Expected behavior: Discover frames with rewritten Ethernet source will now trigger Hello response with both mapper addresses correctly preserved in the Hello upper header. * Add diagnostic dump when TARGET_BUILD_DIR is missing When xcodebuild -showBuildSettings doesn't provide TARGET_BUILD_DIR, print the first 60 lines of the captured settings to stderr before failing. This helps debug build failures on different macOS/Xcode configurations. - Uses printf + head for bash 3.2 compatibility - Separate checks for TARGET_BUILD_DIR and FULL_PRODUCT_NAME * Fix MS-LLTD compliance: broadcast Hello and conditional QueryResp Per MS-LLTD specification: - Hello frames MUST be sent to Ethernet broadcast (FF:FF:FF:FF:FF:FF) - QueryResp/QueryLargeTlvResp frames MUST be broadcast when the mapper is behind a bridge/AP (Real Source != Ethernet source), otherwise unicast to Real Source Also improves send failure diagnostics with errno details. * Fix sendto() in sendHelloMessageEx to use socketAddr AF_NDRV sockets on Darwin require the socket address structure to identify the interface, not NULL. * Fix LLTD mapping for bridged networks: real vs apparent addressing Major fixes for LLTD mapping phase in bridged/AP topologies: A) Real vs Apparent addressing: - Add setLltdHeaderEx() to set Ethernet and LLTD addresses independently - Add MapperApparentAddress field to track bridge-level mapper address - parseProbe: Accept frames based on realDestination (not Ethernet dest) - sendProbeMsg: Use proper dual addressing (Ethernet=apparent, LLTD=real) - ACKs now correctly target apparent mapper through bridge B) Sequence number handling: - Remove global MapperSeqNumber update on every frame - Update only on session-defining frames (Discover, Emit, Query) C) Probe/Train fixes: - sendProbeMsg: Add missing return value, fix memory leak - Add proper error handling and buffer cleanup D) Debug logging: - Add compact debug logs for Emit, Query, Probe/Train frames - Log opcode, tos, seq, all addresses, forUs decision - Enhanced send failure logs with errno details * Correct Endianness conversion for Generation * Fix hello generation endianness for discovery/quick hello frames (#18) * Fix hello generation byte order for discovery * Enforce LLTD sequence and generation byte order * Add offline LLTD pcap regression checker * Add mapper-id hello diagnostics and warnings * Add LLTD generation harness for Discover vs Hello * Throttle hello timeouts and log mapper discovery timing * Always reply to Discover and add frame logs * Fix TLV sizes for perf counter and QoS * Restore QoS characteristics TLV width * Restore perf counter TLV width * Avoid unaligned TLV payload writes * Use SO_RCVTIMEO for AF_NDRV recv loop * Squashed commit of the following: commit c310def Author: Claude <noreply@anthropic.com> Date: Wed Jan 7 20:32:46 2026 +0000 Add Darwin Wi-Fi metrics module using CoreWLAN Implements a pure C API for querying Wi-Fi metrics on macOS using CoreWLAN framework. This provides RSSI, noise, link speed, and computed max link speed without relying on external commands like wdutil or airport. New files: - lltd_wifi_corewlan.h: Pure C89 header with lltd_wifi_metrics_t struct - lltd_wifi_corewlan.m: Objective-C shim using CoreWLAN - lltd_wifi_rates.c/h: Rate calculation tables for HT/VHT/HE PHY modes - tools/lltd-wifi-metrics.c: CLI tool for testing/verification Features: - Queries RSSI, noise, PHY mode, channel width via CoreWLAN - Computes theoretical max link speed based on PHY/width/NSS - Infers NSS/MCS/GI from observed link rate using rate tables - Supports 802.11a/b/g/n/ac/ax with proper rate calculations - Handles missing selectors gracefully for SDK compatibility The module is Darwin-only and guarded with __APPLE__. No Objective-C headers leak into the cross-platform C codebase. commit e35ad88 Author: Claude <noreply@anthropic.com> Date: Wed Jan 7 20:21:10 2026 +0000 Add single-instance check to prevent duplicate daemon processes AF_NDRV sockets allow multiple binds but only the first process receives packets. This caused silent failures when a previous lltdDaemon was still running. Now uses flock() on /tmp/lltdDaemon.lock to ensure only one instance runs at a time. --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent a32123b commit 509ac76

30 files changed

Lines changed: 3680 additions & 307 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
lltdDaemon.xcodeproj/project.xcworkspace/
44
LLMNRd.xcodeproj/project.xcworkspace/xcshareddata/
55
LLMNRd.xcodeproj/project.xcworkspace/xcshareddata/LLMNRd.xccheckout
6+
build
7+
dist

Documentation/automata_runtime.md

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
# LLTD Automata Runtime Integration
2+
3+
This document describes how the three LLTD finite state machines (Mapping Engine, Session Table, Enumeration Engine) are integrated into the Darwin runtime.
4+
5+
## Architecture Overview
6+
7+
```
8+
+------------------+
9+
| lltdLoop() | Per-interface receive thread
10+
+--------+---------+
11+
|
12+
| select() with 100ms timeout
13+
|
14+
+----v----+
15+
| Packet | Data available?
16+
| RX? |
17+
+----+----+
18+
|
19+
+----v----+
20+
|automata | Called every 100ms regardless of RX
21+
| _tick() |
22+
+----+----+
23+
|
24+
+------+------+------+
25+
| | | |
26+
v v v v
27+
Mapping Session Enum Session
28+
Engine Table Engine Table
29+
(FSM) (entries)(FSM) Timeouts
30+
```
31+
32+
## Component Initialization
33+
34+
When a network interface is validated in `deviceAppeared()`:
35+
36+
```c
37+
currentNetworkInterface->mappingAutomata = init_automata_mapping();
38+
currentNetworkInterface->sessionAutomata = init_automata_session();
39+
currentNetworkInterface->enumerationAutomata = init_automata_enumeration();
40+
currentNetworkInterface->sessionTable = session_table_create();
41+
```
42+
43+
Each automaton starts in its initial state:
44+
- **Mapping Engine**: Quiescent (state 0)
45+
- **Session Automaton**: Nascent (state 1)
46+
- **Enumeration Engine**: Quiescent (state 0)
47+
48+
## Periodic Tick Mechanism
49+
50+
The receive loop uses `select()` with a 100ms timeout to ensure timeouts are processed even without incoming packets:
51+
52+
```c
53+
for(;;) {
54+
fd_set readfds;
55+
struct timeval timeout = {0, 100000}; // 100ms
56+
57+
int result = select(fd + 1, &readfds, NULL, NULL, &timeout);
58+
59+
// Always call tick (handles all timeout-based behavior)
60+
automata_tick(mapping, enumeration, sessionTable, interface);
61+
62+
if (result > 0) {
63+
// Process received frame...
64+
}
65+
}
66+
```
67+
68+
## Mapping Engine Integration
69+
70+
The Mapping Engine FSM tracks the current mapping session:
71+
72+
### States
73+
| State | Index | Timeout | Description |
74+
|-------|-------|---------|-------------|
75+
| Quiescent | 0 | None | Idle, waiting for Discover |
76+
| Command | 1 | 1s | Processing commands |
77+
| Emit | 2 | 30s | Transmitting probes |
78+
79+
### Extended State (`mapping_state`)
80+
```c
81+
typedef struct mapping_state {
82+
uint8_t ctc; // Charge timeout counter
83+
uint64_t charge_timeout_ts; // Charge timeout timestamp
84+
uint64_t inactive_timeout_ts;// Inactive timeout timestamp (30s)
85+
} mapping_state;
86+
```
87+
88+
### Runtime Behavior
89+
90+
1. **On Frame Receipt**: Reset inactive timeout, update FSM state
91+
2. **On Charge Opcode**: Increment `ctc`, restart 1s charge timeout
92+
3. **On Charge Timeout**: Reset `ctc` to 0
93+
4. **On Inactive Timeout**: Return to Quiescent, clear session table
94+
95+
## Session Table Integration
96+
97+
The session table tracks multiple concurrent mapper sessions:
98+
99+
### Data Structure
100+
```c
101+
typedef struct session_entry {
102+
uint8_t mapper_mac[6]; // Mapper hardware address
103+
uint16_t generation; // Session generation number
104+
uint16_t seq_number; // Current sequence number
105+
uint8_t state; // Session state (sess_* constants)
106+
bool complete; // Session complete flag
107+
bool valid; // Entry in use
108+
uint64_t last_activity_ts; // Last activity timestamp
109+
} session_entry;
110+
```
111+
112+
### Session Event Derivation
113+
114+
The `derive_session_event()` function analyzes incoming frames to produce session-level events:
115+
116+
| Opcode | Condition | Event |
117+
|--------|-----------|-------|
118+
| Discover | Empty station list OR we're in list | `sess_discover_acking` |
119+
| Discover | Not in station list | `sess_discover_noack` |
120+
| Discover | Seq changed | `*_chgd_xid` variants |
121+
| Discover | Different mapper, same gen | `sess_discover_conflicting` |
122+
| Hello | Any | `sess_hello` |
123+
| Reset | Broadcast dest | `sess_topo_reset` |
124+
| Reset | Unicast dest | `sess_reset` |
125+
126+
### Runtime Behavior
127+
128+
1. **On Discover**: Add/update session entry, update MapperHwAddress
129+
2. **On Reset**: Clear session table
130+
3. **On Tick**: Remove stale entries (>1s inactivity)
131+
4. **Status Query**: `session_table_is_empty()`, `session_table_all_complete()`
132+
133+
## Enumeration Engine (RepeatBand) Integration
134+
135+
The Enumeration Engine implements the RepeatBand algorithm for periodic Hello transmission:
136+
137+
### States
138+
| State | Index | Timeout | Description |
139+
|-------|-------|---------|-------------|
140+
| Quiescent | 0 | None | No active sessions |
141+
| Pausing | 1 | 60s | Active enumeration |
142+
| Wait | 2 | 30s | All sessions complete |
143+
144+
### RepeatBand State (`band_state`)
145+
```c
146+
typedef struct band_state {
147+
uint32_t Ni; // Repetition count
148+
uint32_t r; // Hello counter for current block
149+
bool begun; // Enumeration started flag
150+
uint64_t hello_timeout_ts; // Next Hello time (ms)
151+
uint64_t block_timeout_ts; // Next block timeout (ms)
152+
} band_state;
153+
```
154+
155+
### RepeatBand Constants
156+
```c
157+
#define BAND_NMAX 10000 // Maximum repetition count
158+
#define BAND_ALPHA 45 // Scaling factor
159+
#define BAND_BETA 2 // Exponent for Ni calculation
160+
#define BAND_GAMMA 10 // Min Hellos before stats
161+
#define BAND_TXC 4 // Transmit count
162+
#define BAND_FRAME_TIME 6.667 // Frame time (ms)
163+
#define BAND_BLOCK_TIME 300 // Block time (ms)
164+
```
165+
166+
### Runtime Behavior
167+
168+
1. **On New Session (Quiescent)**:
169+
- Call `band_init_stats()` - sets `Ni=ALPHA`, `r=0`
170+
- Call `band_choose_hello_time()` - schedules first Hello
171+
- Transition to Pausing
172+
173+
2. **On Hello Received (Pausing)**:
174+
- Call `band_on_hello_received()` - increments `r`
175+
176+
3. **On Hello Timeout (Pausing)**:
177+
- Call `sendHelloMessage()` - transmit Hello frame
178+
- Call `band_do_hello()` - reschedule next Hello
179+
180+
4. **On Block Timeout (Pausing)**:
181+
- Call `band_update_stats()` - update `Ni = min(NMAX, ALPHA * r^BETA)`
182+
- Call `band_choose_hello_time()` - schedule next Hello
183+
184+
5. **On Session Table Complete**: Transition to Wait
185+
6. **On Session Table Empty**: Transition to Quiescent
186+
187+
## Frame Processing Flow
188+
189+
```
190+
Frame Received
191+
|
192+
v
193+
derive_session_event() --> session event (sess_*)
194+
|
195+
v
196+
Update session_table with mapper info
197+
|
198+
v
199+
switch_state_mapping(opcode)
200+
|
201+
v
202+
mapping_reset_inactive_timeout()
203+
|
204+
v
205+
[if opcode == charge] mapping_on_charge()
206+
|
207+
v
208+
switch_state_session(sess_event)
209+
|
210+
v
211+
[if opcode == hello] band_on_hello_received()
212+
|
213+
v
214+
switch_state_enumeration(enum_event)
215+
|
216+
v
217+
parseFrame() --> generate response
218+
```
219+
220+
## Timeout Processing (automata_tick)
221+
222+
Called every 100ms from the receive loop:
223+
224+
```
225+
automata_tick()
226+
|
227+
+-- Check mapping_check_inactive_timeout()
228+
| --> Clear session table, go Quiescent
229+
|
230+
+-- Check mapping_check_charge_timeout()
231+
| --> Reset ctc to 0
232+
|
233+
+-- Check session entries for timeout
234+
| --> Remove stale entries
235+
|
236+
+-- Update session_table_all_complete()
237+
|
238+
+-- Check enumeration hello_timeout
239+
| --> sendHelloMessage(), band_do_hello()
240+
|
241+
+-- Check enumeration block_timeout
242+
--> band_update_stats(), band_choose_hello_time()
243+
```
244+
245+
## Thread Safety
246+
247+
Each interface runs in its own thread with its own automata instances. No cross-thread access occurs. The main CFRunLoop only handles IOKit notifications for interface add/remove events.
248+
249+
## Cleanup
250+
251+
On interface removal (`deviceDisappeared`):
252+
253+
```c
254+
free_automata(currentNetworkInterface->mappingAutomata);
255+
free_automata(currentNetworkInterface->sessionAutomata);
256+
free_automata(currentNetworkInterface->enumerationAutomata);
257+
session_table_destroy(currentNetworkInterface->sessionTable);
258+
```
259+
260+
## Testing
261+
262+
The automata module supports the `LLTD_TESTING` compile flag which:
263+
- Stubs out platform-specific functions
264+
- Disables actual frame transmission
265+
- Enables unit testing of state machine logic
266+
267+
See `tests/test_lltd_tlv_ops.c` for TLV-related tests.

lltdDaemon.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
C1A0D7D618E01E0900863EA1 /* lltd_wifi_corewlan.m in Sources */ = {isa = PBXBuildFile; fileRef = C1A0D7D518E01E0900863EA1 /* lltd_wifi_corewlan.m */; };
11+
C1A0D7D618E01E0900863EA2 /* lltd_wifi_rates.c in Sources */ = {isa = PBXBuildFile; fileRef = C1A0D7D518E01E0900863EA2 /* lltd_wifi_rates.c */; };
12+
C1A0D7D618E01E0900863EA5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1A0D7D518E01E0900863EA5 /* Foundation.framework */; };
1013
E500D7D618E01E0900863EAC /* darwin-ops.c in Sources */ = {isa = PBXBuildFile; fileRef = E500D7D518E01E0900863EAC /* darwin-ops.c */; };
1114
E500D7DD18E02F3900863EAC /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E500D7DC18E02F3900863EAC /* ImageIO.framework */; };
1215
E500D7E318E0427200863EAC /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E500D7E218E0427200863EAC /* CoreServices.framework */; };
@@ -53,6 +56,11 @@
5356
/* End PBXCopyFilesBuildPhase section */
5457

5558
/* Begin PBXFileReference section */
59+
C1A0D7D518E01E0900863EA1 /* lltd_wifi_corewlan.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "lltd_wifi_corewlan.m"; path = "lltdDaemon/darwin/lltd_wifi_corewlan.m"; sourceTree = SOURCE_ROOT; };
60+
C1A0D7D518E01E0900863EA2 /* lltd_wifi_rates.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "lltd_wifi_rates.c"; path = "lltdDaemon/darwin/lltd_wifi_rates.c"; sourceTree = SOURCE_ROOT; };
61+
C1A0D7D518E01E0900863EA3 /* lltd_wifi_corewlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lltd_wifi_corewlan.h"; path = "lltdDaemon/darwin/lltd_wifi_corewlan.h"; sourceTree = SOURCE_ROOT; };
62+
C1A0D7D518E01E0900863EA4 /* lltd_wifi_rates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lltd_wifi_rates.h"; path = "lltdDaemon/darwin/lltd_wifi_rates.h"; sourceTree = SOURCE_ROOT; };
63+
C1A0D7D518E01E0900863EA5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
5664
E500D7D518E01E0900863EAC /* darwin-ops.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "darwin-ops.c"; path = "lltdDaemon/darwin/darwin-ops.c"; sourceTree = SOURCE_ROOT; };
5765
E500D7D718E01E1800863EAC /* darwin-ops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "darwin-ops.h"; path = "lltdDaemon/darwin/darwin-ops.h"; sourceTree = SOURCE_ROOT; };
5866
E500D7DC18E02F3900863EAC /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; };
@@ -85,6 +93,7 @@
8593
isa = PBXFrameworksBuildPhase;
8694
buildActionMask = 2147483647;
8795
files = (
96+
C1A0D7D618E01E0900863EA5 /* Foundation.framework in Frameworks */,
8897
E59ADBBE1C80982300895932 /* SystemConfiguration.framework in Frameworks */,
8998
E500D7E318E0427200863EAC /* CoreServices.framework in Frameworks */,
9099
E500D7DD18E02F3900863EAC /* ImageIO.framework in Frameworks */,
@@ -130,6 +139,7 @@
130139
E52240FA18CF0CA200DD9E2F /* Frameworks */ = {
131140
isa = PBXGroup;
132141
children = (
142+
C1A0D7D518E01E0900863EA5 /* Foundation.framework */,
133143
E59ADBBD1C80982300895932 /* SystemConfiguration.framework */,
134144
E500D7E218E0427200863EAC /* CoreServices.framework */,
135145
E500D7DC18E02F3900863EAC /* ImageIO.framework */,
@@ -150,6 +160,10 @@
150160
E5774FA718D61F5E00988358 /* darwin-main.h */,
151161
E500D7D518E01E0900863EAC /* darwin-ops.c */,
152162
E500D7D718E01E1800863EAC /* darwin-ops.h */,
163+
C1A0D7D518E01E0900863EA1 /* lltd_wifi_corewlan.m */,
164+
C1A0D7D518E01E0900863EA3 /* lltd_wifi_corewlan.h */,
165+
C1A0D7D518E01E0900863EA2 /* lltd_wifi_rates.c */,
166+
C1A0D7D518E01E0900863EA4 /* lltd_wifi_rates.h */,
153167
E53E69BE1908293B0033F651 /* lltdBlock.c */,
154168
E53E69C0190829540033F651 /* lltdBlock.h */,
155169
E55B08981C6A3C930020A136 /* lltdDaemon.h */,
@@ -232,6 +246,8 @@
232246
files = (
233247
E5A41A0E19082C0B00D5D2FD /* darwin-main.c in Sources */,
234248
E500D7D618E01E0900863EAC /* darwin-ops.c in Sources */,
249+
C1A0D7D618E01E0900863EA1 /* lltd_wifi_corewlan.m in Sources */,
250+
C1A0D7D618E01E0900863EA2 /* lltd_wifi_rates.c in Sources */,
235251
FAD3A21C19EACF54000FB445 /* lltdAutomata.c in Sources */,
236252
E53E69BF1908293B0033F651 /* lltdBlock.c in Sources */,
237253
E5FD8AE0192A130900E4EA22 /* lltdTlvOps.c in Sources */,

lltdDaemon/beos/beos-main.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,20 @@ typedef struct {
2424
uint32_t MTU;
2525
uint8_t macAddress[6];
2626
uint8_t MapperHwAddress[6];
27+
uint8_t MapperApparentAddress[6];
28+
uint8_t MapperKnown;
2729
void *seeList;
2830
uint32_t seeListCount;
2931
uint16_t MapperSeqNumber;
32+
uint16_t MapperGenerationTopology;
33+
uint16_t MapperGenerationQuick;
34+
uint64_t LastHelloTxMs;
35+
uint64_t LastHelloReplyMs;
36+
uint16_t LastHelloReplyXid;
37+
uint16_t LastHelloReplyGen;
38+
uint8_t LastHelloReplyTos;
3039
void *recvBuffer;
40+
int helloSent;
3141
} network_interface_t;
3242

3343
#define lltdEtherType 0x88D9

0 commit comments

Comments
 (0)