docs: document ncp22 quota and trustee layouts

This commit is contained in:
Mario Fetka
2026-06-01 20:32:01 +00:00
parent 017ef23833
commit cb4d9c8a9e
3 changed files with 187 additions and 35 deletions

58
TODO.md
View File

@@ -186,21 +186,23 @@ Follow-up:
Current status:
- `NCP 0x2222/22` is handled in `src/nwconn.c`, not forwarded to `nwbind.c`.
- `NCP 0x2222/22` is handled in `src/nwconn.c`, with selected quota-related
subfunctions forwarded to `src/nwbind.c` for bindery/ObjectID prehandling.
- The group header is documented inline as `SubFuncStrucLen` (Hi-Lo),
`SubFunctionCode`, and subfunction payload.
- The first NetWare 1.x/2.x/3.x-compatible directory services
subfunctions now have inline SDK request/reply layout documentation:
`22/00` Set Directory Handle, `22/01` Get Directory Path,
`22/02` Scan Directory Information, `22/03` Get Effective Directory Rights, `22/04` Modify Maximum Rights Mask, `22/05` Get
Volume Number, and `22/06` Get Volume Name.
`22/02` Scan Directory Information, `22/03` Get Effective Directory Rights,
`22/04` Modify Maximum Rights Mask, `22/05` Get Volume Number, and `22/06`
Get Volume Name.
- The old SDK PDF table for `22/00` repeats `TargetDirectoryHandle` for the
second payload byte, but the remarks describe a source handle; MARS-NWE
parses the byte as `SourceDirectoryHandle`. This is documented inline but
not changed.
- No NetWare 1.x/2.x/3.x SDK/PDF entries were found for direct `22/07`, `22/08`, or
`22/09` during this audit. The next documented direct directory calls
continue at `22/0a`.
- No NetWare 1.x/2.x/3.x SDK/PDF entries were found for direct `22/07`,
`22/08`, or `22/09` during this audit. The next documented direct directory
calls continue at `22/0a`.
- `22/0a` Create Directory, `22/0b` Delete Directory, `22/0d` Add Trustee to
Directory, `22/0e` Delete Trustee from Directory, and `22/0f` Rename
Directory now have inline request-layout documentation.
@@ -240,10 +242,29 @@ Current status:
- `22/1f` consumes the documented `DirectoryHandle`; legacy source comments
expected two extra unknown bytes after it, but the SDK request has no such
fields and the helper ignores them.
- `22/20` reads `VolumeNumber` and `Sequence` in the normal NCP 22 payload
positions. The WebSDK/PDF table for this call shows `VolumeNumber` one byte
later than the common group-header alignment; treat this as an offset
ambiguity until verified with a direct test caller.
- `22/20` reads `VolumeNumber` in the normal NCP 22 payload position, but the
WebSDK/PDF table for this call shows `VolumeNumber` one byte later than the
common group-header alignment. The code also reads `Sequence` with
`GET_BE32()` although the SDK/PDF documents Lo-Hi; treat both as audit items
until verified with a direct test caller.
- `22/21` Add User Disk Space Restriction, `22/22` Remove User Disk Space
Restrictions, `22/25` Set Directory Entry Information, `22/26` Scan File or
Directory for Extended Trustees, `22/27` Add Extended Trustee to Directory or
File, `22/28` Scan Directory Disk Space, and `22/29` Get Object Disk Usage
and Restrictions now have inline request/reply layout documentation.
- `22/21` and `22/22` are forwarded to `nwbind.c` for quota prehandling; both
layers are documented. The shared `nwbind` prehandler reads ObjectID from
the documented payload position.
- `22/26`, `22/27`, and `22/29` match the documented request payload offsets.
- `22/25` matches the documented payload field order, but the current parser
reads Sequence with `GET_BE32()` although the SDK/PDF documents Lo-Hi.
- `22/21` includes a documented DiskSpaceLimit field, but the current shared
quota prehandler in `nwbind.c` does not consume it before returning the
uid/gid/permission tuple.
- `22/28` matches the documented payload offsets, but the current parser reads
Sequence with `GET_BE32()` although the SDK/PDF documents Lo-Hi; it also
returns the normal directory scan structure from `nw_scan_a_directory()`
rather than the full documented Scan Directory Disk Space reply.
Follow-up:
@@ -266,10 +287,19 @@ Follow-up:
- Verify whether `22/1f` should continue accepting legacy callers that send the
two extra bytes described by the old source comment, even though the SDK
request only contains `DirectoryHandle`.
- Verify `22/20` VolumeNumber offset against a direct test caller; the WebSDK
table appears shifted by one byte compared with the normal NCP 22 group
header and the current parser.
- Continue the `0x2222/22` audit from `22/21` Add User Disk Space Restriction
- Verify `22/20` VolumeNumber offset and Sequence byte order against a direct
test caller; the WebSDK table appears shifted by one byte compared with the
normal NCP 22 group header, and current code uses `GET_BE32()` although the
SDK/PDF documents Lo-Hi.
- Decide whether `22/21` should pass the documented DiskSpaceLimit through the
quota prehandling path or whether the current behavior is intentionally
handled later in the quota backend.
- Verify `22/25` Sequence byte order; current code uses `GET_BE32()` although
the SDK/PDF documents Lo-Hi.
- Verify `22/28` Sequence byte order and reply shape; current code uses
`GET_BE32()` and delegates to the normal directory scan reply rather than the
documented Scan Directory Disk Space reply.
- Continue the `0x2222/22` audit from `22/30` Get Name Space Directory Entry
onward, keeping each patch to a small logical endpoint block.

View File

@@ -756,10 +756,24 @@ static void handle_fxx(int gelen, int func)
} else if (0x16 == func) {
switch (ufunc) {
/* QUOTA support from: Matt Paley */
case 0x21 : /* Change volume restrictions */
case 0x22 : /* Remove volume restrictions */
case 0x29 : { /* Read volume restrictions */
/* Returns 3 integers, uid, gid, 0=OK/1=Permission denied */
case 0x21 : /* Add User Disk Space Restriction, 0x2222/22/33 */
case 0x22 : /* Remove User Disk Space Restrictions, 0x2222/22/34 */
case 0x29 : { /* Get Object Disk Usage And Restrictions, 0x2222/22/41 */
/*
* Forwarded from src/nwconn.c NCP 0x2222/22. The shared quota
* prehandler sees only the subfunction payload as rdata:
*
* rdata[0] VolumeNumber
* rdata[1..4] ObjectID (Hi-Lo)
* rdata[5..8] DiskSpaceLimit (Lo-Hi, only for 22/33)
*
* Parser comparison: ObjectID is read from the documented position
* for all three subfunctions. DiskSpaceLimit for 22/33 is not
* consumed by this prehandler; handle_after_bind() receives only the
* uid/gid/permission tuple produced below.
*
* Returns 3 integers, uid, gid, 0=OK/1=Permission denied.
*/
uint32 id = GET_BE32(rdata+1);
internal_act=1;
if (get_guid((int*) responsedata, (int*)(responsedata+sizeof(int)),

View File

@@ -4229,12 +4229,12 @@ static int handle_ncp_serv(void)
* entries per call.
*
* Parser comparison: current parser reads VolumeNumber from
* the first payload byte and Sequence as Lo-Hi via GET_32().
* The Micro Focus WebSDK table shows VolumeNumber one byte
* later than the normal NCP 22 group header would imply; the
* local parser follows the common group-header alignment.
* This offset ambiguity is recorded in TODO for direct-test
* verification.
* the first payload byte and Sequence with GET_BE32(), while
* the SDK/PDF documents Sequence as Lo-Hi. The Micro Focus
* WebSDK table shows VolumeNumber one byte later than the
* normal NCP 22 group header would imply; the local parser
* follows the common group-header alignment. Both items are
* recorded in TODO for direct-test verification.
*
* The Rust nwserver and lwared implementations both return
* an empty list after validating the volume. MARS-NWE keeps
@@ -4252,22 +4252,70 @@ static int handle_ncp_serv(void)
}
break;
case 0x21 : { /* change Vol restrictions for Obj */
case 0x21 : { /* Add User Disk Space Restriction */
/*
* NCP 0x2222/22/33 Add User Disk Space Restriction.
*
* SDK request payload after the group header:
* byte VolumeNumber
* long ObjectID (Hi-Lo)
* long DiskSpaceLimit (Lo-Hi, 4K blocks)
*
* SDK completion: 0x00 success, 0x8c no set privileges,
* 0x96 server out of memory, 0x98 disk map error.
*
* Parser comparison: this dispatcher only recognizes the
* subfunction and forwards prehandling to nwbind. The
* forwarded parser in src/nwbind.c maps ObjectID from the
* documented payload position, but the current quota
* prehandle does not consume DiskSpaceLimit. That is
* recorded in TODO for a behavior audit; this comment does
* not change wire behavior.
*/
XDPRINTF((5, 0, "Change vol restrictions"));
}
return(-2); /* nwbind must do prehandling */
case 0x22 : { /* remove Vol restrictions for Obj */
case 0x22 : { /* Remove User Disk Space Restrictions */
/*
* NCP 0x2222/22/34 Remove User Disk Space Restrictions.
*
* SDK request payload after the group header:
* byte VolumeNumber
* long ObjectID (Hi-Lo)
*
* SDK completion: 0x00 success, 0x8c no set privileges,
* 0xfe user not found.
*
* Parser comparison: this dispatcher forwards the call to
* nwbind, whose quota prehandler reads ObjectID from the
* documented payload position.
*/
XDPRINTF((5, 0, "Remove vol restrictions"));
}
return(-2); /* nwbind must do prehandling */
case 0x25 : { /* Set Entry, Set Directory File Information
* sets or changes the file or directory information to the
* values entered in 'Change Bits'.
* NO REPLY
* used by ncopy.exe, flag.exe
*/
case 0x25 : { /* Set Directory Entry Information */
/*
* NCP 0x2222/22/37 Set Directory Entry Information.
*
* SDK request payload after the group header:
* byte DirHandle
* byte SearchAttributes
* long Sequence (Lo-Hi)
* long ChangeBits (Lo-Hi)
* ... DOS file/directory or Macintosh namespace entry
*
* SDK completion: 0x00 success, 0x01 invalid parameter,
* 0x8c no set privileges, 0xbf invalid name space.
*
* Parser comparison: current struct layout matches the
* documented field order and fixed 148-byte payload, but it
* reads Sequence with GET_BE32() while the SDK documents
* Sequence as Lo-Hi. ChangeBits is handled later by
* nw_set_a_directory_entry() as Lo-Hi. This endpoint is
* used by ncopy.exe and flag.exe.
*/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, ufunc */
@@ -4295,7 +4343,27 @@ static int handle_ncp_serv(void)
}
break;
case 0x26 : { /* Scan file or Dir for ext trustees */
case 0x26 : { /* Scan File or Directory for Extended Trustees */
/*
* NCP 0x2222/22/38 Scan File or Directory for Extended
* Trustees.
*
* SDK request payload after the group header:
* byte DirHandle
* byte Sequence
* byte PathLen
* byte Path[PathLen]
*
* SDK reply payload:
* byte NumberOfEntries
* long ObjectID[20] (Hi-Lo)
* word TrusteeRights[20]
*
* Parser comparison: current parser and reply layout match
* the documented payload offsets. Rights are converted
* from mars_nwe trustee bits back to the NCP 22 mask before
* serialization.
*/
int sequence = (int)*(p+2); /* trustee sequence */
struct XDATA {
uint8 entries;
@@ -4331,7 +4399,23 @@ static int handle_ncp_serv(void)
}
break;
case 0x27 : { /* Add Ext Trustees to DIR or File */
case 0x27 : { /* Add Extended Trustee to Directory or File */
/*
* NCP 0x2222/22/39 Add Extended Trustee to Directory or
* File.
*
* SDK request payload after the group header:
* byte DirHandle
* long ObjectID (Hi-Lo)
* word TrusteeRights (Lo-Hi)
* byte PathLen
* byte Path[PathLen]
*
* Parser comparison: current parser matches the documented
* payload layout and converts the NCP 22 rights mask to the
* internal trustee-rights representation before calling the
* existing trustee backend.
*/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, ufunc */
@@ -4370,7 +4454,28 @@ static int handle_ncp_serv(void)
}
break;
case 0x28 : { /* Scan File Physical ??? */
case 0x28 : { /* Scan Directory Disk Space */
/*
* NCP 0x2222/22/40 Scan Directory Disk Space.
*
* SDK request payload after the group header:
* byte DirectoryHandle
* byte SearchAttributes
* long Sequence (Lo-Hi)
* byte SearchPatternLen
* byte SearchPattern[SearchPatternLen]
*
* SDK reply is the extended disk-space scan entry, including
* Sequence, data/resource fork size, deleted-file fields,
* inherited rights, and namespace fork-size data.
*
* Parser comparison: current payload offsets match, but the
* Sequence is read with GET_BE32() while the SDK documents
* Lo-Hi. The current implementation delegates to
* nw_scan_a_directory(), returning the normal directory-scan
* structure rather than the full documented disk-space scan
* reply. Both differences are recorded in TODO.
*/
struct INPUT {
uint8 header[7]; /* Requestheader */
uint8 div[3]; /* 0x0, dlen, ufunc */
@@ -4410,6 +4515,9 @@ static int handle_ncp_serv(void)
* handle_after_bind() calls nw_get_vol_restrictions(). Without
* quota support, keep the SDK-compatible fallback local so builds
* on hosts without quota support do not need the quota backend.
*
* Parser comparison: request payload is VolumeNumber followed by
* ObjectID (Hi-Lo), matching the documented layout.
*/
case 0x29 : { /* Get Object Disk Usage And Restrictions */
#if QUOTA_SUPPORT