xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
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
- );
+ !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) {
+
+ if(macos_vmnet_addr) {
xpc_dictionary_set_string(if_desc, vmnet_start_address_key, 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) {
+
+ 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(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,
- ^(vmnet_return_t status, xpc_object_t interface_param) {
- if_status = status;
- if(status == VMNET_SUCCESS && interface_param) {
- max_packet_size = xpc_dictionary_get_uint64(interface_param, vmnet_max_packet_size_key);
- }
- dispatch_semaphore_signal(if_started_sem);
- });
- if (vmnet_if) {
+ if_desc, if_queue,
+ ^(vmnet_return_t status, xpc_object_t interface_param) {
+ if_status = status;
+
+ if(status == VMNET_SUCCESS && interface_param) {
+ max_packet_size = xpc_dictionary_get_uint64(interface_param, vmnet_max_packet_size_key);
+ }
+
+ dispatch_semaphore_signal(if_started_sem);
+ });
+
+ if(vmnet_if) {
dispatch_semaphore_wait(if_started_sem, DISPATCH_TIME_FOREVER);
}
+
dispatch_release(if_started_sem);
- if (if_status == VMNET_SUCCESS) {
+ 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();
- });
+ 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) {
+
+ 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]);
dispatch_semaphore_t if_stopped_sem = dispatch_semaphore_create(0);
if_status = vmnet_stop_interface(
- vmnet_if, if_queue,
- ^(vmnet_return_t status) {
- if_status = status;
- dispatch_semaphore_signal(if_stopped_sem);
- });
- if (if_status == VMNET_SUCCESS) {
+ vmnet_if, if_queue,
+ ^(vmnet_return_t status) {
+ if_status = status;
+ dispatch_semaphore_signal(if_stopped_sem);
+ });
+
+ if(if_status == VMNET_SUCCESS) {
dispatch_semaphore_wait(if_stopped_sem, DISPATCH_TIME_FOREVER);
}
+
dispatch_release(if_stopped_sem);
if(if_status != VMNET_SUCCESS) {
};
if_status = vmnet_read(vmnet_if, &packet, &pkt_count);
+
if(if_status != VMNET_SUCCESS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read packet: %s", str_vmnet_status(if_status));
return;
.iov_base = packet.vm_pkt_iov->iov_base,
.iov_len = packet.vm_pkt_size,
};
+
if(writev(read_socket[1], &read_iov_out, 1) < 0) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to write to read socket: %s", strerror(errno));
return;
.iov_base = (char *) buffer,
.iov_len = buflen,
};
+
struct vmpktdesc packet = {
.vm_pkt_iovcnt = 1,
.vm_flags = 0,
.vm_pkt_size = buflen,
.vm_pkt_iov = &iov,
};
+
int pkt_count = 1;
vmnet_return_t result = vmnet_write(vmnet_if, &packet, &pkt_count);
+
if(result != VMNET_SUCCESS) {
logger(DEBUG_ALWAYS, LOG_ERR, "Write failed: %s", str_vmnet_status(result));
return -1;
}
const char *str_vmnet_status(vmnet_return_t status) {
- switch (status) {
+ switch(status) {
case VMNET_SUCCESS:
return "success";
+
case VMNET_FAILURE:
return "general failure (possibly not enough privileges)";
+
case VMNET_MEM_FAILURE:
return "memory allocation failure";
+
case VMNET_INVALID_ARGUMENT:
return "invalid argument specified";
+
case VMNET_SETUP_INCOMPLETE:
return "interface setup is not complete";
+
case VMNET_INVALID_ACCESS:
return "invalid access, permission denied";
+
case VMNET_PACKET_TOO_BIG:
return "packet size is larger than MTU";
+
case VMNET_BUFFER_EXHAUSTED:
return "buffers exhausted in kernel";
+
case VMNET_TOO_MANY_PACKETS:
return "packet count exceeds limit";
+
case VMNET_SHARING_SERVICE_BUSY:
return "conflict, sharing service is in use";
+
default:
return "unknown vmnet error";
}