Skip to content

List the DFS namespaces a domain hosts #13

Open

Description

@vdavid

Context

SmbClient::connect_share opens a domain-based DFS namespace like \\example.com\namespace when the caller already
knows its name. SmbClient::list_shares (IPC$ + the srvsvc pipe, NetShareEnumAll) is how a caller discovers what
exists on a server, and against a domain name it legitimately returns zero disk shares: namespaces aren't shares.

MS-DFSC, the referral protocol this crate speaks, has no operation that lists namespaces. That lives in a different
protocol, MS-DFSNM (DFS namespace management), as NetrDfsEnumEx over the netdfs named pipe. The crate already has a
small DCE/RPC layer (crates/smb2/src/rpc/) that does exactly this dance for srvsvc.

crates/smb2/README.md § Limitations lists this as unsupported.

Problem

A person browsing a network in a file manager types \\example.com, sees nothing, and has no way to find out that
\\example.com\projects exists unless someone tells them. Windows Explorer lists a domain's namespaces when you browse
the domain name. This is the exact shape of the first field report that led to namespace-root support: the domain answered, listed no
shares, and the consumer concluded there was nothing there.

Solution

Add a netdfs RPC client beside srvsvc and a public call that returns the namespaces a domain (or a standalone
namespace server) hosts.

For the implementer

  • Fetch the spec first: MS-DFSNM via the curl recipe in AGENTS.md § "Spec files". Read NetrDfsEnumEx (the
    method list in § 3.1.4 gives its opnum), the DFS_INFO_* levels it returns (§ 2.2.4), and the interface UUID in
    § 1.9. Level 200 (DFS_INFO_200, the namespace name only) is enough to list domain-based namespaces; level 300 adds
    standalone ones.
  • crates/smb2/src/rpc/: add netdfs.rs next to srvsvc.rs, reusing mod.rs's BIND / REQUEST / RESPONSE framing and
    the fragment reassembly in client/shares.rs (read_pipe_message, parse_response_fragment). Plain NDR only, as
    rpc/CLAUDE.md explains.
  • crates/smb2/src/client/: a namespaces.rs mirroring shares.rs (connect IPC$, open netdfs, bind, call, close),
    and a public SmbClient method. Reuse the connection's cached IPC$ tree the way client/dfs.rs::get_dfs_referral
    does.
  • For a domain, NetrDfsEnumEx is answered by a DC; the connection to the domain name normally lands on one already, the same
    way the root referral does.
  • Tests: known-bytes NDR tests for the request and a captured response; a mock-transport flow test in the new module.
    Samba implements netdfs only partially, so check whether smb-dfs-namespace (crates/smb2/tests/docker/internal/)
    answers NetrDfsEnumEx before promising a Docker test; the real proof is the Windows setup from the "Verify DFS
    namespace roots against a real Windows domain" issue.
  • Update README.md § Limitations, client/CLAUDE.md § DFS, and rpc/CLAUDE.md.

Open questions

  1. Where should the namespaces show up in the API? (a) A separate SmbClient::list_dfs_namespaces() returning
    names. (b) Fold them into list_shares() as entries with a new ShareInfo kind. (a) keeps list_shares honest
    (it means NetShareEnumAll, which consumers already understand) and lets a consumer decide when to pay for the
    second RPC; (b) is less work for a consumer that only wants "what can I open here?". I'd go with (a) and let Cmdr
    merge the two lists in its own UI.
  2. Is this worth doing before the Windows verification lands? It can't be tested for real without a Windows DC, so
    I'd sequence it after that issue.

Impact: Makes domain DFS namespaces discoverable instead of only reachable by name · Size: L (a new RPC
interface, NDR encoding for its structures, and a Windows test run)

Origin: DFS namespace root plan § Follow-up work, deliberately out of scope

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    claude-createddfsMicrosoft's Distributed File System

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions