.It utun Pq OS X
Set type to utun.
This mode should support both IPv4 and IPv6 packets.
-.It vmnet Pq OS X
-Set type to vmnet.
+.It vmnet-host Pq OS X
+Set type to vmnet-host.
Like with tap, Tinc will expect packets read from the virtual network device
to start with an Ethernet header.
-Use VmnetAddr and VmnetNetmask settings to configure the device address/network
+.It vmnet-shared Pq OS X
+Set type to vmnet-shared.
+Like with tap, Tinc will expect packets read from the virtual network device
+to start with an Ethernet header.
+.It vmnet-bridged Pq OS X
+Set type to vmnet-bridged.
+Like with tap, Tinc will expect packets read from the virtual network device
+to start with an Ethernet header.
+Use BridgedIf settings to select the bridged physical device
.It tap Pq BSD and Linux
Set type to tap.
Tinc will expect packets read from the virtual network device
static void macos_vmnet_read(void);
static const char *str_vmnet_status(vmnet_return_t status);
-int macos_vmnet_open(void) {
+int macos_vmnet_open(const char device[]) {
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, read_socket)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to create socket: %s", strerror(errno));
return -1;
}
- if_queue = dispatch_queue_create("org.tinc-vpn.vmnet.if_queue", DISPATCH_QUEUE_SERIAL);
-
xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
- xpc_dictionary_set_uint64(if_desc, vmnet_operation_mode_key, VMNET_HOST_MODE);
+ xpc_dictionary_set_uint64(if_desc, vmnet_operation_mode_key,
+ !strncmp(device, "vmnet-bridged", 14) ? VMNET_BRIDGED_MODE :
+ !strncmp(device, "vmnet-shared", 13) ? VMNET_SHARED_MODE :
+ VMNET_HOST_MODE
+ );
xpc_dictionary_set_bool(if_desc, vmnet_enable_isolation_key, 0);
xpc_dictionary_set_bool(if_desc, vmnet_allocate_mac_address_key, false);
if (macos_vmnet_addr) {
xpc_dictionary_set_string(if_desc, vmnet_end_address_key, macos_vmnet_addr);
xpc_dictionary_set_string(if_desc, vmnet_subnet_mask_key, macos_vmnet_netmask);
}
+ if (macos_vmnet_bridged_if) {
+ xpc_dictionary_set_string(if_desc, vmnet_shared_interface_name_key, macos_vmnet_bridged_if);
+ }
if (macos_vmnet_nat66_prefix) {
xpc_dictionary_set_string(if_desc, vmnet_nat66_prefix_key, macos_vmnet_nat66_prefix);
}
+ if_queue = dispatch_queue_create("org.tinc-vpn.vmnet.if_queue", DISPATCH_QUEUE_SERIAL);
+
dispatch_semaphore_t if_started_sem = dispatch_semaphore_create(0);
vmnet_if = vmnet_start_interface(
if_desc, if_queue,
}
dispatch_semaphore_signal(if_started_sem);
});
- dispatch_semaphore_wait(if_started_sem, DISPATCH_TIME_FOREVER);
+ if (vmnet_if) {
+ dispatch_semaphore_wait(if_started_sem, DISPATCH_TIME_FOREVER);
+ }
dispatch_release(if_started_sem);
+ if (if_status == VMNET_SUCCESS) {
+ read_iov_in.iov_base = malloc(max_packet_size);
+ read_iov_in.iov_len = max_packet_size;
+
+ if_status = vmnet_interface_set_event_callback(
+ vmnet_if, VMNET_INTERFACE_PACKETS_AVAILABLE, if_queue,
+ ^(interface_event_t event_type, xpc_object_t event) {
+ macos_vmnet_read();
+ });
+ }
+
xpc_release(if_desc);
if(if_status != VMNET_SUCCESS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to create vmnet device: %s", str_vmnet_status(if_status));
+ if (vmnet_if) {
+ vmnet_stop_interface(vmnet_if, if_queue, ^(vmnet_return_t result) {});
+ vmnet_if = NULL;
+ }
+ if_status = VMNET_SETUP_INCOMPLETE;
+ dispatch_release(if_queue);
+ close(read_socket[0]);
+ close(read_socket[1]);
return -1;
}
- read_iov_in.iov_base = malloc(max_packet_size);
- read_iov_in.iov_len = max_packet_size;
-
- vmnet_interface_set_event_callback(
- vmnet_if, VMNET_INTERFACE_PACKETS_AVAILABLE, if_queue,
- ^(interface_event_t event_type, xpc_object_t event) {
- macos_vmnet_read();
- });
-
return read_socket[0];
}
return -1;
}
- vmnet_interface_set_event_callback(vmnet_if, VMNET_INTERFACE_PACKETS_AVAILABLE, NULL, NULL);
-
dispatch_semaphore_t if_stopped_sem = dispatch_semaphore_create(0);
- vmnet_stop_interface(
+ if_status = vmnet_stop_interface(
vmnet_if, if_queue,
^(vmnet_return_t status) {
if_status = status;
dispatch_semaphore_signal(if_stopped_sem);
});
- dispatch_semaphore_wait(if_stopped_sem, DISPATCH_TIME_FOREVER);
+ if (if_status == VMNET_SUCCESS) {
+ dispatch_semaphore_wait(if_stopped_sem, DISPATCH_TIME_FOREVER);
+ }
dispatch_release(if_stopped_sem);
if(if_status != VMNET_SUCCESS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to close vmnet device: %s", str_vmnet_status(if_status));
return -1;
}
- if_status = VMNET_SETUP_INCOMPLETE;
+ if_status = VMNET_SETUP_INCOMPLETE;
dispatch_release(if_queue);
read_iov_in.iov_len = 0;
#endif
#ifdef ENABLE_VMNET
- else if(!strcasecmp(type, "vmnet")) {
- device = xstrdup("vmnet");
+ else if(!strcasecmp(type, "vmnet-host")
+ || !strcasecmp(type, "vmnet-shared")
+ || !strcasecmp(type, "vmnet-bridged")) {
+ device = xstrdup(type);
device_type = DEVICE_TYPE_VMNET;
get_config_string(lookup_config(&config_tree, "VmnetAddr"), &macos_vmnet_addr);
get_config_string(lookup_config(&config_tree, "VmnetNetmask"), &macos_vmnet_netmask);
+ get_config_string(lookup_config(&config_tree, "VmnetBridgedIf"), &macos_vmnet_bridged_if);
get_config_string(lookup_config(&config_tree, "VmnetNat66Prefix"), &macos_vmnet_nat66_prefix);
}
#ifdef ENABLE_VMNET
case DEVICE_TYPE_VMNET: {
- device_fd = macos_vmnet_open();
+ device_fd = macos_vmnet_open(device);
}
break;
#endif