Skip to content

Feature: --vmnet-disable-dhcp for shared mode (macOS 26), preserving NAT #166

Description

@fpolica91

Background

#139 / #140 added the ability to disable the vmnet DHCP server by joining an isolated vmnet-host network via vmnet_network_identifier_key. That works great when you want an isolated network, but it drops NAT — the guests lose outbound connectivity.

Use case

Running an external DHCP server (and/or DNS) on the guest L2 while keeping shared-mode NAT / internet for the guests. With vmnet's built-in DHCP (bootpd) active, the external DHCP server collides with it (duplicate offers / lease wars). The host-mode + network-identifier path avoids the collision but removes NAT, so it doesn't fit this case.

What macOS 26 added

macOS 26 introduced the vmnet_network_configuration_* API, including vmnet_network_configuration_disable_dhcp(), which disables the DHCP server while keeping shared-mode NAT. (Noted in #139 but intentionally not used there to avoid a 26-only dependency.)

Proposal

An opt-in --vmnet-disable-dhcp flag:

  • Default path is unchangedvmnet_start_interface with the existing xpc dict; zero behavior change for current users.
  • When the flag is set, the interface is started via the new vmnet_network_configuration API (...createset_ipv4_subnetdisable_dhcpvmnet_network_createvmnet_interface_start_with_network).
  • Dual-guarded so it still builds and runs everywhere:
    • compile-time: #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 260000
    • runtime: if (__builtin_available(macOS 26.0, *))
    • on older SDKs / OSes the flag errors cleanly (requires macOS 26) instead of breaking the build or crashing.
  • Adds an integration test that boots a guest through the flag and asserts it gets no DHCP lease (self-skips below macOS 26; the QEMU CI matrix already includes macos-26).

I have a branch implementing exactly this (single instance, no process-model changes). Before opening the PR:

  1. Would you be open to this as a 26-gated opt-in flag?
  2. Any preference on naming, or on restricting it to --vmnet-mode=shared?
  3. Any concerns with the @available + SDK-guard approach for backward compatibility?

Happy to adjust to fit your conventions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions