From bfcb2e178f46b2a31c644faf8c5f8a51af361f0b Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Tue, 2 Jun 2026 05:25:25 +0000 Subject: [PATCH] docs: document semaphore endpoint layouts --- TODO.md | 37 ++++++++++++++++++++++++++++--- src/sema.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/TODO.md b/TODO.md index 0809c4b..58cf0a5 100644 --- a/TODO.md +++ b/TODO.md @@ -179,9 +179,6 @@ Present in the code but not yet fully endpoint-audited: - SDK `0x2222/26` through `0x2222/31` / wire `0x1a` through `0x1f` physical record synchronization calls are implemented in `src/nwconn.c` but have not yet received the detailed request-layout audit. -- SDK `0x2222/32` / wire `0x20` Semaphore is forwarded to `src/nwbind.c`; the - handoff is noted, but the semaphore subfunctions still need a per-subfunction - request/reply audit. - SDK `0x2222/33` / wire `0x21` Negotiate Buffer Size and SDK `0x2222/34` / wire `0x22` TTS calls are present in `src/nwconn.c`; their layouts still need source comparisons. @@ -491,6 +488,40 @@ Follow-up: items. Continue with the next non-4.x/OES-only group after this block. +#### Semaphore group 0x2222/32 + +Current status: + +- Direct `NCP 0x2222/32` / wire `0x20` is forwarded unchanged from + `src/nwconn.c` to `src/nwbind.c`, which passes `requestdata[0]` as the + semaphore subfunction and `requestdata[1..]` to `handle_func_0x20()` in + `src/sema.c`. +- The NetWare 2.x/3.x-compatible old semaphore subfunctions are now documented + at their real parser/reply site in `src/sema.c`: + - SDK `32/00` / wire subfunction `0x00` Open Semaphore (old) + - SDK `32/01` / wire subfunction `0x01` Examine Semaphore (old) + - SDK `32/02` / wire subfunction `0x02` Wait On Semaphore (old) + - SDK `32/03` / wire subfunction `0x03` Signal Semaphore (old) + - SDK `32/04` / wire subfunction `0x04` Close Semaphore (old) +- Request and response payloads were compared against the NDK/Core Protocols + PDF, the extracted WebSDK semaphore pages, and `nwsync.h`. The old `32/00` + through `32/04` operations line up with the currently implemented operation + set. + +Known differences / follow-up: + +- The PDF/WebSDK tables label `SemaphoreHandle` as long Lo-Hi. The current + `src/sema.c` implementation parses and emits semaphore handles with + `GET_BE32()` / `U32_TO_BE32()` while parsing `SemaphoreTimeOut` as Hi-Lo with + `GET_BE16()`. Keep this documented as a compatibility detail until packet + traces or client tests prove the expected wire order for MARS-NWE clients. +- `Wait On Semaphore` currently does not sleep until `SemaphoreTimeOut`; the + simple emulator returns timeout immediately when the semaphore value is not + available. +- Newer SDK `0x2222/111` semaphore calls are the modern paired variants and are + not routed through this compatibility handler. + + #### File Server Environment group 0x2222/23 Current status: diff --git a/src/sema.c b/src/sema.c index 43a1eab..584ff2e 100644 --- a/src/sema.c +++ b/src/sema.c @@ -171,8 +171,36 @@ int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) { int result = -0xfb; /* unknown request */ XDPRINTF((3, 0, "0x20 call ufunc=0x%x", ufunc)); + /* + * Direct NCP 0x2222/32 Semaphore group. nwconn.c forwards this + * group unchanged: requestdata[0] is SubFunctionCode and p points + * at requestdata[1], the subfunction payload. + * + * The uploaded NDK/Core Protocols PDF and WebSDK list the old + * NetWare 2.x/3.x-compatible semaphore subfunctions as SDK + * 32/00 through 32/04. The newer SDK 111 semaphore variants have + * the same semantic operations but are not routed here. + * + * Note the current wire-order compatibility detail before changing + * this code: the PDF tables label SemaphoreHandle as long Lo-Hi, + * while this handler currently reads and writes handles with the + * big-endian helpers GET_BE32()/U32_TO_BE32(). TimeOut remains + * documented and parsed Hi-Lo with GET_BE16(). + */ switch (ufunc) { case 0x0 : { /* open semaphore */ + /* + * SDK 32/00 / wire subfunction 0x00 Open Semaphore + * (old). + * Request payload after SubFunctionCode: + * byte InitialSemaphoreValue + * byte SemaphoreNameLen + * byte SemaphoreName[SemaphoreNameLen] + * Reply data: + * dword SemaphoreHandle (currently emitted with + * U32_TO_BE32(), see group note above) + * byte SemaphoreOpenCount + */ int value = *p; int namlen = *(p+1); uint8 *name = (p+2); @@ -204,6 +232,16 @@ int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) break; case 0x1 : { /* examine semaphore */ + /* + * SDK 32/01 / wire subfunction 0x01 Examine Semaphore + * (old). + * Request payload after SubFunctionCode: + * dword SemaphoreHandle (currently parsed with + * GET_BE32(), see group note above) + * Reply data: + * byte SemaphoreValue + * byte SemaphoreOpenCount + */ int handle = GET_BE32(p); struct XDATA { char value; @@ -224,6 +262,17 @@ int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) case 0x2 : { /* wait on semaphore */ + /* + * SDK 32/02 / wire subfunction 0x02 Wait On Semaphore + * (old). + * Request payload after SubFunctionCode: + * dword SemaphoreHandle (currently parsed with + * GET_BE32(), see group note above) + * word SemaphoreTimeOut (Hi-Lo) + * Reply: no data. Completion reports success, timeout, + * or lock error. The simple local emulator does not + * sleep; unavailable semaphores return timeout at once. + */ int handle = GET_BE32(p); int timeout = GET_BE16(p+4); result=wait_sema(handle, timeout); @@ -233,6 +282,14 @@ int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) break; case 0x3 : { /* signal sema */ + /* + * SDK 32/03 / wire subfunction 0x03 Signal Semaphore + * (old). + * Request payload after SubFunctionCode: + * dword SemaphoreHandle (currently parsed with + * GET_BE32(), see group note above) + * Reply: no data. + */ int handle = GET_BE32(p); result=signal_sema(handle); XDPRINTF((2, 0, "signal_sem:%d, result=%d", @@ -242,6 +299,14 @@ int handle_func_0x20(CONNECTION *c, uint8 *p, int ufunc, uint8 *responsedata) case 0x4 : { /* close semaphore */ + /* + * SDK 32/04 / wire subfunction 0x04 Close Semaphore + * (old). + * Request payload after SubFunctionCode: + * dword SemaphoreHandle (currently parsed with + * GET_BE32(), see group note above) + * Reply: no data. + */ int handle = GET_BE32(p); result=close_conn_sema(c, handle); if (!result)