1
0
mirror of https://github.com/open-simh/simh.git synced 2026-02-27 01:10:17 +00:00

Revert vmnet support, PR #443

This reverts commits 361ef76d through 6fd146ae.
This commit is contained in:
Paul Koning
2025-08-27 15:52:55 -04:00
parent c20b391eea
commit c064bb6676
6 changed files with 0 additions and 350 deletions

View File

@@ -213,79 +213,6 @@ Note: As mentioned above, NAT networking is specifically capable of providing
packets.
-------------------------------------------------------------------------------
Another alternative to pcap and tun/tap on macOS is using the vmnet framework.
The vmnet framework provides simh a way to provide emulated systems networking,
without requiring any additional software. Because tun/tap support requires
third-party kernel extensions (which is heavily discouraged by Apple), this
provides an equivalent that doesn't require reducing OS security.
vmnet provides Layer 2 networking, so things like DECnet and MOP will work
properly, even across multiple systems. It can be used to either bridge to a
physical network, or provide a virtual network for systems, including NAT.
simh must be running as root. (Running without root is possible if simh is a
notarized application. You're very unlikely to be building simh like this, so
de facto it needs root.) vmnet.framework requires macOS 10.10; macOS 10.15 is
required for bridged networking.
When attaching an ethernet device, you have three options available:
- "vmnet:host": This provides "host-only" networking. It allows the system to
talk to the host Mac, as well as other emulated systems on the host-only VM
network.
- "vmnet:shared": This extends the host-only network to add NAT, using the
host as a gateway.
- "vmnet:<device>": This bridges vmnet to a physical network. You must
specify a valid network device to use.
You can use SHOW ETHERNET in SCP to see what devices are allowed to be
bridged; these are likely your Ethernet and Wi-Fi devices.
sim> show eth
ETH devices:
eth0 vmnet:en0
eth1 vmnet:en7
eth2 udp:sourceport:remotehost:remoteport
sim> attach xq vmnet:en0
You can verify with i.e. "ifconfig" to see if this is the correct interface
to bridge to.
When using the host and shared modes, the host system create an IPv4 and v6
subnet for the emulated systems. macOS will provide DHCP and other discovery
protocols on the virtual network as well. To see what IP and subnet the host
has claimed, you can use "ifconfig" to display it; macOS will bind its IP to
the bridgeN device, with the simh instance having its own vmenetN device joined
to that bridgeN device:
vmenet0: flags=8963<UP,BROADCAST,SMART,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
options=60<TSO4,TSO6>
ether a6:94:63:7e:f3:04
media: autoselect
status: active
bridge100: flags=8a63<UP,BROADCAST,SMART,RUNNING,ALLMULTI,SIMPLEX,MULTICAST> mtu 1500
options=3<RXCSUM,TXCSUM>
ether b2:f1:d8:65:66:64
inet 192.168.67.1 netmask 0xffffff00 broadcast 192.168.67.255
inet6 fe80::b0f1:d8ff:fe65:6664%bridge100 prefixlen 64 scopeid 0x23
inet6 fd91:d62b:63cd:ec3d:4ad:c40c:d0b8:5826 prefixlen 64 autoconf secured
Configuration:
id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
ipfilter disabled flags 0x0
member: vmenet0 flags=3<LEARNING,DISCOVER>
ifmaxaddr 0 port 34 priority 0 path cost 0
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
Currently, settings like the subnet ranges nor port forwarding are controllable
via simh. For finer grained control over how systems are addressed, you can use
a bridged network instead of a host-only or shared network. These settings are
provided by macOS, so a future version of simh may be able to adopt these.
-------------------------------------------------------------------------------
Windows notes:

View File

@@ -199,9 +199,6 @@ option(WITH_VDE
option(WITH_TAP
"Enable (=1)/disable (=0) TAP/TUN device network support. (def: enabled)"
TRUE)
option(WITH_VMNET
"Enable (=1)/disable (=0) macOS vmnet.framework network support. (def: enabled)"
TRUE)
option(WITH_VIDEO
"Enable (=1)/disable (=0) simulator display and graphics support (def: enabled)"
TRUE)

View File

@@ -351,36 +351,6 @@ if (WITH_NETWORK)
list(APPEND NETWORK_PKG_STATUS "NAT(SLiRP)")
endif (WITH_SLIRP)
if (WITH_VMNET AND APPLE)
# CMAKE_OSX_DEPLOYMENT_TARGET is attractive, but not set by default.
# See what we're using, either by default or what the user has set.
check_c_source_compiles(
"
#include <Availability.h>
#if TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000
#error macOS too old
#endif
int main(int argc, char **argv) { return 0; }
" TARGETING_MACOS_10_10)
if (NOT TARGETING_MACOS_10_10)
message(FATAL_ERROR "vmnet.framework requires targeting macOS 10.10 or newer")
endif()
# vmnet requires blocks for its callback parameter, even in vanilla C.
# This is only supported in clang, not by GCC. It's default in clang,
# but we should be clear about it. Do a feature instead of compiler
# check anyways though, in case GCC does add it eventually.
check_c_compiler_flag(-fblocks HAVE_C_BLOCKS)
if (NOT HAVE_C_BLOCKS)
message(FATAL_ERROR "vmnet.framework requires blocks support in the C compiler")
endif()
target_compile_options(simh_network INTERFACE -fblocks)
target_link_libraries(simh_network INTERFACE "-framework vmnet")
target_compile_definitions(simh_network INTERFACE HAVE_VMNET_NETWORK)
list(APPEND NETWORK_PKG_STATUS "macOS vmnet.framework")
endif(WITH_VMNET AND APPLE)
## Finally, set the network runtime
if (NOT network_runtime)
## Default to USE_SHARED... USE_NETWORK is deprecated.

View File

@@ -1063,13 +1063,6 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
NETWORK_CCDEFS += -DUSE_NETWORK
endif
endif
# XXX: Check for the target version of macOS, check for -fblocks
ifeq (Darwin,$(OSTYPE))
# Provide support for macOS vmnet.framework (requires 10.10)
NETWORK_CCDEFS += -fblocks -DHAVE_VMNET_NETWORK
NETWORK_LAN_FEATURES += vmnet.framework
NETWORK_LDFLAGS += -framework vmnet
endif
ifeq (slirp,$(shell if ${TEST} -e slirp_glue/sim_slirp.c; then echo slirp; fi))
NETWORK_CCDEFS += -Islirp -Islirp_glue -Islirp_glue/qemu -DHAVE_SLIRP_NETWORK -DUSE_SIMH_SLIRP_DEBUG slirp/*.c slirp_glue/*.c
NETWORK_LAN_FEATURES += NAT(SLiRP)

View File

@@ -381,11 +381,6 @@
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
// Declare earlier than other implementations
#ifdef HAVE_VMNET_NETWORK
#include <vmnet/vmnet.h>
#endif
/* Internal routine - forward declaration */
static int _eth_get_system_id (char *buf, size_t buf_size);
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on);
@@ -1018,9 +1013,6 @@ const char *eth_capabilities(void)
#endif
#if defined (HAVE_SLIRP_NETWORK)
":NAT"
#endif
#if defined (HAVE_VMNET_NETWORK)
":VMNET"
#endif
":UDP";
}
@@ -1212,42 +1204,6 @@ if (used < max) {
++used;
}
#endif
#ifdef HAVE_VMNET_NETWORK
if (used < max) {
sprintf(list[used].name, "%s", "vmnet:shared");
sprintf(list[used].desc, "%s", "Integrated NAT (vmnet.framework) support");
list[used].eth_api = ETH_API_VMN;
++used;
}
if (used < max) {
sprintf(list[used].name, "%s", "vmnet:host");
sprintf(list[used].desc, "%s", "Integrated host-only network (vmnet.framework) support");
list[used].eth_api = ETH_API_VMN;
++used;
}
// vmnet.framework has an allowed list of devices for bridging
// handy for user if we list them since ifconfig is noisy
#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500)
if (__builtin_available(macOS 10.15, *)) {
// avoid putting a __block marker on used on other platforms
__block int used_block;
xpc_object_t bridge_list = vmnet_copy_shared_interface_list();
xpc_array_apply(bridge_list, ^bool(size_t index, xpc_object_t value) {
if (used_block < max) {
sprintf(list[used_block].name, "%s%s", "vmnet:", xpc_string_get_string_ptr(value));
sprintf(list[used_block].desc, "%s", "Integrated bridged network (vmnet.framework) support");
list[used_block].eth_api = ETH_API_VMN;
++used_block;
}
return true;
});
used = used_block;
xpc_release(bridge_list);
}
#endif
#endif
if (used < max) {
sprintf(list[used].name, "%s", "udp:sourceport:remotehost:remoteport");
@@ -1813,10 +1769,6 @@ return tool;
static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on)
{
// we set this at interface creation time in open_port for vmnet
if (dev->eth_api == ETH_API_VMN) {
return;
}
memset(&dev->host_nic_phy_hw_addr, 0, sizeof(dev->host_nic_phy_hw_addr));
dev->have_host_nic_phy_addr = 0;
if (dev->eth_api != ETH_API_PCAP)
@@ -2116,37 +2068,6 @@ while (dev->handle) {
}
break;
#endif /* HAVE_VDE_NETWORK */
#ifdef HAVE_VMNET_NETWORK
case ETH_API_VMN:
{
vmnet_return_t ret;
int count = 1;
struct pcap_pkthdr header;
struct vmpktdesc pkt_desc;
struct iovec iov;
// XXX: Should be MTU returned from vmnet startup?
u_char buf[ETH_MAX_JUMBO_FRAME];
iov.iov_base = buf;
iov.iov_len = ETH_MAX_JUMBO_FRAME;
pkt_desc.vm_pkt_size = ETH_MAX_JUMBO_FRAME;
pkt_desc.vm_pkt_iov = &iov;
pkt_desc.vm_pkt_iovcnt = 1;
pkt_desc.vm_flags = 0;
ret = vmnet_read((interface_ref)dev->handle, &pkt_desc, &count);
if (ret == VMNET_SUCCESS && count > 0) {
status = 1;
header.caplen = header.len = pkt_desc.vm_pkt_size;
_eth_callback((u_char *)dev, &header, buf);
} else {
status = ret == VMNET_SUCCESS ? 0 : -1;
}
}
break;
#endif
#ifdef HAVE_SLIRP_NETWORK
case ETH_API_NAT:
sim_slirp_dispatch ((SLIRP*)dev->handle);
@@ -2331,87 +2252,6 @@ if (bufsz < ETH_MAX_JUMBO_FRAME)
/* attempt to connect device */
memset(errbuf, 0, PCAP_ERRBUF_SIZE);
if (0 == strncmp("vmnet:", savname, 6)) {
#if defined(HAVE_VMNET_NETWORK)
xpc_object_t if_desc;
dispatch_queue_t vmn_queue;
interface_ref vmn_interface;
// __block is used so it can be captured in the callback
__block vmnet_return_t vmn_status;
// Because vmnet operates via callbacks, set up a semaphore to block on
dispatch_semaphore_t cb_finished;
const char *devname = savname + sizeof("vmnet:") - 1;
if_desc = xpc_dictionary_create(NULL, NULL, 0);
if (0 == strcmp(devname, "shared")) {
xpc_dictionary_set_uint64(if_desc, vmnet_operation_mode_key, VMNET_SHARED_MODE);
} else if (0 == strcmp(devname, "host")) {
xpc_dictionary_set_uint64(if_desc, vmnet_operation_mode_key, VMNET_HOST_MODE);
#if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500)
} else if (strlen(devname) > 0) { // Bridged, this is the device name
if (__builtin_available(macOS 10.15, *)) {
xpc_dictionary_set_uint64(if_desc, vmnet_operation_mode_key, VMNET_BRIDGED_MODE);
xpc_dictionary_set_string(if_desc, vmnet_shared_interface_name_key, devname);
} else {
xpc_release(if_desc);
return sim_messagef (SCPE_OPENERR, "Eth: You must be using macOS 10.15 or newer for bridged devices\n");
}
#endif
} else {
if (__builtin_available(macOS 10.15, *)) {
xpc_release(if_desc);
return sim_messagef (SCPE_OPENERR, "Eth: You must pick either shared, host, or an allowed bridge device\n");
} else {
xpc_release(if_desc);
return sim_messagef (SCPE_OPENERR, "Eth: You must pick either shared or host\n");
}
}
vmn_queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
cb_finished = dispatch_semaphore_create(0);
// Set the MAC address
__block ETH_DEV *eth_dev = (ETH_DEV*)opaque;
vmn_interface = vmnet_start_interface(if_desc, vmn_queue, ^(vmnet_return_t status, xpc_object_t params){
vmn_status = status;
if (vmn_status == VMNET_SUCCESS) {
// Scan like eth_scan_mac but simplified (only one format)
const char *mac_string = xpc_dictionary_get_string(params, vmnet_mac_address_key);
int a[6];
if (6 == sscanf(mac_string, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) {
eth_dev->have_host_nic_phy_addr = 1;
eth_dev->host_nic_phy_hw_addr[0] = a[0];
eth_dev->host_nic_phy_hw_addr[1] = a[1];
eth_dev->host_nic_phy_hw_addr[2] = a[2];
eth_dev->host_nic_phy_hw_addr[3] = a[3];
eth_dev->host_nic_phy_hw_addr[4] = a[4];
eth_dev->host_nic_phy_hw_addr[5] = a[5];
}
}
dispatch_semaphore_signal(cb_finished);
});
dispatch_semaphore_wait(cb_finished, DISPATCH_TIME_FOREVER);
dispatch_release(cb_finished);
xpc_release(if_desc);
if (vmn_status != VMNET_SUCCESS) {
return sim_messagef (SCPE_OPENERR, "Eth: Failed to create vmnet (vmnet_return_t: %d)\n", vmn_status);
}
*eth_api = ETH_API_VMN;
*handle = (void *)vmn_interface; /* Flag used to indicated open */
return SCPE_OK;
#else
return sim_messagef (SCPE_OPENERR, "Eth: No support for vmnet devices\n");
#endif
}
if (0 == strncmp("tap:", savname, 4)) {
int tun = -1; /* TUN/TAP Socket */
int on = 1;
@@ -2814,15 +2654,6 @@ switch (eth_api) {
case ETH_API_NAT:
sim_slirp_close((SLIRP*)pcap);
break;
#endif
#ifdef HAVE_VMNET_NETWORK
case ETH_API_VMN:
{
dispatch_queue_t stop_queue;
stop_queue = dispatch_get_global_queue(QOS_CLASS_UTILITY, 0);
vmnet_stop_interface((interface_ref)pcap, stop_queue, ^(vmnet_return_t status){});
}
break;
#endif
case ETH_API_UDP:
sim_close_sock(pcap_fd);
@@ -2920,11 +2751,6 @@ fprintf (st, " eth2 vde:device{:switch-port-number} (Integrated VDE su
fprintf (st, " eth3 nat:{optional-nat-parameters} (Integrated NAT (SLiRP) support)\n");
#endif
fprintf (st, " eth4 udp:sourceport:remotehost:remoteport (Integrated UDP bridge support)\n");
#if defined(HAVE_VMNET_NETWORK)
fprintf (st, " eth6 vmnet:shared (Integrated NAT (vmnet.framework) support)\n");
fprintf (st, " eth7 vmnet:host (Integrated host-only (vmnet.framework) support)\n");
fprintf (st, " eth8 vmnet:device-name (Integrated bridged (vmnet.framework) support)\n");
#endif
fprintf (st, " sim> ATTACH %s eth0\n\n", dptr->name);
fprintf (st, "or equivalently:\n\n");
fprintf (st, " sim> ATTACH %s en0\n\n", dptr->name);
@@ -3141,9 +2967,6 @@ switch (dev->eth_api) {
case ETH_API_NAT:
netname = "nat";
break;
case ETH_API_VMN:
netname = "vmnet";
break;
}
sprintf(msg, "%s(%s): ", where, netname);
switch (dev->eth_api) {
@@ -3151,12 +2974,6 @@ switch (dev->eth_api) {
case ETH_API_PCAP:
sim_printf ("%s%s\n", msg, pcap_geterr ((pcap_t*)dev->handle));
break;
#endif
#if defined(HAVE_VMNET_NETWORK)
case ETH_API_VMN:
/* XXX: vmnet errors aren't global */
sim_printf ("%s\n", msg);
break;
#endif
default:
sim_err_sock (INVALID_SOCKET, msg);
@@ -3278,27 +3095,6 @@ if ((packet->len >= ETH_MIN_PACKET) && (packet->len <= ETH_MAX_PACKET)) {
else
status = 1;
break;
#endif
#ifdef HAVE_VMNET_NETWORK
case ETH_API_VMN:
{
vmnet_return_t ret;
int count = 1;
struct vmpktdesc pkt_desc;
struct iovec iov;
iov.iov_base = packet->msg;
iov.iov_len = packet->len;
pkt_desc.vm_pkt_size = packet->len;
pkt_desc.vm_pkt_iov = &iov;
pkt_desc.vm_pkt_iovcnt = 1;
pkt_desc.vm_flags = 0;
ret = vmnet_write((interface_ref)dev->handle, &pkt_desc, &count);
status = (ret == VMNET_SUCCESS && count > 0) ? 0 : 1;
}
break;
#endif
case ETH_API_UDP:
status = (((int32)packet->len == sim_write_sock (dev->fd_handle, (char *)packet->msg, (int32)packet->len)) ? 0 : -1);
@@ -3919,7 +3715,6 @@ switch (dev->eth_api) {
case ETH_API_VDE:
case ETH_API_UDP:
case ETH_API_NAT:
case ETH_API_VMN:
bpf_used = 0;
to_me = 0;
eth_packet_trace (dev, data, header->len, "received");
@@ -4116,37 +3911,6 @@ do {
}
break;
#endif /* HAVE_VDE_NETWORK */
#ifdef HAVE_VMNET_NETWORK
case ETH_API_VMN:
{
vmnet_return_t ret;
int count = 1;
struct pcap_pkthdr header;
struct vmpktdesc pkt_desc;
struct iovec iov;
// XXX: Should be MTU returned from vmnet startup?
u_char buf[ETH_MAX_JUMBO_FRAME];
iov.iov_base = buf;
iov.iov_len = ETH_MAX_JUMBO_FRAME;
pkt_desc.vm_pkt_size = ETH_MAX_JUMBO_FRAME;
pkt_desc.vm_pkt_iov = &iov;
pkt_desc.vm_pkt_iovcnt = 1;
pkt_desc.vm_flags = 0;
ret = vmnet_read((interface_ref)dev->handle, &pkt_desc, &count);
if (ret == VMNET_SUCCESS && count > 0) {
status = 1;
header.caplen = header.len = pkt_desc.vm_pkt_size;
_eth_callback((u_char *)dev, &header, buf);
} else {
status = ret == VMNET_SUCCESS ? 0 : -1;
}
}
break;
#endif
case ETH_API_UDP:
if (1) {
struct pcap_pkthdr header;

View File

@@ -265,7 +265,6 @@ struct eth_device {
#define ETH_API_VDE 3 /* VDE API in use */
#define ETH_API_UDP 4 /* UDP API in use */
#define ETH_API_NAT 5 /* NAT (SLiRP) API in use */
#define ETH_API_VMN 6 /* Apple vmnet.framework in use */
ETH_PCALLBACK read_callback; /* read callback function */
ETH_PCALLBACK write_callback; /* write callback function */
ETH_PACK* read_packet; /* read packet */