1 /*
2 * Copyright (c) 2015-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <unistd.h>
34 #include <errno.h>
35 #include <skywalk/os_skywalk_private.h>
36
37 #ifndef LIBSYSCALL_INTERFACE
38 #error "LIBSYSCALL_INTERFACE not defined"
39 #endif /* !LIBSYSCALL_INTERFACE */
40
41 nexus_attr_t
os_nexus_attr_create(void)42 os_nexus_attr_create(void)
43 {
44 struct nexus_attr *nxa;
45
46 nxa = malloc(sizeof(*nxa));
47 if (nxa != NULL) {
48 bzero(nxa, sizeof(*nxa));
49 }
50 return nxa;
51 }
52
53 nexus_attr_t
os_nexus_attr_clone(const nexus_attr_t nxa)54 os_nexus_attr_clone(const nexus_attr_t nxa)
55 {
56 struct nexus_attr *nnxa = NULL;
57
58 nnxa = os_nexus_attr_create();
59 if (nnxa != NULL && nxa != NULL) {
60 bcopy(nxa, nnxa, sizeof(*nnxa));
61 }
62
63 return nnxa;
64 }
65
66 int
os_nexus_attr_set(const nexus_attr_t nxa,const nexus_attr_type_t type,const uint64_t value)67 os_nexus_attr_set(const nexus_attr_t nxa, const nexus_attr_type_t type,
68 const uint64_t value)
69 {
70 return __nexus_attr_set(nxa, type, value);
71 }
72
73 int
os_nexus_attr_get(const nexus_attr_t nxa,const nexus_attr_type_t type,uint64_t * value)74 os_nexus_attr_get(const nexus_attr_t nxa, const nexus_attr_type_t type,
75 uint64_t *value)
76 {
77 return __nexus_attr_get(nxa, type, value);
78 }
79
80 void
os_nexus_attr_destroy(nexus_attr_t nxa)81 os_nexus_attr_destroy(nexus_attr_t nxa)
82 {
83 free(nxa);
84 }
85
86 nexus_controller_t
os_nexus_controller_create(void)87 os_nexus_controller_create(void)
88 {
89 struct nexus_controller *ncd = NULL;
90 struct nxctl_init init;
91 int fd;
92
93 bzero(&init, sizeof(init));
94 init.ni_version = NEXUSCTL_INIT_CURRENT_VERSION;
95
96 fd = __nexus_open(&init, sizeof(init));
97 if (fd == -1) {
98 goto done;
99 }
100
101 ncd = malloc(sizeof(*ncd));
102 if (ncd == NULL) {
103 (void) guarded_close_np(fd, &init.ni_guard);
104 goto done;
105 }
106 bzero(ncd, sizeof(*ncd));
107 ncd->ncd_fd = fd;
108 ncd->ncd_guard = init.ni_guard;
109 done:
110 return ncd;
111 }
112
113 int
os_nexus_controller_get_fd(const nexus_controller_t ncd)114 os_nexus_controller_get_fd(const nexus_controller_t ncd)
115 {
116 return ncd->ncd_fd;
117 }
118
119 int
os_nexus_controller_register_provider(const nexus_controller_t ncd,const nexus_name_t name,const nexus_type_t type,const nexus_attr_t nxa,uuid_t * prov_uuid)120 os_nexus_controller_register_provider(const nexus_controller_t ncd,
121 const nexus_name_t name, const nexus_type_t type,
122 const nexus_attr_t nxa, uuid_t *prov_uuid)
123 {
124 struct nxprov_reg reg;
125 int err;
126
127 if ((err = __nexus_provider_reg_prepare(®, name, type, nxa)) == 0) {
128 err = __nexus_register(ncd->ncd_fd, ®, sizeof(reg),
129 prov_uuid, sizeof(uuid_t));
130 }
131 return err;
132 }
133
134 int
os_nexus_controller_deregister_provider(const nexus_controller_t ncd,const uuid_t prov_uuid)135 os_nexus_controller_deregister_provider(const nexus_controller_t ncd,
136 const uuid_t prov_uuid)
137 {
138 return __nexus_deregister(ncd->ncd_fd, prov_uuid, sizeof(uuid_t));
139 }
140
141 int
os_nexus_controller_alloc_provider_instance(const nexus_controller_t ncd,const uuid_t prov_uuid,uuid_t * nx_uuid)142 os_nexus_controller_alloc_provider_instance(const nexus_controller_t ncd,
143 const uuid_t prov_uuid, uuid_t *nx_uuid)
144 {
145 return __nexus_create(ncd->ncd_fd, prov_uuid, sizeof(uuid_t),
146 nx_uuid, sizeof(uuid_t));
147 }
148
149 int
os_nexus_controller_free_provider_instance(const nexus_controller_t ncd,const uuid_t nx_uuid)150 os_nexus_controller_free_provider_instance(const nexus_controller_t ncd,
151 const uuid_t nx_uuid)
152 {
153 return __nexus_destroy(ncd->ncd_fd, nx_uuid, sizeof(uuid_t));
154 }
155
156 int
os_nexus_controller_bind_provider_instance(const nexus_controller_t ncd,const uuid_t nx_uuid,const nexus_port_t port,const pid_t pid,const uuid_t exec_uuid,const void * key,const uint32_t key_len,uint32_t bind_flags)157 os_nexus_controller_bind_provider_instance(const nexus_controller_t ncd,
158 const uuid_t nx_uuid, const nexus_port_t port, const pid_t pid,
159 const uuid_t exec_uuid, const void *key, const uint32_t key_len,
160 uint32_t bind_flags)
161 {
162 struct nx_bind_req nbr;
163
164 __nexus_bind_req_prepare(&nbr, nx_uuid, port, pid, exec_uuid,
165 key, key_len, bind_flags);
166
167 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_BIND,
168 &nbr, sizeof(nbr));
169 }
170
171 int
os_nexus_controller_unbind_provider_instance(const nexus_controller_t ncd,const uuid_t nx_uuid,const nexus_port_t port)172 os_nexus_controller_unbind_provider_instance(const nexus_controller_t ncd,
173 const uuid_t nx_uuid, const nexus_port_t port)
174 {
175 struct nx_unbind_req nbu;
176
177 __nexus_unbind_req_prepare(&nbu, nx_uuid, port);
178
179 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_UNBIND,
180 &nbu, sizeof(nbu));
181 }
182
183 int
os_nexus_controller_read_provider_attr(const nexus_controller_t ncd,const uuid_t prov_uuid,nexus_attr_t nxa)184 os_nexus_controller_read_provider_attr(const nexus_controller_t ncd,
185 const uuid_t prov_uuid, nexus_attr_t nxa)
186 {
187 struct nxprov_reg_ent nre;
188 uint32_t nre_len = sizeof(nre);
189 struct nxprov_params *p = &nre.npre_prov_params;
190 int ret = 0;
191
192 if (nxa == NULL) {
193 return EINVAL;
194 }
195
196 bzero(&nre, sizeof(nre));
197 bcopy(prov_uuid, nre.npre_prov_uuid, sizeof(uuid_t));
198 ret = __nexus_get_opt(ncd->ncd_fd, NXOPT_NEXUS_PROV_ENTRY,
199 &nre, &nre_len);
200
201 if (ret == 0) {
202 __nexus_attr_from_params(nxa, p);
203 }
204
205 return ret;
206 }
207
208 void
os_nexus_controller_destroy(nexus_controller_t ncd)209 os_nexus_controller_destroy(nexus_controller_t ncd)
210 {
211 if (ncd->ncd_fd != -1) {
212 (void) guarded_close_np(ncd->ncd_fd, &ncd->ncd_guard);
213 }
214 free(ncd);
215 }
216
217 int
__os_nexus_ifattach(const nexus_controller_t ncd,const uuid_t nx_uuid,const char * ifname,const uuid_t netif_uuid,boolean_t host,uuid_t * nx_if_uuid)218 __os_nexus_ifattach(const nexus_controller_t ncd,
219 const uuid_t nx_uuid, const char *ifname, const uuid_t netif_uuid,
220 boolean_t host, uuid_t *nx_if_uuid)
221 {
222 struct nx_cfg_req ncr;
223 struct nx_spec_req nsr;
224 int ret;
225
226 bzero(&nsr, sizeof(nsr));
227 if (ifname != NULL) {
228 (void) strlcpy(nsr.nsr_name, ifname, sizeof(nsr.nsr_name));
229 } else {
230 bcopy(netif_uuid, nsr.nsr_uuid, sizeof(uuid_t));
231 nsr.nsr_flags |= NXSPECREQ_UUID;
232 }
233
234 if (host) {
235 nsr.nsr_flags |= NXSPECREQ_HOST;
236 }
237
238 __nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_ATTACH,
239 &nsr, sizeof(nsr));
240
241 ret = __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
242 &ncr, sizeof(ncr));
243
244 if (ret == 0) {
245 bcopy(nsr.nsr_if_uuid, nx_if_uuid, sizeof(uuid_t));
246 }
247
248 return ret;
249 }
250
251 int
__os_nexus_ifdetach(const nexus_controller_t ncd,const uuid_t nx_uuid,const uuid_t nx_if_uuid)252 __os_nexus_ifdetach(const nexus_controller_t ncd, const uuid_t nx_uuid,
253 const uuid_t nx_if_uuid)
254 {
255 struct nx_cfg_req ncr;
256 struct nx_spec_req nsr;
257
258 bzero(&nsr, sizeof(nsr));
259 bcopy(nx_if_uuid, nsr.nsr_if_uuid, sizeof(uuid_t));
260
261 __nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_DETACH,
262 &nsr, sizeof(nsr));
263
264 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
265 &ncr, sizeof(ncr));
266 }
267
268 int
__os_nexus_flow_add(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_flow_req * nfr)269 __os_nexus_flow_add(const nexus_controller_t ncd, const uuid_t nx_uuid,
270 const struct nx_flow_req *nfr)
271 {
272 struct nx_cfg_req ncr;
273
274 __nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_FLOW_ADD,
275 nfr, sizeof(*nfr));
276
277 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
278 &ncr, sizeof(ncr));
279 }
280
281 int
__os_nexus_flow_del(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_flow_req * nfr)282 __os_nexus_flow_del(const nexus_controller_t ncd, const uuid_t nx_uuid,
283 const struct nx_flow_req *nfr)
284 {
285 struct nx_cfg_req ncr;
286
287 __nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_FLOW_DEL,
288 nfr, sizeof(*nfr));
289
290 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
291 &ncr, sizeof(ncr));
292 }
293
294 int
__os_nexus_get_llink_info(const nexus_controller_t ncd,const uuid_t nx_uuid,const struct nx_llink_info_req * nlir,size_t len)295 __os_nexus_get_llink_info(const nexus_controller_t ncd, const uuid_t nx_uuid,
296 const struct nx_llink_info_req *nlir, size_t len)
297 {
298 struct nx_cfg_req ncr;
299
300 __nexus_config_req_prepare(&ncr, nx_uuid, NXCFG_CMD_GET_LLINK_INFO,
301 nlir, len);
302
303 return __nexus_set_opt(ncd->ncd_fd, NXOPT_NEXUS_CONFIG,
304 &ncr, sizeof(ncr));
305 }
306