blob: 40c7306a758a5dc73a26fef4a223945f46550728 [file] [log] [blame]
Vladislav Yaroshchuk81ad2962022-03-17 20:28:34 +03001/*
2 * vmnet-shared.c
3 *
4 * Copyright(c) 2022 Vladislav Yaroshchuk <vladislav.yaroshchuk@jetbrains.com>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 *
9 */
10
11#include "qemu/osdep.h"
12#include "qapi/qapi-types-net.h"
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +030013#include "qapi/error.h"
Vladislav Yaroshchuk81ad2962022-03-17 20:28:34 +030014#include "vmnet_int.h"
15#include "clients.h"
Vladislav Yaroshchuk81ad2962022-03-17 20:28:34 +030016
17#include <vmnet/vmnet.h>
18
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +030019
20static bool validate_options(const Netdev *netdev, Error **errp)
21{
22 const NetdevVmnetSharedOptions *options = &(netdev->u.vmnet_shared);
23
24#if !defined(MAC_OS_VERSION_11_0) || \
25 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_11_0
26 if (options->has_isolated) {
27 error_setg(errp,
28 "vmnet-shared.isolated feature is "
29 "unavailable: outdated vmnet.framework API");
30 return false;
31 }
32#endif
33
Markus Armbruster74808742022-11-04 17:07:00 +010034 if ((options->start_address ||
35 options->end_address ||
36 options->subnet_mask) &&
37 !(options->start_address &&
38 options->end_address &&
39 options->subnet_mask)) {
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +030040 error_setg(errp,
41 "'start-address', 'end-address', 'subnet-mask' "
42 "should be provided together"
43 );
44 return false;
45 }
46
47 return true;
48}
49
50static xpc_object_t build_if_desc(const Netdev *netdev)
51{
52 const NetdevVmnetSharedOptions *options = &(netdev->u.vmnet_shared);
53 xpc_object_t if_desc = xpc_dictionary_create(NULL, NULL, 0);
54
55 xpc_dictionary_set_uint64(
56 if_desc,
57 vmnet_operation_mode_key,
58 VMNET_SHARED_MODE
59 );
60
Markus Armbruster74808742022-11-04 17:07:00 +010061 if (options->nat66_prefix) {
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +030062 xpc_dictionary_set_string(if_desc,
63 vmnet_nat66_prefix_key,
64 options->nat66_prefix);
65 }
66
Markus Armbruster74808742022-11-04 17:07:00 +010067 if (options->start_address) {
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +030068 xpc_dictionary_set_string(if_desc,
69 vmnet_start_address_key,
70 options->start_address);
71 xpc_dictionary_set_string(if_desc,
72 vmnet_end_address_key,
73 options->end_address);
74 xpc_dictionary_set_string(if_desc,
75 vmnet_subnet_mask_key,
76 options->subnet_mask);
77 }
78
79#if defined(MAC_OS_VERSION_11_0) && \
80 MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_VERSION_11_0
81 xpc_dictionary_set_bool(
82 if_desc,
83 vmnet_enable_isolation_key,
84 options->isolated
85 );
86#endif
87
88 return if_desc;
89}
90
91static NetClientInfo net_vmnet_shared_info = {
92 .type = NET_CLIENT_DRIVER_VMNET_SHARED,
93 .size = sizeof(VmnetState),
94 .receive = vmnet_receive_common,
95 .cleanup = vmnet_cleanup_common,
96};
97
Vladislav Yaroshchuk81ad2962022-03-17 20:28:34 +030098int net_init_vmnet_shared(const Netdev *netdev, const char *name,
99 NetClientState *peer, Error **errp)
100{
Vladislav Yaroshchuk73f99db2022-03-17 20:28:35 +0300101 NetClientState *nc = qemu_new_net_client(&net_vmnet_shared_info,
102 peer, "vmnet-shared", name);
103 xpc_object_t if_desc;
104 int result = -1;
105
106 if (!validate_options(netdev, errp)) {
107 return result;
108 }
109
110 if_desc = build_if_desc(netdev);
111 result = vmnet_if_create(nc, if_desc, errp);
112 xpc_release(if_desc);
113 return result;
Vladislav Yaroshchuk81ad2962022-03-17 20:28:34 +0300114}