diff --git a/TODO.md b/TODO.md index 8c41f71..e134eb8 100644 --- a/TODO.md +++ b/TODO.md @@ -126,6 +126,9 @@ Current status: - `NCP 0x12 Get Volume Info with Number`, `NCP 0x13 Get Station Number`, `NCP 0x14 Get File Server Date And Time`, and the `NCP 0x15` message group handoff now have inline SDK request/reply layout documentation. +- The forwarded `NCP 0x15` message subfunctions in `src/nwbind.c` now have + inline SDK request/reply layout documentation for broadcast send/get, + enable/disable, and console broadcast calls. - `NCP 0x13 Get Station Number` is documented by the SDK as a three-byte StationNumber reply; MARS-NWE currently returns only the low one-byte connection number. This parser/reply difference is documented inline but not @@ -150,6 +153,10 @@ Follow-up: `LockFlag` byte after direct requester evidence is available. - Verify whether the current one-byte `0x13` reply is required by old clients or whether the SDK three-byte StationNumber reply should be implemented. +- Verify whether `NCP 0x2222/21/10 Send Broadcast Message` must accept the + SDK-documented long connection list and return long completion flags, or + whether the current 16-bit connection list plus byte status reply is the + requester-compatible format used by the clients MARS-NWE supports. - Verify the implemented file/logical-record/physical-record calls against the Novell SDK request/reply layouts and a real DOS requester or direct test caller. diff --git a/src/nwbind.c b/src/nwbind.c index 22be1fc..1cc31ff 100644 --- a/src/nwbind.c +++ b/src/nwbind.c @@ -586,8 +586,42 @@ static void handle_fxx(int gelen, int func) // ) if (0x15 == func) { + /* + * NCP 0x2222/21 is the Message NCP function group forwarded from + * nwconn.c. For this group the old/new SDK request header is: + * + * word SubFuncStrucLen (Hi-Lo) + * byte SubFunctionCode + * ... subfunction payload + * + * handle_fxx() has already consumed that group header here: + * + * ufunc = requestdata[2] + * rdata = requestdata + 3 + * + * Therefore all offsets below are relative to the first byte after + * SubFunctionCode. The code keeps the existing wire behavior; comments + * record the SDK layout and any parser differences only. + */ switch (ufunc) { /* Messages */ case 0x0 : { /* Send Broadcast Message (old) */ + /* + * NCP 0x2222/21/00 Send Broadcast Message (old). + * SDK payload after SubFunctionCode: + * + * byte ClientListLen + * byte TargetClientList[ClientListLen] + * byte MessageLen + * byte Message[MessageLen] + * + * SDK reply payload: + * + * byte ClientListLen + * byte SendStatus[ClientListLen] + * + * MARS-NWE parses the old one-byte connection list as documented and + * returns one status byte per target. + */ int count_conns = (int)*(rdata); /* Number of connections */ uint8 *conns = rdata+1; /* connectionslist */ int msglen = *(conns+count_conns); @@ -609,6 +643,17 @@ static void handle_fxx(int gelen, int func) break; case 0x01: { /* Get Broadcast Message (old) */ + /* + * NCP 0x2222/21/01 Get Broadcast Message (old). + * SDK payload after SubFunctionCode: empty. + * SDK reply payload: + * + * byte MessageLen + * byte Message[MessageLen] + * + * The stored per-connection broadcast buffer is returned and then + * cleared. + */ *responsedata = (uint8) strmaxcpy(responsedata+1, act_c->message, 58); act_c->message[0] = '\0'; data_len = (int)(*responsedata) + 1; @@ -616,16 +661,36 @@ static void handle_fxx(int gelen, int func) break; case 0x02: { /* Disable Broadcasts */ + /* + * NCP 0x2222/21/02 Disable Broadcasts. + * SDK payload after SubFunctionCode: empty. + * Completion-only success reply. + */ act_c->broadcast_disabled = 1; } break; case 0x03: { /* Enable Broadcasts */ + /* + * NCP 0x2222/21/03 Enable Broadcasts. + * SDK payload after SubFunctionCode: empty. + * Completion-only success reply. + */ act_c->broadcast_disabled = 0; } break; case 0x09: { /* Broadcast to CONSOLE */ + /* + * NCP 0x2222/21/09 Broadcast To Console. + * SDK payload after SubFunctionCode: + * + * byte MessageLen + * byte Message[MessageLen] + * + * Completion-only success reply. The current implementation logs the + * message text locally with the existing stderr console behavior. + */ char message[60]; strmaxcpy(message, rdata+1, min(59, *rdata)); fprintf(stderr, "\n:%s\n", message); @@ -633,6 +698,25 @@ static void handle_fxx(int gelen, int func) break; case 0x0a: { /* Send Broadcast Message (new) */ + /* + * NCP 0x2222/21/10 Send Broadcast Message. + * SDK payload after SubFunctionCode: + * + * word ClientListCount + * long ClientList[ClientListCount] + * byte MessageLen + * byte Message[MessageLen] + * + * SDK reply payload: + * + * word RClientListCount + * long RClientCompFlag[ClientListCount] + * + * MARS-NWE currently keeps the historical in-tree parser: it reads a + * big-endian 16-bit count, then 16-bit connection numbers, and returns + * one status byte per target after the echoed count. This parser + * difference is documented only, not changed here. + */ int count_conns = GET_BE16(rdata); uint8 *conns = rdata+2; int msglen = *(conns + count_conns*2); @@ -650,6 +734,17 @@ static void handle_fxx(int gelen, int func) break; case 0x0b: { /* Get Broadcast Message (new) */ + /* + * NCP 0x2222/21/11 Get Broadcast Message. + * SDK payload after SubFunctionCode: empty. + * SDK reply payload: + * + * byte MessageLen + * byte Message[MessageLen] + * + * Like the old get call, the current implementation returns and clears + * the per-connection broadcast buffer. + */ *responsedata = (uint8) strmaxcpy(responsedata+1, act_c->message, 58); act_c->message[0] = '\0'; data_len = (int)(*responsedata) + 1; diff --git a/src/nwconn.c b/src/nwconn.c index c2e1cad..fc8a4f0 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -3230,6 +3230,13 @@ static int handle_ncp_serv(void) * ... subfunction-specific payload * * This direct dispatcher deliberately leaves the group to nwbind. + * See src/nwbind.c handle_fxx(func == 0x15) for the documented + * message subfunction layouts. The nwbind pre-parser consumes the + * three-byte group header above as: + * + * requestdata[0..1] SubFuncStrucLen + * requestdata[2] SubFunctionCode + * requestdata[3..] subfunction payload passed as rdata */ return(-1); /* nwbind must do this call */