xref: /xnu-8019.80.24/bsd/net/network_agent.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2014-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 #include <string.h>
30 #include <sys/systm.h>
31 #include <sys/types.h>
32 #include <sys/syslog.h>
33 #include <sys/queue.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
36 #include <sys/kern_control.h>
37 #include <sys/mbuf.h>
38 #include <sys/kpi_mbuf.h>
39 #include <sys/sysctl.h>
40 #include <sys/priv.h>
41 #include <sys/kern_event.h>
42 #include <sys/sysproto.h>
43 #include <net/network_agent.h>
44 #include <net/if_var.h>
45 #include <net/necp.h>
46 #include <os/log.h>
47 
48 u_int32_t netagent_debug = LOG_NOTICE; // 0=None, 1=Basic
49 
50 SYSCTL_NODE(_net, OID_AUTO, netagent, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "NetworkAgent");
51 SYSCTL_INT(_net_netagent, OID_AUTO, debug, CTLFLAG_LOCKED | CTLFLAG_RW, &netagent_debug, 0, "");
52 
53 static int netagent_registered_count = 0;
54 SYSCTL_INT(_net_netagent, OID_AUTO, registered_count, CTLFLAG_RD | CTLFLAG_LOCKED,
55     &netagent_registered_count, 0, "");
56 
57 static int netagent_active_count = 0;
58 SYSCTL_INT(_net_netagent, OID_AUTO, active_count, CTLFLAG_RD | CTLFLAG_LOCKED,
59     &netagent_active_count, 0, "");
60 
61 #define NETAGENTLOG(level, format, ...) do {                                             \
62     if (level <= netagent_debug) {                                                       \
63 	if (level == LOG_ERR) {                                                          \
64 	    os_log_error(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
65 	} else {                                                                         \
66 	    os_log(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__);       \
67 	}                                                                                \
68     }                                                                                    \
69 } while (0)
70 
71 #define NETAGENTLOG0(level, msg) do {                                                    \
72     if (level <= netagent_debug) {                                                       \
73 	        if (level == LOG_ERR) {                                                          \
74 	    os_log_error(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg);                 \
75 	} else {                                                                         \
76 	    os_log(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg);                       \
77 	}                                                                                \
78     }                                                                                    \
79 } while (0)
80 
81 struct netagent_client {
82 	LIST_ENTRY(netagent_client) client_chain;
83 	uuid_t client_id;
84 	uuid_t client_proc_uuid;
85 	pid_t client_pid;
86 };
87 
88 LIST_HEAD(netagent_client_list_s, netagent_client);
89 
90 struct netagent_token {
91 	TAILQ_ENTRY(netagent_token) token_chain;
92 	u_int32_t token_length;
93 	u_int8_t *token_bytes;
94 };
95 
96 TAILQ_HEAD(netagent_token_list_s, netagent_token);
97 
98 #define NETAGENT_MAX_CLIENT_ERROR_COUNT 32
99 
100 struct netagent_wrapper {
101 	LIST_ENTRY(netagent_wrapper) master_chain;
102 	u_int32_t control_unit;
103 	netagent_event_f event_handler;
104 	void *event_context;
105 	u_int32_t generation;
106 	u_int64_t use_count;
107 	u_int32_t token_count;
108 	u_int32_t token_low_water;
109 	int32_t last_client_error;
110 	u_int32_t client_error_count;
111 	u_int8_t __pad_bytes[3];
112 	struct netagent_token_list_s token_list;
113 	struct netagent_client_list_s pending_triggers_list;
114 	struct netagent *netagent;
115 };
116 
117 struct netagent_session {
118 	u_int32_t control_unit; // A control unit of 0 indicates an agent owned by the kernel
119 	struct netagent_wrapper *wrapper;
120 	netagent_event_f event_handler;
121 	void *event_context;
122 };
123 
124 typedef enum {
125 	kNetagentErrorDomainPOSIX                       = 0,
126 	kNetagentErrorDomainUserDefined         = 1,
127 } netagent_error_domain_t;
128 
129 static LIST_HEAD(_netagent_list, netagent_wrapper) master_netagent_list =
130     LIST_HEAD_INITIALIZER(master_netagent_list);
131 
132 // Protected by netagent_lock
133 static u_int32_t g_next_generation = 1;
134 
135 static kern_ctl_ref     netagent_kctlref;
136 static u_int32_t        netagent_family;
137 static LCK_GRP_DECLARE(netagent_mtx_grp, NETAGENT_CONTROL_NAME);
138 static LCK_RW_DECLARE(netagent_lock, &netagent_mtx_grp);
139 
140 static errno_t netagent_register_control(void);
141 static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
142     void **unitinfo);
143 static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
144 static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
145     mbuf_t m, int flags);
146 static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
147 static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
148     int opt, void *data, size_t *len);
149 static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
150     int opt, void *data, size_t len);
151 
152 static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
153 
154 static struct netagent_session *netagent_create_session(u_int32_t control_unit);
155 static void netagent_delete_session(struct netagent_session *session);
156 
157 // Register
158 static void netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
159     size_t payload_length, mbuf_t packet, size_t offset);
160 static errno_t netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
161     size_t payload_length);
162 
163 // Unregister
164 static void netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
165     size_t payload_length, mbuf_t packet, size_t offset);
166 static errno_t netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
167     size_t payload_length);
168 
169 // Update
170 static void netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
171     size_t payload_length, mbuf_t packet, size_t offset);
172 static errno_t netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload,
173     size_t payload_length);
174 
175 // Assign nexus
176 static void netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
177     size_t payload_length, mbuf_t packet, size_t offset);
178 static errno_t netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
179     size_t payload_length);
180 
181 // Assign group
182 static errno_t netagent_handle_assign_group_setopt(struct netagent_session *session, u_int8_t *payload,
183     size_t payload_length);
184 
185 // Set/get assert count
186 static errno_t netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
187 static errno_t netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
188 
189 // Manage tokens
190 static errno_t netagent_handle_add_token_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
191 static errno_t netagent_handle_flush_tokens_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
192 static errno_t netagent_handle_token_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
193 static errno_t netagent_handle_token_low_water_setopt(struct netagent_session *session, u_int8_t *buffer, size_t buffer_length);
194 static errno_t netagent_handle_token_low_water_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
195 
196 // Client error
197 static errno_t netagent_handle_reset_client_error_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
198 
199 static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
200     size_t payload_length, mbuf_t packet, size_t offset);
201 
202 static struct netagent_wrapper *netagent_find_agent_with_uuid(uuid_t uuid);
203 
204 errno_t
netagent_init(void)205 netagent_init(void)
206 {
207 	return netagent_register_control();
208 }
209 
210 static errno_t
netagent_register_control(void)211 netagent_register_control(void)
212 {
213 	struct kern_ctl_reg     kern_ctl;
214 	errno_t                 result = 0;
215 
216 	// Find a unique value for our interface family
217 	result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
218 	if (result != 0) {
219 		NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
220 		return result;
221 	}
222 
223 	bzero(&kern_ctl, sizeof(kern_ctl));
224 	strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
225 	kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
226 	kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
227 	kern_ctl.ctl_sendsize = 64 * 1024;
228 	kern_ctl.ctl_recvsize = 64 * 1024;
229 	kern_ctl.ctl_connect = netagent_ctl_connect;
230 	kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
231 	kern_ctl.ctl_send = netagent_ctl_send;
232 	kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
233 	kern_ctl.ctl_setopt = netagent_ctl_setopt;
234 	kern_ctl.ctl_getopt = netagent_ctl_getopt;
235 
236 	result = ctl_register(&kern_ctl, &netagent_kctlref);
237 	if (result != 0) {
238 		NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
239 		return result;
240 	}
241 
242 	return 0;
243 }
244 
245 static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)246 netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
247 {
248 #pragma unused(kctlref)
249 	*unitinfo = netagent_create_session(sac->sc_unit);
250 	if (*unitinfo == NULL) {
251 		// Could not allocate session
252 		return ENOBUFS;
253 	}
254 
255 	return 0;
256 }
257 
258 static errno_t
netagent_ctl_disconnect(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo)259 netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
260 {
261 #pragma unused(kctlref, unit)
262 	struct netagent_session *session = (struct netagent_session *)unitinfo;
263 	if (session != NULL) {
264 		netagent_delete_session(session);
265 	}
266 
267 	return 0;
268 }
269 
270 // Kernel events
271 static void
netagent_post_event(uuid_t agent_uuid,u_int32_t event_code,bool update_necp,bool should_update_immediately)272 netagent_post_event(uuid_t agent_uuid, u_int32_t event_code, bool update_necp, bool should_update_immediately)
273 {
274 	if (update_necp) {
275 		necp_update_all_clients_immediately_if_needed(should_update_immediately);
276 	}
277 
278 	struct kev_msg ev_msg;
279 	memset(&ev_msg, 0, sizeof(ev_msg));
280 
281 	struct kev_netagent_data event_data;
282 
283 	ev_msg.vendor_code      = KEV_VENDOR_APPLE;
284 	ev_msg.kev_class        = KEV_NETWORK_CLASS;
285 	ev_msg.kev_subclass     = KEV_NETAGENT_SUBCLASS;
286 	ev_msg.event_code       = event_code;
287 
288 	uuid_copy(event_data.netagent_uuid, agent_uuid);
289 	ev_msg.dv[0].data_ptr    = &event_data;
290 	ev_msg.dv[0].data_length = sizeof(event_data);
291 
292 	kev_post_msg(&ev_msg);
293 }
294 
295 // Message handling
296 static u_int8_t *
netagent_buffer_write_message_header(u_int8_t * buffer,u_int8_t message_type,u_int8_t flags,u_int32_t message_id,u_int32_t error,size_t payload_length)297 netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
298     u_int32_t message_id, u_int32_t error, size_t payload_length)
299 {
300 	memset(buffer, 0, sizeof(struct netagent_message_header));
301 	((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
302 	((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
303 	((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
304 	((struct netagent_message_header *)(void *)buffer)->message_error = error;
305 	((struct netagent_message_header *)(void *)buffer)->message_payload_length = (u_int32_t)payload_length;
306 	return buffer + sizeof(struct netagent_message_header);
307 }
308 
309 static int
netagent_send_ctl_data(u_int32_t control_unit,u_int8_t * buffer,size_t buffer_size)310 netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
311 {
312 	if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
313 		return EINVAL;
314 	}
315 
316 	return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
317 }
318 
319 static int
netagent_send_trigger(struct netagent_wrapper * wrapper,struct proc * p,u_int32_t flags,u_int8_t trigger_type)320 netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int8_t trigger_type)
321 {
322 	int error = 0;
323 	struct netagent_trigger_message *trigger_message = NULL;
324 	u_int8_t *trigger = NULL;
325 	size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
326 
327 	trigger = (u_int8_t *)kalloc_data(trigger_size, Z_WAITOK);
328 	if (trigger == NULL) {
329 		return ENOMEM;
330 	}
331 
332 	(void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
333 
334 	trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
335 	trigger_message->trigger_flags = flags;
336 	if (p != NULL) {
337 		trigger_message->trigger_pid = proc_pid(p);
338 		proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
339 	} else {
340 		trigger_message->trigger_pid = 0;
341 		uuid_clear(trigger_message->trigger_proc_uuid);
342 	}
343 
344 	if ((error = netagent_send_ctl_data(wrapper->control_unit, trigger, trigger_size))) {
345 		NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
346 	}
347 
348 	kfree_data(trigger, trigger_size);
349 	return error;
350 }
351 
352 static int
netagent_send_client_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type)353 netagent_send_client_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type)
354 {
355 	int error = 0;
356 	struct netagent_client_message *client_message = NULL;
357 	u_int8_t *message = NULL;
358 	size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_message);
359 
360 	message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
361 	if (message == NULL) {
362 		return ENOMEM;
363 	}
364 
365 	(void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_message));
366 
367 	client_message = (struct netagent_client_message *)(void *)(message + sizeof(struct netagent_message_header));
368 	uuid_copy(client_message->client_id, client_id);
369 
370 	if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
371 		NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
372 	}
373 
374 	kfree_data(message, message_size);
375 	return error;
376 }
377 
378 static int
netagent_send_error_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type,int32_t error_code)379 netagent_send_error_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type, int32_t error_code)
380 {
381 	int error = 0;
382 	struct netagent_client_error_message *client_message = NULL;
383 	u_int8_t *message = NULL;
384 	size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_error_message);
385 
386 	message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
387 	if (message == NULL) {
388 		return ENOMEM;
389 	}
390 
391 	(void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_error_message));
392 
393 	client_message = (struct netagent_client_error_message *)(void *)(message + sizeof(struct netagent_message_header));
394 	uuid_copy(client_message->client_id, client_id);
395 	client_message->error_code = error_code;
396 
397 	if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
398 		NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
399 	}
400 
401 	kfree_data(message, message_size);
402 	return error;
403 }
404 
405 static int
netagent_send_group_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type,struct necp_client_group_members * group_members)406 netagent_send_group_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type, struct necp_client_group_members *group_members)
407 {
408 	int error = 0;
409 	struct netagent_client_group_message *client_message = NULL;
410 	u_int8_t *message = NULL;
411 	size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_group_message) + group_members->group_members_length;
412 
413 	message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
414 	if (message == NULL) {
415 		return ENOMEM;
416 	}
417 
418 	(void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_group_message) + group_members->group_members_length);
419 
420 	client_message = (struct netagent_client_group_message *)(void *)(message + sizeof(struct netagent_message_header));
421 	uuid_copy(client_message->client_id, client_id);
422 	memcpy(client_message->group_members, group_members->group_members, group_members->group_members_length);
423 
424 	if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
425 		NETAGENTLOG(LOG_ERR, "Failed to send client group message %d on control unit %d", message_type, wrapper->control_unit);
426 	}
427 
428 	kfree_data(message, message_size);
429 	return error;
430 }
431 
432 static int
netagent_send_tokens_needed(struct netagent_wrapper * wrapper)433 netagent_send_tokens_needed(struct netagent_wrapper *wrapper)
434 {
435 	const u_int8_t message_type = NETAGENT_MESSAGE_TYPE_TOKENS_NEEDED;
436 	int error = 0;
437 	u_int8_t *message = NULL;
438 	size_t message_size = sizeof(struct netagent_message_header);
439 
440 	message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
441 	if (message == NULL) {
442 		return ENOMEM;
443 	}
444 
445 	(void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, 0);
446 
447 	if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
448 		NETAGENTLOG(LOG_ERR, "Failed to send client tokens needed message on control unit %d", wrapper->control_unit);
449 	}
450 
451 	kfree_data(message, message_size);
452 	return error;
453 }
454 
455 static int
netagent_send_success_response(struct netagent_session * session,u_int8_t message_type,u_int32_t message_id)456 netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
457 {
458 	int error = 0;
459 	u_int8_t *response = NULL;
460 	size_t response_size = sizeof(struct netagent_message_header);
461 	response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
462 	if (response == NULL) {
463 		return ENOMEM;
464 	}
465 	(void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
466 
467 	if ((error = netagent_send_ctl_data(session->control_unit, response, response_size))) {
468 		NETAGENTLOG0(LOG_ERR, "Failed to send response");
469 	}
470 
471 	kfree_data(response, response_size);
472 	return error;
473 }
474 
475 static errno_t
netagent_send_error_response(struct netagent_session * session,u_int8_t message_type,u_int32_t message_id,u_int32_t error_code)476 netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
477     u_int32_t message_id, u_int32_t error_code)
478 {
479 	int error = 0;
480 	u_int8_t *response = NULL;
481 	size_t response_size = sizeof(struct netagent_message_header);
482 
483 	if (session == NULL) {
484 		NETAGENTLOG0(LOG_ERR, "Got a NULL session");
485 		return EINVAL;
486 	}
487 
488 	response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
489 	if (response == NULL) {
490 		return ENOMEM;
491 	}
492 	(void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
493 	    message_id, error_code, 0);
494 
495 	if ((error = netagent_send_ctl_data(session->control_unit, response, response_size))) {
496 		NETAGENTLOG0(LOG_ERR, "Failed to send response");
497 	}
498 
499 	kfree_data(response, response_size);
500 	return error;
501 }
502 
503 static errno_t
netagent_ctl_send(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,mbuf_t packet,int flags)504 netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
505 {
506 #pragma unused(kctlref, unit, flags)
507 	struct netagent_session *session = (struct netagent_session *)unitinfo;
508 	struct netagent_message_header header;
509 	int error = 0;
510 
511 	if (session == NULL) {
512 		NETAGENTLOG0(LOG_ERR, "Got a NULL session");
513 		error = EINVAL;
514 		goto done;
515 	}
516 
517 	if (mbuf_pkthdr_len(packet) < sizeof(header)) {
518 		NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
519 		    mbuf_pkthdr_len(packet), sizeof(header));
520 		error = EINVAL;
521 		goto done;
522 	}
523 
524 	error = mbuf_copydata(packet, 0, sizeof(header), &header);
525 	if (error) {
526 		NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
527 		error = ENOBUFS;
528 		goto done;
529 	}
530 
531 	switch (header.message_type) {
532 	case NETAGENT_MESSAGE_TYPE_REGISTER: {
533 		netagent_handle_register_message(session, header.message_id, header.message_payload_length,
534 		    packet, sizeof(header));
535 		break;
536 	}
537 	case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
538 		netagent_handle_unregister_message(session, header.message_id, header.message_payload_length,
539 		    packet, sizeof(header));
540 		break;
541 	}
542 	case NETAGENT_MESSAGE_TYPE_UPDATE: {
543 		netagent_handle_update_message(session, header.message_id, header.message_payload_length,
544 		    packet, sizeof(header));
545 		break;
546 	}
547 	case NETAGENT_MESSAGE_TYPE_GET: {
548 		netagent_handle_get(session, header.message_id, header.message_payload_length,
549 		    packet, sizeof(header));
550 		break;
551 	}
552 	case NETAGENT_MESSAGE_TYPE_ASSERT: {
553 		NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
554 		break;
555 	}
556 	case NETAGENT_MESSAGE_TYPE_UNASSERT: {
557 		NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
558 		break;
559 	}
560 	case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS: {
561 		netagent_handle_assign_nexus_message(session, header.message_id, header.message_payload_length,
562 		    packet, sizeof(header));
563 		break;
564 	}
565 	default: {
566 		NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
567 		netagent_send_error_response(session, header.message_type, header.message_id,
568 		    NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
569 		break;
570 	}
571 	}
572 
573 done:
574 	mbuf_freem(packet);
575 	return error;
576 }
577 
578 static void
netagent_ctl_rcvd(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int flags)579 netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
580 {
581 #pragma unused(kctlref, unit, unitinfo, flags)
582 	return;
583 }
584 
585 static errno_t
netagent_ctl_getopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t * len)586 netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
587     void *data, size_t *len)
588 {
589 #pragma unused(kctlref, unit)
590 	struct netagent_session *session = (struct netagent_session *)unitinfo;
591 	errno_t error;
592 
593 	if (session == NULL) {
594 		NETAGENTLOG0(LOG_ERR, "Received a NULL session");
595 		error = EINVAL;
596 		goto done;
597 	}
598 
599 	switch (opt) {
600 	case NETAGENT_OPTION_TYPE_USE_COUNT: {
601 		NETAGENTLOG0(LOG_DEBUG, "Request to get use count");
602 		error = netagent_handle_use_count_getopt(session, data, len);
603 		break;
604 	}
605 	case NETAGENT_OPTION_TYPE_TOKEN_COUNT: {
606 		NETAGENTLOG0(LOG_DEBUG, "Request to get token count");
607 		error = netagent_handle_token_count_getopt(session, data, len);
608 		break;
609 	}
610 	case NETAGENT_OPTION_TYPE_TOKEN_LOW_WATER: {
611 		NETAGENTLOG0(LOG_DEBUG, "Request to get token low water mark");
612 		error = netagent_handle_token_low_water_getopt(session, data, len);
613 		break;
614 	}
615 	default:
616 		NETAGENTLOG0(LOG_ERR, "Received unknown option");
617 		error = ENOPROTOOPT;
618 		break;
619 	}
620 
621 done:
622 	return error;
623 }
624 
625 static errno_t
netagent_ctl_setopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t len)626 netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
627     void *data, size_t len)
628 {
629 #pragma unused(kctlref, unit)
630 	struct netagent_session *session = (struct netagent_session *)unitinfo;
631 	errno_t error;
632 
633 	if (session == NULL) {
634 		NETAGENTLOG0(LOG_ERR, "Received a NULL session");
635 		error = EINVAL;
636 		goto done;
637 	}
638 
639 	switch (opt) {
640 	case NETAGENT_OPTION_TYPE_REGISTER: {
641 		NETAGENTLOG0(LOG_DEBUG, "Request for registration");
642 		error = netagent_handle_register_setopt(session, data, len);
643 		break;
644 	}
645 	case NETAGENT_OPTION_TYPE_UPDATE: {
646 		NETAGENTLOG0(LOG_DEBUG, "Request for update");
647 		error = netagent_handle_update_setopt(session, data, len);
648 		break;
649 	}
650 	case NETAGENT_OPTION_TYPE_UNREGISTER: {
651 		NETAGENTLOG0(LOG_DEBUG, "Request for unregistration");
652 		error = netagent_handle_unregister_setopt(session, data, len);
653 		break;
654 	}
655 	case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS: {
656 		NETAGENTLOG0(LOG_DEBUG, "Request for assigning nexus");
657 		error = netagent_handle_assign_nexus_setopt(session, data, len);
658 		break;
659 	}
660 	case NETAGENT_MESSAGE_TYPE_ASSIGN_GROUP_MEMBERS: {
661 		NETAGENTLOG0(LOG_DEBUG, "Request for assigning group members");
662 		error = netagent_handle_assign_group_setopt(session, data, len);
663 		break;
664 	}
665 	case NETAGENT_OPTION_TYPE_USE_COUNT: {
666 		NETAGENTLOG0(LOG_DEBUG, "Request to set use count");
667 		error = netagent_handle_use_count_setopt(session, data, len);
668 		break;
669 	}
670 	case NETAGENT_OPTION_TYPE_ADD_TOKEN: {
671 		NETAGENTLOG0(LOG_DEBUG, "Request to add a token");
672 		error = netagent_handle_add_token_setopt(session, data, len);
673 		break;
674 	}
675 	case NETAGENT_OPTION_TYPE_FLUSH_TOKENS: {
676 		NETAGENTLOG0(LOG_DEBUG, "Request to flush tokens");
677 		error = netagent_handle_flush_tokens_setopt(session, data, len);
678 		break;
679 	}
680 	case NETAGENT_OPTION_TYPE_TOKEN_LOW_WATER: {
681 		NETAGENTLOG0(LOG_DEBUG, "Request to set token low water mark");
682 		error = netagent_handle_token_low_water_setopt(session, data, len);
683 		break;
684 	}
685 	case NETAGENT_OPTION_TYPE_RESET_CLIENT_ERROR: {
686 		NETAGENTLOG0(LOG_DEBUG, "Request to reset client error");
687 		error = netagent_handle_reset_client_error_setopt(session, data, len);
688 		break;
689 	}
690 	default:
691 		NETAGENTLOG0(LOG_ERR, "Received unknown option");
692 		error = ENOPROTOOPT;
693 		break;
694 	}
695 
696 done:
697 	return error;
698 }
699 
700 // Session Management
701 static struct netagent_session *
netagent_create_session(u_int32_t control_unit)702 netagent_create_session(u_int32_t control_unit)
703 {
704 	struct netagent_session *new_session = NULL;
705 
706 	new_session = kalloc_type(struct netagent_session,
707 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
708 	NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
709 	new_session->control_unit = control_unit;
710 
711 	return new_session;
712 }
713 
714 netagent_session_t
netagent_create(netagent_event_f event_handler,void * context)715 netagent_create(netagent_event_f event_handler, void *context)
716 {
717 	struct netagent_session *session = netagent_create_session(0);
718 	if (session == NULL) {
719 		return NULL;
720 	}
721 
722 	session->event_handler = event_handler;
723 	session->event_context = context;
724 	return session;
725 }
726 
727 static void
netagent_token_free(struct netagent_token * token)728 netagent_token_free(struct netagent_token *token)
729 {
730 	kfree_data(token->token_bytes, token->token_length);
731 	kfree_type(struct netagent_token, token);
732 }
733 
734 static struct netagent_wrapper *
netagent_alloc_wrapper_memory(uint32_t data_size)735 netagent_alloc_wrapper_memory(uint32_t data_size)
736 {
737 	struct netagent_wrapper *new_wrapper;
738 
739 	new_wrapper = kalloc_type(struct netagent_wrapper,
740 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
741 	new_wrapper->netagent = kalloc_data(sizeof(struct netagent) + data_size,
742 	    Z_WAITOK | Z_NOFAIL);
743 
744 	return new_wrapper;
745 }
746 
747 static void
netagent_free_wrapper_memory(struct netagent_wrapper * wrapper)748 netagent_free_wrapper_memory(struct netagent_wrapper *wrapper)
749 {
750 	kfree_data(wrapper->netagent, sizeof(struct netagent) +
751 	    wrapper->netagent->netagent_data_size);
752 	kfree_type(struct netagent_wrapper, wrapper);
753 }
754 
755 static void
netagent_free_wrapper(struct netagent_wrapper * wrapper)756 netagent_free_wrapper(struct netagent_wrapper *wrapper)
757 {
758 	// Free any leftover tokens
759 	struct netagent_token *search_token = NULL;
760 	struct netagent_token *temp_token = NULL;
761 	TAILQ_FOREACH_SAFE(search_token, &wrapper->token_list, token_chain, temp_token) {
762 		TAILQ_REMOVE(&wrapper->token_list, search_token, token_chain);
763 		netagent_token_free(search_token);
764 	}
765 
766 	// Free any pending client triggers
767 	struct netagent_client *search_client = NULL;
768 	struct netagent_client *temp_client = NULL;
769 	LIST_FOREACH_SAFE(search_client, &wrapper->pending_triggers_list, client_chain, temp_client) {
770 		LIST_REMOVE(search_client, client_chain);
771 		kfree_type(struct netagent_client, search_client);
772 	}
773 
774 	// Free wrapper itself
775 	netagent_free_wrapper_memory(wrapper);
776 }
777 
778 static void
netagent_unregister_session_wrapper(struct netagent_session * session)779 netagent_unregister_session_wrapper(struct netagent_session *session)
780 {
781 	bool unregistered = FALSE;
782 	uuid_t unregistered_uuid;
783 	struct netagent_wrapper *wrapper = NULL;
784 	lck_rw_lock_exclusive(&netagent_lock);
785 	if (session != NULL) {
786 		wrapper = session->wrapper;
787 		if (wrapper != NULL) {
788 			if (netagent_registered_count > 0) {
789 				netagent_registered_count--;
790 			}
791 			if ((session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
792 			    netagent_active_count > 0) {
793 				netagent_active_count--;
794 			}
795 
796 			LIST_REMOVE(wrapper, master_chain);
797 
798 			unregistered = TRUE;
799 			uuid_copy(unregistered_uuid, session->wrapper->netagent->netagent_uuid);
800 
801 			netagent_free_wrapper(session->wrapper);
802 			session->wrapper = NULL;
803 			NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
804 		}
805 	}
806 	lck_rw_done(&netagent_lock);
807 
808 	if (unregistered) {
809 		ifnet_clear_netagent(unregistered_uuid);
810 		netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED, TRUE, false);
811 	}
812 }
813 
814 static void
netagent_delete_session(struct netagent_session * session)815 netagent_delete_session(struct netagent_session *session)
816 {
817 	if (session != NULL) {
818 		netagent_unregister_session_wrapper(session);
819 		kfree_type(struct netagent_session, session);
820 	}
821 }
822 
823 void
netagent_destroy(netagent_session_t session)824 netagent_destroy(netagent_session_t session)
825 {
826 	return netagent_delete_session((struct netagent_session *)session);
827 }
828 
829 static size_t
netagent_packet_get_netagent_data_size(mbuf_t packet,size_t offset,int * err)830 netagent_packet_get_netagent_data_size(mbuf_t packet, size_t offset, int *err)
831 {
832 	int error = 0;
833 
834 	struct netagent netagent_peek;
835 	memset(&netagent_peek, 0, sizeof(netagent_peek));
836 
837 	*err = 0;
838 
839 	error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
840 	if (error) {
841 		*err = ENOENT;
842 		return 0;
843 	}
844 
845 	return netagent_peek.netagent_data_size;
846 }
847 
848 static errno_t
netagent_handle_register_inner(struct netagent_session * session,struct netagent_wrapper * new_wrapper)849 netagent_handle_register_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper)
850 {
851 	lck_rw_lock_exclusive(&netagent_lock);
852 
853 	if (session->wrapper != NULL) {
854 		lck_rw_done(&netagent_lock);
855 		return EINVAL;
856 	}
857 
858 	new_wrapper->control_unit = session->control_unit;
859 	new_wrapper->event_handler = session->event_handler;
860 	new_wrapper->event_context = session->event_context;
861 	new_wrapper->generation = g_next_generation++;
862 
863 	session->wrapper = new_wrapper;
864 	LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
865 	TAILQ_INIT(&new_wrapper->token_list);
866 	LIST_INIT(&new_wrapper->pending_triggers_list);
867 
868 	new_wrapper->netagent->netagent_flags |= NETAGENT_FLAG_REGISTERED;
869 	netagent_registered_count++;
870 	if (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) {
871 		netagent_active_count++;
872 	}
873 
874 	lck_rw_done(&netagent_lock);
875 
876 	return 0;
877 }
878 
879 errno_t
netagent_register(netagent_session_t _session,struct netagent * agent)880 netagent_register(netagent_session_t _session, struct netagent *agent)
881 {
882 	struct netagent_wrapper *new_wrapper = NULL;
883 	uuid_t registered_uuid;
884 
885 	struct netagent_session *session = (struct netagent_session *)_session;
886 	if (session == NULL) {
887 		NETAGENTLOG0(LOG_ERR, "Cannot register agent on NULL session");
888 		return EINVAL;
889 	}
890 
891 	if (agent == NULL) {
892 		NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
893 		return EINVAL;
894 	}
895 
896 	if (session->wrapper != NULL) {
897 		NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
898 		return EINVAL;
899 	}
900 
901 	size_t data_size = agent->netagent_data_size;
902 	if (data_size > NETAGENT_MAX_DATA_SIZE) {
903 		NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu",
904 		    data_size);
905 		return EINVAL;
906 	}
907 
908 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
909 
910 	__nochk_memcpy(new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
911 
912 	uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
913 
914 	errno_t error = netagent_handle_register_inner(session, new_wrapper);
915 	if (error != 0) {
916 		netagent_free_wrapper_memory(new_wrapper);
917 		return error;
918 	}
919 
920 	NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
921 	netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
922 
923 	return 0;
924 }
925 
926 static errno_t
netagent_handle_register_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)927 netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
928     size_t payload_length)
929 {
930 	struct netagent_wrapper *new_wrapper = NULL;
931 	errno_t response_error = 0;
932 	struct netagent *register_netagent = (struct netagent *)(void *)payload;
933 	uuid_t registered_uuid;
934 
935 	if (session == NULL) {
936 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
937 		response_error = EINVAL;
938 		goto done;
939 	}
940 
941 	if (payload == NULL) {
942 		NETAGENTLOG0(LOG_ERR, "No payload received");
943 		response_error = EINVAL;
944 		goto done;
945 	}
946 
947 	if (session->wrapper != NULL) {
948 		NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
949 		response_error = EINVAL;
950 		goto done;
951 	}
952 
953 	if (payload_length < sizeof(struct netagent)) {
954 		NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
955 		    payload_length, sizeof(struct netagent));
956 		response_error = EINVAL;
957 		goto done;
958 	}
959 
960 	size_t data_size = register_netagent->netagent_data_size;
961 	if (data_size > NETAGENT_MAX_DATA_SIZE) {
962 		NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu", data_size);
963 		response_error = EINVAL;
964 		goto done;
965 	}
966 
967 	if (payload_length != (sizeof(struct netagent) + data_size)) {
968 		NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
969 		response_error = EINVAL;
970 		goto done;
971 	}
972 
973 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
974 
975 	__nochk_memcpy(new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
976 
977 	uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
978 
979 	response_error = netagent_handle_register_inner(session, new_wrapper);
980 	if (response_error != 0) {
981 		netagent_free_wrapper_memory(new_wrapper);
982 		goto done;
983 	}
984 
985 	NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
986 	netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
987 
988 done:
989 	return response_error;
990 }
991 
992 static void
netagent_handle_register_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)993 netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
994     size_t payload_length, mbuf_t packet, size_t offset)
995 {
996 	errno_t error;
997 	struct netagent_wrapper *new_wrapper = NULL;
998 	u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
999 	uuid_t registered_uuid;
1000 
1001 	if (session == NULL) {
1002 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1003 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1004 		goto fail;
1005 	}
1006 
1007 	if (session->wrapper != NULL) {
1008 		NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
1009 		response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
1010 		goto fail;
1011 	}
1012 
1013 	if (payload_length < sizeof(struct netagent)) {
1014 		NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
1015 		    payload_length, sizeof(struct netagent));
1016 		response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1017 		goto fail;
1018 	}
1019 
1020 	size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1021 	if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
1022 		NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %zu",
1023 		    error, data_size);
1024 		response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1025 		goto fail;
1026 	}
1027 
1028 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
1029 
1030 	error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
1031 	    new_wrapper->netagent);
1032 	if (error) {
1033 		NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1034 		netagent_free_wrapper_memory(new_wrapper);
1035 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1036 		goto fail;
1037 	}
1038 
1039 	uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
1040 
1041 	error = netagent_handle_register_inner(session, new_wrapper);
1042 	if (error) {
1043 		NETAGENTLOG(LOG_ERR, "Failed to register agent: %d", error);
1044 		netagent_free_wrapper_memory(new_wrapper);
1045 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1046 		goto fail;
1047 	}
1048 
1049 	NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
1050 	netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
1051 	netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
1052 	return;
1053 fail:
1054 	netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
1055 }
1056 
1057 errno_t
netagent_unregister(netagent_session_t _session)1058 netagent_unregister(netagent_session_t _session)
1059 {
1060 	struct netagent_session *session = (struct netagent_session *)_session;
1061 	if (session == NULL) {
1062 		NETAGENTLOG0(LOG_ERR, "Cannot unregister NULL session");
1063 		return EINVAL;
1064 	}
1065 
1066 	netagent_unregister_session_wrapper(session);
1067 	return 0;
1068 }
1069 
1070 static errno_t
netagent_handle_unregister_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1071 netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
1072     size_t payload_length)
1073 {
1074 #pragma unused(payload, payload_length)
1075 	errno_t response_error = 0;
1076 
1077 	if (session == NULL) {
1078 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1079 		response_error = EINVAL;
1080 		goto done;
1081 	}
1082 
1083 	netagent_unregister_session_wrapper(session);
1084 
1085 done:
1086 	return response_error;
1087 }
1088 
1089 static void
netagent_handle_unregister_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1090 netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
1091     size_t payload_length, mbuf_t packet, size_t offset)
1092 {
1093 #pragma unused(payload_length, packet, offset)
1094 	u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1095 
1096 	if (session == NULL) {
1097 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1098 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1099 		goto fail;
1100 	}
1101 
1102 	netagent_unregister_session_wrapper(session);
1103 
1104 	netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
1105 	return;
1106 fail:
1107 	netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
1108 }
1109 
1110 static void
netagent_send_cellular_failed_event(struct netagent_wrapper * wrapper,pid_t pid,uuid_t proc_uuid)1111 netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
1112     pid_t pid, uuid_t proc_uuid)
1113 {
1114 	if (strncmp(wrapper->netagent->netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
1115 		return;
1116 	}
1117 
1118 	struct kev_netpolicy_ifdenied ev_ifdenied;
1119 
1120 	bzero(&ev_ifdenied, sizeof(ev_ifdenied));
1121 
1122 	ev_ifdenied.ev_data.epid = (u_int64_t)pid;
1123 	uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
1124 	ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
1125 
1126 	netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
1127 }
1128 
1129 static errno_t
netagent_handle_update_inner(struct netagent_session * session,struct netagent_wrapper * new_wrapper,size_t data_size,u_int8_t * agent_changed,netagent_error_domain_t error_domain)1130 netagent_handle_update_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper, size_t data_size, u_int8_t *agent_changed, netagent_error_domain_t error_domain)
1131 {
1132 	errno_t response_error = 0;
1133 
1134 	if (agent_changed == NULL) {
1135 		NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
1136 		return EINVAL;
1137 	}
1138 
1139 	lck_rw_lock_exclusive(&netagent_lock);
1140 
1141 	if (session->wrapper == NULL) {
1142 		lck_rw_done(&netagent_lock);
1143 		response_error = ENOENT;
1144 		return response_error;
1145 	}
1146 
1147 	if (uuid_compare(session->wrapper->netagent->netagent_uuid, new_wrapper->netagent->netagent_uuid) != 0 ||
1148 	    memcmp(&session->wrapper->netagent->netagent_domain, &new_wrapper->netagent->netagent_domain,
1149 	    sizeof(new_wrapper->netagent->netagent_domain)) != 0 ||
1150 	    memcmp(&session->wrapper->netagent->netagent_type, &new_wrapper->netagent->netagent_type,
1151 	    sizeof(new_wrapper->netagent->netagent_type)) != 0) {
1152 		lck_rw_done(&netagent_lock);
1153 		NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
1154 		if (error_domain == kNetagentErrorDomainPOSIX) {
1155 			response_error = EINVAL;
1156 		} else if (error_domain == kNetagentErrorDomainUserDefined) {
1157 			response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
1158 		}
1159 		return response_error;
1160 	}
1161 
1162 	new_wrapper->netagent->netagent_flags |= NETAGENT_FLAG_REGISTERED;
1163 	if (session->wrapper->netagent->netagent_data_size == new_wrapper->netagent->netagent_data_size &&
1164 	    memcmp(session->wrapper->netagent, new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
1165 		// Agent is exactly identical, don't increment the generation count
1166 
1167 		// Make a copy of the list of pending clients, and clear the current list
1168 		struct netagent_client_list_s pending_triggers_list_copy;
1169 		LIST_INIT(&pending_triggers_list_copy);
1170 		struct netagent_client *search_client = NULL;
1171 		struct netagent_client *temp_client = NULL;
1172 		LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
1173 			LIST_REMOVE(search_client, client_chain);
1174 			LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
1175 		}
1176 		lck_rw_done(&netagent_lock);
1177 
1178 		// Update pending client triggers without holding a lock
1179 		search_client = NULL;
1180 		temp_client = NULL;
1181 		LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
1182 			necp_force_update_client(search_client->client_id, session->wrapper->netagent->netagent_uuid, session->wrapper->generation);
1183 			netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
1184 			LIST_REMOVE(search_client, client_chain);
1185 			kfree_type(struct netagent_client, search_client);
1186 		}
1187 		NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
1188 		*agent_changed = FALSE;
1189 		return response_error;
1190 	}
1191 
1192 	new_wrapper->generation = g_next_generation++;
1193 	new_wrapper->use_count = session->wrapper->use_count;
1194 
1195 	TAILQ_INIT(&new_wrapper->token_list);
1196 	TAILQ_CONCAT(&new_wrapper->token_list, &session->wrapper->token_list, token_chain);
1197 	new_wrapper->token_count = session->wrapper->token_count;
1198 	new_wrapper->token_low_water = session->wrapper->token_low_water;
1199 	new_wrapper->last_client_error = session->wrapper->last_client_error;
1200 	new_wrapper->client_error_count = session->wrapper->client_error_count;
1201 
1202 	if ((new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1203 	    !(session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1204 		netagent_active_count++;
1205 	} else if (!(new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1206 	    (session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1207 	    netagent_active_count > 0) {
1208 		netagent_active_count--;
1209 	}
1210 
1211 	LIST_REMOVE(session->wrapper, master_chain);
1212 	netagent_free_wrapper(session->wrapper);
1213 	session->wrapper = new_wrapper;
1214 	new_wrapper->control_unit = session->control_unit;
1215 	new_wrapper->event_handler = session->event_handler;
1216 	new_wrapper->event_context = session->event_context;
1217 	LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
1218 	LIST_INIT(&new_wrapper->pending_triggers_list);
1219 
1220 	NETAGENTLOG0(LOG_DEBUG, "Updated agent");
1221 	*agent_changed = TRUE;
1222 
1223 	lck_rw_done(&netagent_lock);
1224 
1225 	return response_error;
1226 }
1227 
1228 errno_t
netagent_update(netagent_session_t _session,struct netagent * agent)1229 netagent_update(netagent_session_t _session, struct netagent *agent)
1230 {
1231 	u_int8_t agent_changed;
1232 	struct netagent_wrapper *new_wrapper = NULL;
1233 	bool should_update_immediately;
1234 	uuid_t updated_uuid;
1235 
1236 	struct netagent_session *session = (struct netagent_session *)_session;
1237 	if (session == NULL) {
1238 		NETAGENTLOG0(LOG_ERR, "Cannot update agent on NULL session");
1239 		return EINVAL;
1240 	}
1241 
1242 	if (agent == NULL) {
1243 		NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
1244 		return EINVAL;
1245 	}
1246 
1247 	if (session->wrapper == NULL) {
1248 		NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1249 		return EINVAL;
1250 	}
1251 
1252 	size_t data_size = agent->netagent_data_size;
1253 	if (data_size > NETAGENT_MAX_DATA_SIZE) {
1254 		NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1255 		return EINVAL;
1256 	}
1257 
1258 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
1259 
1260 	__nochk_memcpy(new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
1261 
1262 	uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1263 	should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1264 
1265 	errno_t error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1266 	if (error == 0) {
1267 		netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1268 		if (agent_changed == FALSE) {
1269 			// The session wrapper does not need the "new_wrapper" as nothing changed
1270 			netagent_free_wrapper_memory(new_wrapper);
1271 		}
1272 	} else {
1273 		netagent_free_wrapper_memory(new_wrapper);
1274 		return error;
1275 	}
1276 
1277 	return 0;
1278 }
1279 
1280 static errno_t
netagent_handle_update_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1281 netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1282 {
1283 	struct netagent_wrapper *new_wrapper = NULL;
1284 	errno_t response_error = 0;
1285 	struct netagent *update_netagent = (struct netagent *)(void *)payload;
1286 	u_int8_t agent_changed;
1287 	bool should_update_immediately;
1288 	uuid_t updated_uuid;
1289 
1290 	if (session == NULL) {
1291 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1292 		response_error = EINVAL;
1293 		goto done;
1294 	}
1295 
1296 	if (payload == NULL) {
1297 		NETAGENTLOG0(LOG_ERR, "No payload received");
1298 		response_error = EINVAL;
1299 		goto done;
1300 	}
1301 
1302 	if (session->wrapper == NULL) {
1303 		NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1304 		response_error = ENOENT;
1305 		goto done;
1306 	}
1307 
1308 	if (payload_length < sizeof(struct netagent)) {
1309 		NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1310 		    payload_length, sizeof(struct netagent));
1311 		response_error = EINVAL;
1312 		goto done;
1313 	}
1314 
1315 	size_t data_size = update_netagent->netagent_data_size;
1316 	if (data_size > NETAGENT_MAX_DATA_SIZE) {
1317 		NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1318 		response_error = EINVAL;
1319 		goto done;
1320 	}
1321 
1322 	if (payload_length != (sizeof(struct netagent) + data_size)) {
1323 		NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
1324 		response_error = EINVAL;
1325 		goto done;
1326 	}
1327 
1328 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
1329 
1330 	__nochk_memcpy(new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1331 
1332 	uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1333 	should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1334 
1335 	response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1336 	if (response_error == 0) {
1337 		netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1338 		if (agent_changed == FALSE) {
1339 			// The session wrapper does not need the "new_wrapper" as nothing changed
1340 			netagent_free_wrapper_memory(new_wrapper);
1341 		}
1342 	} else {
1343 		netagent_free_wrapper_memory(new_wrapper);
1344 	}
1345 
1346 done:
1347 	return response_error;
1348 }
1349 
1350 static void
netagent_handle_update_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1351 netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1352     size_t payload_length, mbuf_t packet, size_t offset)
1353 {
1354 	int error;
1355 	struct netagent_wrapper *new_wrapper = NULL;
1356 	u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1357 	u_int8_t agent_changed;
1358 	uuid_t updated_uuid;
1359 	bool should_update_immediately;
1360 
1361 	if (session == NULL) {
1362 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1363 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1364 		goto fail;
1365 	}
1366 
1367 	if (session->wrapper == NULL) {
1368 		NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1369 		response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1370 		goto fail;
1371 	}
1372 
1373 	if (payload_length < sizeof(struct netagent)) {
1374 		NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1375 		    payload_length, sizeof(struct netagent));
1376 		response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1377 		goto fail;
1378 	}
1379 
1380 	size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1381 	if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
1382 		NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %zu",
1383 		    error, data_size);
1384 		response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1385 		goto fail;
1386 	}
1387 
1388 	new_wrapper = netagent_alloc_wrapper_memory(data_size);
1389 
1390 	error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, new_wrapper->netagent);
1391 	if (error) {
1392 		NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1393 		netagent_free_wrapper_memory(new_wrapper);
1394 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1395 		goto fail;
1396 	}
1397 
1398 	uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1399 	should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1400 
1401 	response_error = (u_int32_t)netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainUserDefined);
1402 	if (response_error != 0) {
1403 		netagent_free_wrapper_memory(new_wrapper);
1404 		goto fail;
1405 	}
1406 
1407 	netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1408 	netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1409 
1410 	if (agent_changed == FALSE) {
1411 		// The session wrapper does not need the "new_wrapper" as nothing changed
1412 		netagent_free_wrapper_memory(new_wrapper);
1413 	}
1414 
1415 	return;
1416 fail:
1417 	netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1418 }
1419 
1420 static void
netagent_handle_get(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1421 netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1422     size_t payload_length, mbuf_t packet, size_t offset)
1423 {
1424 #pragma unused(payload_length, packet, offset)
1425 	u_int8_t *response = NULL;
1426 	u_int8_t *cursor = NULL;
1427 	u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1428 
1429 	if (session == NULL) {
1430 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1431 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1432 		goto fail;
1433 	}
1434 
1435 	lck_rw_lock_shared(&netagent_lock);
1436 
1437 	if (session->wrapper == NULL) {
1438 		lck_rw_done(&netagent_lock);
1439 		NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1440 		response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1441 		goto fail;
1442 	}
1443 
1444 	size_t response_size = sizeof(struct netagent_message_header)
1445 	    + sizeof(struct netagent)
1446 	    + session->wrapper->netagent->netagent_data_size;
1447 	response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
1448 	if (response == NULL) {
1449 		goto fail;
1450 	}
1451 
1452 	cursor = response;
1453 	cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1454 	    NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1455 	    response_size - sizeof(struct netagent_message_header));
1456 	memcpy(cursor, session->wrapper->netagent, sizeof(struct netagent) +
1457 	    session->wrapper->netagent->netagent_data_size);
1458 
1459 	lck_rw_done(&netagent_lock);
1460 
1461 	if (!netagent_send_ctl_data(session->control_unit, response, response_size)) {
1462 		NETAGENTLOG0(LOG_ERR, "Failed to send response");
1463 	}
1464 	kfree_data(response, response_size);
1465 	return;
1466 fail:
1467 	netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1468 }
1469 
1470 errno_t
netagent_assign_nexus(netagent_session_t _session,uuid_t necp_client_uuid,void * assign_message,size_t assigned_results_length)1471 netagent_assign_nexus(netagent_session_t _session, uuid_t necp_client_uuid,
1472     void *assign_message, size_t assigned_results_length)
1473 {
1474 	struct netagent_session *session = (struct netagent_session *)_session;
1475 	uuid_t netagent_uuid;
1476 	if (session == NULL) {
1477 		NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1478 		return EINVAL;
1479 	}
1480 
1481 	lck_rw_lock_shared(&netagent_lock);
1482 	if (session->wrapper == NULL) {
1483 		lck_rw_done(&netagent_lock);
1484 		NETAGENTLOG0(LOG_ERR, "Session has no agent");
1485 		return ENOENT;
1486 	}
1487 	uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1488 	lck_rw_done(&netagent_lock);
1489 
1490 	// Note that if the error is 0, NECP has taken over our malloc'ed buffer
1491 	int error = necp_assign_client_result(netagent_uuid, necp_client_uuid, assign_message, assigned_results_length);
1492 	if (error) {
1493 		// necp_assign_client_result returns POSIX errors; don't error for ENOENT
1494 		NETAGENTLOG((error == ENOENT ? LOG_DEBUG : LOG_ERR), "Client assignment failed: %d", error);
1495 		return error;
1496 	}
1497 
1498 	NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1499 	return 0;
1500 }
1501 
1502 errno_t
netagent_update_flow_protoctl_event(netagent_session_t _session,uuid_t client_id,uint32_t protoctl_event_code,uint32_t protoctl_event_val,uint32_t protoctl_event_tcp_seq_number)1503 netagent_update_flow_protoctl_event(netagent_session_t _session,
1504     uuid_t client_id, uint32_t protoctl_event_code,
1505     uint32_t protoctl_event_val, uint32_t protoctl_event_tcp_seq_number)
1506 {
1507 	struct netagent_session *session = (struct netagent_session *)_session;
1508 	uuid_t netagent_uuid;
1509 	int error = 0;
1510 
1511 	if (session == NULL) {
1512 		NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1513 		return EINVAL;
1514 	}
1515 
1516 	lck_rw_lock_shared(&netagent_lock);
1517 	if (session->wrapper == NULL) {
1518 		lck_rw_done(&netagent_lock);
1519 		NETAGENTLOG0(LOG_ERR, "Session has no agent");
1520 		return ENOENT;
1521 	}
1522 	uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1523 	lck_rw_done(&netagent_lock);
1524 
1525 	error = necp_update_flow_protoctl_event(netagent_uuid,
1526 	    client_id, protoctl_event_code, protoctl_event_val, protoctl_event_tcp_seq_number);
1527 
1528 	return error;
1529 }
1530 
1531 static errno_t
netagent_handle_assign_nexus_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1532 netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1533     size_t payload_length)
1534 {
1535 	errno_t response_error = 0;
1536 	struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1537 	uuid_t client_id;
1538 	uuid_t netagent_uuid;
1539 	u_int8_t *assigned_results = NULL;
1540 
1541 	if (session == NULL) {
1542 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1543 		response_error = ENOENT;
1544 		goto done;
1545 	}
1546 
1547 	if (payload == NULL) {
1548 		NETAGENTLOG0(LOG_ERR, "No payload received");
1549 		response_error = EINVAL;
1550 		goto done;
1551 	}
1552 
1553 	lck_rw_lock_shared(&netagent_lock);
1554 	if (session->wrapper == NULL) {
1555 		lck_rw_done(&netagent_lock);
1556 		NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1557 		response_error = ENOENT;
1558 		goto done;
1559 	}
1560 
1561 	uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1562 	lck_rw_done(&netagent_lock);
1563 
1564 	if (payload_length < sizeof(uuid_t)) {
1565 		NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1566 		response_error = EINVAL;
1567 		goto done;
1568 	}
1569 
1570 	memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1571 	size_t assigned_results_length = (payload_length - sizeof(client_id));
1572 
1573 	if (assigned_results_length > 0) {
1574 		assigned_results = kalloc_data(assigned_results_length, Z_WAITOK);
1575 		if (assigned_results == NULL) {
1576 			NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1577 			response_error = ENOMEM;
1578 			goto done;
1579 		}
1580 		memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1581 	}
1582 
1583 	// Note that if the error is 0, NECP has taken over our malloc'ed buffer
1584 	response_error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1585 	if (response_error) {
1586 		// necp_assign_client_result returns POSIX errors
1587 		kfree_data(assigned_results, assigned_results_length);
1588 		NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1589 		goto done;
1590 	}
1591 
1592 	NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1593 done:
1594 	return response_error;
1595 }
1596 
1597 
1598 static void
netagent_handle_assign_nexus_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1599 netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1600     size_t payload_length, mbuf_t packet, size_t offset)
1601 {
1602 	int error = 0;
1603 	u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1604 	uuid_t client_id;
1605 	uuid_t netagent_uuid;
1606 	u_int8_t *assigned_results = NULL;
1607 
1608 	if (session == NULL) {
1609 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1610 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1611 		goto fail;
1612 	}
1613 
1614 	lck_rw_lock_shared(&netagent_lock);
1615 	if (session->wrapper == NULL) {
1616 		lck_rw_done(&netagent_lock);
1617 		NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1618 		response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1619 		goto fail;
1620 	}
1621 	uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1622 	lck_rw_done(&netagent_lock);
1623 
1624 	if (payload_length < sizeof(uuid_t)) {
1625 		NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1626 		response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1627 		goto fail;
1628 	}
1629 
1630 	error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1631 	if (error) {
1632 		NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1633 		response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1634 		goto fail;
1635 	}
1636 
1637 	size_t assigned_results_length = (payload_length - sizeof(client_id));
1638 	if (assigned_results_length > 0) {
1639 		assigned_results = kalloc_data( assigned_results_length, Z_WAITOK);
1640 		if (assigned_results == NULL) {
1641 			NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1642 			response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1643 			goto fail;
1644 		}
1645 
1646 		error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1647 		if (error) {
1648 			kfree_data(assigned_results, assigned_results_length);
1649 			NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1650 			response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1651 			goto fail;
1652 		}
1653 	}
1654 
1655 	// Note that if the error is 0, NECP has taken over our malloc'ed buffer
1656 	error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1657 	if (error) {
1658 		kfree_data(assigned_results, assigned_results_length);
1659 		NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1660 		response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1661 		goto fail;
1662 	}
1663 
1664 	NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1665 	netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1666 	return;
1667 fail:
1668 	netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1669 }
1670 
1671 static errno_t
netagent_handle_assign_group_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1672 netagent_handle_assign_group_setopt(struct netagent_session *session, u_int8_t *payload,
1673     size_t payload_length)
1674 {
1675 	errno_t response_error = 0;
1676 	struct netagent_assign_nexus_message *assign_message = (struct netagent_assign_nexus_message *)(void *)payload;
1677 	uuid_t client_id;
1678 	uuid_t netagent_uuid;
1679 	u_int8_t *assigned_group_members = NULL;
1680 
1681 	if (session == NULL) {
1682 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1683 		response_error = ENOENT;
1684 		goto done;
1685 	}
1686 
1687 	if (payload == NULL) {
1688 		NETAGENTLOG0(LOG_ERR, "No payload received");
1689 		response_error = EINVAL;
1690 		goto done;
1691 	}
1692 
1693 	lck_rw_lock_shared(&netagent_lock);
1694 	if (session->wrapper == NULL) {
1695 		lck_rw_done(&netagent_lock);
1696 		NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1697 		response_error = ENOENT;
1698 		goto done;
1699 	}
1700 
1701 	uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1702 	lck_rw_done(&netagent_lock);
1703 
1704 	if (payload_length < sizeof(uuid_t)) {
1705 		NETAGENTLOG0(LOG_ERR, "Group assign message is too short");
1706 		response_error = EINVAL;
1707 		goto done;
1708 	}
1709 
1710 	memcpy(client_id, assign_message->assign_client_id, sizeof(client_id));
1711 	size_t assigned_group_members_length = (payload_length - sizeof(client_id));
1712 
1713 	if (assigned_group_members_length > 0) {
1714 		assigned_group_members = (u_int8_t *)kalloc_data(assigned_group_members_length, Z_WAITOK);
1715 		if (assigned_group_members == NULL) {
1716 			NETAGENTLOG(LOG_ERR, "Failed to allocate group assign message (%lu bytes)", assigned_group_members_length);
1717 			response_error = ENOMEM;
1718 			goto done;
1719 		}
1720 		memcpy(assigned_group_members, assign_message->assign_necp_results, assigned_group_members_length);
1721 	}
1722 
1723 	// Note that if the error is 0, NECP has taken over our malloc'ed buffer
1724 	response_error = necp_assign_client_group_members(netagent_uuid, client_id, assigned_group_members, assigned_group_members_length);
1725 	if (response_error != 0) {
1726 		// necp_assign_client_group_members returns POSIX errors
1727 		if (assigned_group_members != NULL) {
1728 			kfree_data(assigned_group_members, assigned_group_members_length);
1729 		}
1730 		NETAGENTLOG(LOG_ERR, "Client group assignment failed: %d", response_error);
1731 		goto done;
1732 	}
1733 
1734 	NETAGENTLOG0(LOG_DEBUG, "Agent assigned group members to client");
1735 done:
1736 	return response_error;
1737 }
1738 
1739 
1740 errno_t
netagent_handle_use_count_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1741 netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1742 {
1743 	errno_t response_error = 0;
1744 	uint64_t use_count = 0;
1745 
1746 	if (session == NULL) {
1747 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1748 		response_error = ENOENT;
1749 		goto done;
1750 	}
1751 
1752 	if (payload == NULL) {
1753 		NETAGENTLOG0(LOG_ERR, "No payload received");
1754 		response_error = EINVAL;
1755 		goto done;
1756 	}
1757 
1758 	if (payload_length != sizeof(use_count)) {
1759 		NETAGENTLOG(LOG_ERR, "Payload length is invalid (%lu)", payload_length);
1760 		response_error = EINVAL;
1761 		goto done;
1762 	}
1763 
1764 	memcpy(&use_count, payload, sizeof(use_count));
1765 
1766 	lck_rw_lock_shared(&netagent_lock);
1767 
1768 	if (session->wrapper == NULL) {
1769 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1770 		response_error = ENOENT;
1771 		lck_rw_done(&netagent_lock);
1772 		goto done;
1773 	}
1774 
1775 	session->wrapper->use_count = use_count;
1776 
1777 	lck_rw_done(&netagent_lock);
1778 
1779 done:
1780 	return response_error;
1781 }
1782 
1783 errno_t
netagent_handle_use_count_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)1784 netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1785 {
1786 	errno_t response_error = 0;
1787 	uint64_t use_count = 0;
1788 
1789 	if (session == NULL) {
1790 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1791 		response_error = ENOENT;
1792 		goto done;
1793 	}
1794 
1795 	if (buffer == NULL) {
1796 		NETAGENTLOG0(LOG_ERR, "No payload received");
1797 		response_error = EINVAL;
1798 		goto done;
1799 	}
1800 
1801 	if (*buffer_length != sizeof(use_count)) {
1802 		NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1803 		response_error = EINVAL;
1804 		goto done;
1805 	}
1806 
1807 	lck_rw_lock_shared(&netagent_lock);
1808 
1809 	if (session->wrapper == NULL) {
1810 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1811 		response_error = ENOENT;
1812 		lck_rw_done(&netagent_lock);
1813 		goto done;
1814 	}
1815 
1816 	use_count = session->wrapper->use_count;
1817 	lck_rw_done(&netagent_lock);
1818 
1819 	memcpy(buffer, &use_count, sizeof(use_count));
1820 	*buffer_length = sizeof(use_count);
1821 
1822 done:
1823 	return response_error;
1824 }
1825 
1826 static errno_t
netagent_handle_add_token_setopt(struct netagent_session * session,u_int8_t * token,size_t token_length)1827 netagent_handle_add_token_setopt(struct netagent_session *session, u_int8_t *token, size_t token_length)
1828 {
1829 	errno_t response_error = 0;
1830 
1831 	if (session == NULL) {
1832 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1833 		response_error = ENOENT;
1834 		goto done;
1835 	}
1836 
1837 	if (token == NULL) {
1838 		NETAGENTLOG0(LOG_ERR, "No token received");
1839 		response_error = EINVAL;
1840 		goto done;
1841 	}
1842 
1843 	if (token_length > NETAGENT_MAX_DATA_SIZE) {
1844 		NETAGENTLOG(LOG_ERR, "Token length is invalid (%lu)", token_length);
1845 		response_error = EINVAL;
1846 		goto done;
1847 	}
1848 
1849 	lck_rw_lock_exclusive(&netagent_lock);
1850 
1851 	if (session->wrapper == NULL) {
1852 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1853 		response_error = ENOENT;
1854 		lck_rw_done(&netagent_lock);
1855 		goto done;
1856 	}
1857 
1858 	if (session->wrapper->token_count >= NETAGENT_MAX_TOKEN_COUNT) {
1859 		NETAGENTLOG0(LOG_ERR, "Session cannot add more tokens");
1860 		response_error = EINVAL;
1861 		lck_rw_done(&netagent_lock);
1862 		goto done;
1863 	}
1864 
1865 	struct netagent_token *token_struct = NULL;
1866 
1867 	token_struct = kalloc_type(struct netagent_token, Z_WAITOK | Z_ZERO | Z_NOFAIL);
1868 	token_struct->token_bytes = kalloc_data(token_length, Z_WAITOK | Z_NOFAIL);
1869 	token_struct->token_length = (u_int32_t)token_length;
1870 	memcpy(token_struct->token_bytes, token, token_length);
1871 
1872 	TAILQ_INSERT_TAIL(&session->wrapper->token_list, token_struct, token_chain);
1873 
1874 	session->wrapper->token_count++;
1875 
1876 	lck_rw_done(&netagent_lock);
1877 done:
1878 	return response_error;
1879 }
1880 
1881 static errno_t
netagent_handle_flush_tokens_setopt(struct netagent_session * session,__unused u_int8_t * buffer,__unused size_t buffer_length)1882 netagent_handle_flush_tokens_setopt(struct netagent_session *session, __unused u_int8_t *buffer, __unused size_t buffer_length)
1883 {
1884 	errno_t response_error = 0;
1885 
1886 	if (session == NULL) {
1887 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1888 		response_error = ENOENT;
1889 		goto done;
1890 	}
1891 
1892 	lck_rw_lock_exclusive(&netagent_lock);
1893 
1894 	if (session->wrapper == NULL) {
1895 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1896 		response_error = ENOENT;
1897 		lck_rw_done(&netagent_lock);
1898 		goto done;
1899 	}
1900 
1901 	struct netagent_token *search_token = NULL;
1902 	struct netagent_token *temp_token = NULL;
1903 	TAILQ_FOREACH_SAFE(search_token, &session->wrapper->token_list, token_chain, temp_token) {
1904 		TAILQ_REMOVE(&session->wrapper->token_list, search_token, token_chain);
1905 		netagent_token_free(search_token);
1906 	}
1907 	session->wrapper->token_count = 0;
1908 
1909 	lck_rw_done(&netagent_lock);
1910 done:
1911 	return response_error;
1912 }
1913 
1914 static errno_t
netagent_handle_token_count_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)1915 netagent_handle_token_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1916 {
1917 	errno_t response_error = 0;
1918 	uint32_t token_count = 0;
1919 
1920 	if (session == NULL) {
1921 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1922 		response_error = ENOENT;
1923 		goto done;
1924 	}
1925 
1926 	if (buffer == NULL) {
1927 		NETAGENTLOG0(LOG_ERR, "No payload received");
1928 		response_error = EINVAL;
1929 		goto done;
1930 	}
1931 
1932 	if (*buffer_length != sizeof(token_count)) {
1933 		NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1934 		response_error = EINVAL;
1935 		goto done;
1936 	}
1937 
1938 	lck_rw_lock_shared(&netagent_lock);
1939 
1940 	if (session->wrapper == NULL) {
1941 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1942 		response_error = ENOENT;
1943 		lck_rw_done(&netagent_lock);
1944 		goto done;
1945 	}
1946 
1947 	token_count = session->wrapper->token_count;
1948 	lck_rw_done(&netagent_lock);
1949 
1950 	memcpy(buffer, &token_count, sizeof(token_count));
1951 	*buffer_length = sizeof(token_count);
1952 
1953 done:
1954 	return response_error;
1955 }
1956 
1957 static errno_t
netagent_handle_token_low_water_setopt(struct netagent_session * session,u_int8_t * buffer,size_t buffer_length)1958 netagent_handle_token_low_water_setopt(struct netagent_session *session, u_int8_t *buffer, size_t buffer_length)
1959 {
1960 	errno_t response_error = 0;
1961 	uint32_t token_low_water = 0;
1962 
1963 	if (session == NULL) {
1964 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
1965 		response_error = ENOENT;
1966 		goto done;
1967 	}
1968 
1969 	if (buffer == NULL) {
1970 		NETAGENTLOG0(LOG_ERR, "No payload received");
1971 		response_error = EINVAL;
1972 		goto done;
1973 	}
1974 
1975 	if (buffer_length != sizeof(token_low_water)) {
1976 		NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", buffer_length);
1977 		response_error = EINVAL;
1978 		goto done;
1979 	}
1980 
1981 	memcpy(&token_low_water, buffer, sizeof(token_low_water));
1982 
1983 	lck_rw_lock_exclusive(&netagent_lock);
1984 
1985 	if (session->wrapper == NULL) {
1986 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1987 		response_error = ENOENT;
1988 		lck_rw_done(&netagent_lock);
1989 		goto done;
1990 	}
1991 
1992 	session->wrapper->token_low_water = token_low_water;
1993 	lck_rw_done(&netagent_lock);
1994 
1995 done:
1996 	return response_error;
1997 }
1998 
1999 static errno_t
netagent_handle_token_low_water_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)2000 netagent_handle_token_low_water_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
2001 {
2002 	errno_t response_error = 0;
2003 	uint32_t token_low_water = 0;
2004 
2005 	if (session == NULL) {
2006 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
2007 		response_error = ENOENT;
2008 		goto done;
2009 	}
2010 
2011 	if (buffer == NULL) {
2012 		NETAGENTLOG0(LOG_ERR, "No payload received");
2013 		response_error = EINVAL;
2014 		goto done;
2015 	}
2016 
2017 	if (*buffer_length != sizeof(token_low_water)) {
2018 		NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
2019 		response_error = EINVAL;
2020 		goto done;
2021 	}
2022 
2023 	lck_rw_lock_shared(&netagent_lock);
2024 
2025 	if (session->wrapper == NULL) {
2026 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
2027 		response_error = ENOENT;
2028 		lck_rw_done(&netagent_lock);
2029 		goto done;
2030 	}
2031 
2032 	token_low_water = session->wrapper->token_low_water;
2033 	lck_rw_done(&netagent_lock);
2034 
2035 	memcpy(buffer, &token_low_water, sizeof(token_low_water));
2036 	*buffer_length = sizeof(token_low_water);
2037 
2038 done:
2039 	return response_error;
2040 }
2041 
2042 static errno_t
netagent_handle_reset_client_error_setopt(struct netagent_session * session,__unused u_int8_t * payload,__unused size_t payload_length)2043 netagent_handle_reset_client_error_setopt(struct netagent_session *session, __unused u_int8_t *payload, __unused size_t payload_length)
2044 {
2045 	errno_t response_error = 0;
2046 
2047 	if (session == NULL) {
2048 		NETAGENTLOG0(LOG_ERR, "Failed to find session");
2049 		response_error = ENOENT;
2050 		goto done;
2051 	}
2052 
2053 	lck_rw_lock_exclusive(&netagent_lock);
2054 
2055 	if (session->wrapper == NULL) {
2056 		NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
2057 		response_error = ENOENT;
2058 		lck_rw_done(&netagent_lock);
2059 		goto done;
2060 	}
2061 
2062 	struct netagent_token *search_token = NULL;
2063 	struct netagent_token *temp_token = NULL;
2064 	TAILQ_FOREACH_SAFE(search_token, &session->wrapper->token_list, token_chain, temp_token) {
2065 		TAILQ_REMOVE(&session->wrapper->token_list, search_token, token_chain);
2066 		netagent_token_free(search_token);
2067 	}
2068 	session->wrapper->last_client_error = 0;
2069 	session->wrapper->client_error_count = 0;
2070 
2071 	lck_rw_done(&netagent_lock);
2072 done:
2073 	return response_error;
2074 }
2075 
2076 static struct netagent_wrapper *
netagent_find_agent_with_uuid(uuid_t uuid)2077 netagent_find_agent_with_uuid(uuid_t uuid)
2078 {
2079 	struct netagent_wrapper *search_netagent = NULL;
2080 
2081 	LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
2082 		if (uuid_compare(search_netagent->netagent->netagent_uuid, uuid) == 0) {
2083 			return search_netagent;
2084 		}
2085 	}
2086 
2087 	return NULL;
2088 }
2089 
2090 void
netagent_post_updated_interfaces(uuid_t uuid)2091 netagent_post_updated_interfaces(uuid_t uuid)
2092 {
2093 	struct netagent_wrapper *wrapper = NULL;
2094 	lck_rw_lock_shared(&netagent_lock);
2095 	wrapper = netagent_find_agent_with_uuid(uuid);
2096 	lck_rw_done(&netagent_lock);
2097 
2098 	if (wrapper != NULL) {
2099 		netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, TRUE, false);
2100 	} else {
2101 		NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
2102 	}
2103 
2104 	return;
2105 }
2106 
2107 static u_int32_t
netagent_dump_get_data_size_locked()2108 netagent_dump_get_data_size_locked()
2109 {
2110 	struct netagent_wrapper *search_netagent = NULL;
2111 	u_int32_t total_netagent_data_size = 0;
2112 	// Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
2113 	LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
2114 		total_netagent_data_size += sizeof(search_netagent->netagent->netagent_uuid);
2115 	}
2116 	return total_netagent_data_size;
2117 }
2118 
2119 static void
netagent_dump_copy_data_locked(u_int8_t * buffer,u_int32_t buffer_length)2120 netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
2121 {
2122 	size_t response_size = 0;
2123 	u_int8_t *cursor = NULL;
2124 	struct netagent_wrapper *search_netagent = NULL;
2125 
2126 	response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
2127 	cursor = buffer;
2128 	LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
2129 		memcpy(cursor, search_netagent->netagent->netagent_uuid, sizeof(search_netagent->netagent->netagent_uuid));
2130 		cursor += sizeof(search_netagent->netagent->netagent_uuid);
2131 	}
2132 }
2133 
2134 int
netagent_ioctl(u_long cmd,caddr_t data)2135 netagent_ioctl(u_long cmd, caddr_t data)
2136 {
2137 	int error = 0;
2138 
2139 	switch (cmd) {
2140 	case SIOCGIFAGENTLIST32:
2141 	case SIOCGIFAGENTLIST64: {
2142 		/* Check entitlement if the client requests agent dump */
2143 		errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
2144 		if (cred_result != 0) {
2145 			NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
2146 			return EINVAL;
2147 		}
2148 		break;
2149 	}
2150 	default:
2151 		break;
2152 	}
2153 
2154 	lck_rw_lock_shared(&netagent_lock);
2155 	switch (cmd) {
2156 	case SIOCGIFAGENTDATA32: {
2157 		struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
2158 		struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
2159 		if (wrapper == NULL) {
2160 			error = ENOENT;
2161 			break;
2162 		}
2163 		uuid_copy(ifsir32->netagent_uuid, wrapper->netagent->netagent_uuid);
2164 		memcpy(ifsir32->netagent_domain, wrapper->netagent->netagent_domain, sizeof(ifsir32->netagent_domain));
2165 		memcpy(ifsir32->netagent_type, wrapper->netagent->netagent_type, sizeof(ifsir32->netagent_type));
2166 		memcpy(ifsir32->netagent_desc, wrapper->netagent->netagent_desc, sizeof(ifsir32->netagent_desc));
2167 		ifsir32->netagent_flags = wrapper->netagent->netagent_flags;
2168 		if (ifsir32->netagent_data_size == 0) {
2169 			// First pass, client wants data size
2170 			ifsir32->netagent_data_size = wrapper->netagent->netagent_data_size;
2171 		} else if (ifsir32->netagent_data != USER_ADDR_NULL &&
2172 		    ifsir32->netagent_data_size == wrapper->netagent->netagent_data_size) {
2173 			// Second pass, client wants data buffer filled out
2174 			error = copyout(wrapper->netagent->netagent_data, ifsir32->netagent_data, wrapper->netagent->netagent_data_size);
2175 		} else {
2176 			error = EINVAL;
2177 		}
2178 		break;
2179 	}
2180 	case SIOCGIFAGENTDATA64: {
2181 		struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
2182 		struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
2183 		if (wrapper == NULL) {
2184 			error = ENOENT;
2185 			break;
2186 		}
2187 		uuid_copy(ifsir64->netagent_uuid, wrapper->netagent->netagent_uuid);
2188 		memcpy(ifsir64->netagent_domain, wrapper->netagent->netagent_domain, sizeof(ifsir64->netagent_domain));
2189 		memcpy(ifsir64->netagent_type, wrapper->netagent->netagent_type, sizeof(ifsir64->netagent_type));
2190 		memcpy(ifsir64->netagent_desc, wrapper->netagent->netagent_desc, sizeof(ifsir64->netagent_desc));
2191 		ifsir64->netagent_flags = wrapper->netagent->netagent_flags;
2192 		if (ifsir64->netagent_data_size == 0) {
2193 			// First pass, client wants data size
2194 			ifsir64->netagent_data_size = wrapper->netagent->netagent_data_size;
2195 		} else if (ifsir64->netagent_data != USER_ADDR_NULL &&
2196 		    ifsir64->netagent_data_size == wrapper->netagent->netagent_data_size) {
2197 			// Second pass, client wants data buffer filled out
2198 			error = copyout(wrapper->netagent->netagent_data, ifsir64->netagent_data, wrapper->netagent->netagent_data_size);
2199 		} else {
2200 			error = EINVAL;
2201 		}
2202 		break;
2203 	}
2204 	case SIOCGIFAGENTLIST32: {
2205 		struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
2206 		if (ifsir32->data_size == 0) {
2207 			// First pass, client wants data size
2208 			ifsir32->data_size = netagent_dump_get_data_size_locked();
2209 		} else if (ifsir32->data != USER_ADDR_NULL &&
2210 		    ifsir32->data_size > 0 &&
2211 		    ifsir32->data_size == netagent_dump_get_data_size_locked()) {
2212 			// Second pass, client wants data buffer filled out
2213 			u_int8_t *response = NULL;
2214 			response = (u_int8_t *)kalloc_data(ifsir32->data_size, Z_NOWAIT | Z_ZERO);
2215 			if (response == NULL) {
2216 				error = ENOMEM;
2217 				break;
2218 			}
2219 
2220 			netagent_dump_copy_data_locked(response, ifsir32->data_size);
2221 			error = copyout(response, ifsir32->data, ifsir32->data_size);
2222 			kfree_data(response, ifsir32->data_size);
2223 		} else {
2224 			error = EINVAL;
2225 		}
2226 		break;
2227 	}
2228 	case SIOCGIFAGENTLIST64: {
2229 		struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
2230 		if (ifsir64->data_size == 0) {
2231 			// First pass, client wants data size
2232 			ifsir64->data_size = netagent_dump_get_data_size_locked();
2233 		} else if (ifsir64->data != USER_ADDR_NULL &&
2234 		    ifsir64->data_size > 0 &&
2235 		    ifsir64->data_size == netagent_dump_get_data_size_locked()) {
2236 			// Second pass, client wants data buffer filled out
2237 			u_int8_t *response = NULL;
2238 			response = (u_int8_t *)kalloc_data(ifsir64->data_size, Z_NOWAIT | Z_ZERO);
2239 			if (response == NULL) {
2240 				error = ENOMEM;
2241 				break;
2242 			}
2243 
2244 			netagent_dump_copy_data_locked(response, ifsir64->data_size);
2245 			error = copyout(response, ifsir64->data, ifsir64->data_size);
2246 			kfree_data(response, ifsir64->data_size);
2247 		} else {
2248 			error = EINVAL;
2249 		}
2250 		break;
2251 	}
2252 	default: {
2253 		error = EINVAL;
2254 		break;
2255 	}
2256 	}
2257 	lck_rw_done(&netagent_lock);
2258 	return error;
2259 }
2260 
2261 u_int32_t
netagent_get_flags(uuid_t uuid)2262 netagent_get_flags(uuid_t uuid)
2263 {
2264 	u_int32_t flags = 0;
2265 	lck_rw_lock_shared(&netagent_lock);
2266 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
2267 	if (wrapper != NULL) {
2268 		flags = wrapper->netagent->netagent_flags;
2269 	} else {
2270 		NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
2271 	}
2272 	lck_rw_done(&netagent_lock);
2273 
2274 	return flags;
2275 }
2276 
2277 errno_t
netagent_set_flags(uuid_t uuid,u_int32_t flags)2278 netagent_set_flags(uuid_t uuid, u_int32_t flags)
2279 {
2280 	errno_t error = 0;
2281 	bool updated = false;
2282 
2283 	lck_rw_lock_exclusive(&netagent_lock);
2284 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
2285 	if (wrapper != NULL) {
2286 		// Don't allow the clients to clear
2287 		// NETAGENT_FLAG_REGISTERED.
2288 		uint32_t registered =
2289 		    wrapper->netagent->netagent_flags & NETAGENT_FLAG_REGISTERED;
2290 		flags |= registered;
2291 		if (wrapper->netagent->netagent_flags != flags) {
2292 			wrapper->netagent->netagent_flags = flags;
2293 			wrapper->generation = g_next_generation++;
2294 			updated = true;
2295 		}
2296 	} else {
2297 		NETAGENTLOG0(LOG_DEBUG,
2298 		    "Attempt to set flags for invalid netagent");
2299 		error = ENOENT;
2300 	}
2301 	lck_rw_done(&netagent_lock);
2302 	if (updated) {
2303 		netagent_post_event(uuid, KEV_NETAGENT_UPDATED, true, false);
2304 	}
2305 
2306 	return error;
2307 }
2308 
2309 u_int32_t
netagent_get_generation(uuid_t uuid)2310 netagent_get_generation(uuid_t uuid)
2311 {
2312 	u_int32_t generation = 0;
2313 	lck_rw_lock_shared(&netagent_lock);
2314 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
2315 	if (wrapper != NULL) {
2316 		generation = wrapper->generation;
2317 	} else {
2318 		NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
2319 	}
2320 	lck_rw_done(&netagent_lock);
2321 
2322 	return generation;
2323 }
2324 
2325 bool
netagent_get_agent_domain_and_type(uuid_t uuid,char * domain,char * type)2326 netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
2327 {
2328 	bool found = FALSE;
2329 	if (domain == NULL || type == NULL) {
2330 		NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
2331 		return FALSE;
2332 	}
2333 
2334 	lck_rw_lock_shared(&netagent_lock);
2335 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
2336 	if (wrapper != NULL) {
2337 		found = TRUE;
2338 		memcpy(domain, wrapper->netagent->netagent_domain, NETAGENT_DOMAINSIZE);
2339 		memcpy(type, wrapper->netagent->netagent_type, NETAGENT_TYPESIZE);
2340 	} else {
2341 		NETAGENTLOG0(LOG_ERR, "Type requested for invalid netagent");
2342 	}
2343 	lck_rw_done(&netagent_lock);
2344 
2345 	return found;
2346 }
2347 
2348 int
netagent_kernel_trigger(uuid_t uuid)2349 netagent_kernel_trigger(uuid_t uuid)
2350 {
2351 	int error = 0;
2352 
2353 	lck_rw_lock_shared(&netagent_lock);
2354 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
2355 	if (wrapper == NULL) {
2356 		NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
2357 		error = ENOENT;
2358 		goto done;
2359 	}
2360 
2361 	if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
2362 		NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
2363 		// Agent does not accept kernel triggers
2364 		error = EINVAL;
2365 		goto done;
2366 	}
2367 
2368 	if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2369 		// Agent already active
2370 		NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
2371 		error = 0;
2372 		goto done;
2373 	}
2374 
2375 	error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
2376 	NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
2377 done:
2378 	lck_rw_done(&netagent_lock);
2379 	return error;
2380 }
2381 
2382 int
netagent_client_message_with_params(uuid_t agent_uuid,uuid_t necp_client_uuid,pid_t pid,void * handle,u_int8_t message_type,struct necp_client_agent_parameters * parameters,void ** assigned_results,size_t * assigned_results_length)2383 netagent_client_message_with_params(uuid_t agent_uuid,
2384     uuid_t necp_client_uuid,
2385     pid_t pid,
2386     void *handle,
2387     u_int8_t message_type,
2388     struct necp_client_agent_parameters *parameters,
2389     void **assigned_results,
2390     size_t *assigned_results_length)
2391 {
2392 	int error = 0;
2393 
2394 	if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
2395 	    message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
2396 	    message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
2397 	    message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ERROR &&
2398 	    message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
2399 	    message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS &&
2400 	    message_type != NETAGENT_MESSAGE_TYPE_ABORT_NEXUS &&
2401 	    message_type != NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS &&
2402 	    message_type != NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2403 		NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
2404 		return EINVAL;
2405 	}
2406 
2407 	lck_rw_lock_shared(&netagent_lock);
2408 	bool should_unlock = TRUE;
2409 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2410 	if (wrapper == NULL) {
2411 		NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2412 		error = ENOENT;
2413 		goto done;
2414 	}
2415 
2416 	if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2417 		if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2418 			// Agent does not accept user triggers
2419 			// Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
2420 			error = ENOTSUP;
2421 
2422 
2423 			pid_t report_pid = 0;
2424 			uuid_t report_proc_uuid = {};
2425 			if (parameters != NULL) {
2426 				report_pid = parameters->u.nexus_request.epid;
2427 				uuid_copy(report_proc_uuid, parameters->u.nexus_request.euuid);
2428 			} else {
2429 				struct proc *p = current_proc();
2430 				if (p != NULL) {
2431 					report_pid = proc_pid(p);
2432 					proc_getexecutableuuid(p, report_proc_uuid, sizeof(report_proc_uuid));
2433 				}
2434 			}
2435 			netagent_send_cellular_failed_event(wrapper, report_pid, report_proc_uuid);
2436 			goto done;
2437 		}
2438 	} else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
2439 	    message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS ||
2440 	    message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2441 		bool is_nexus_agent = ((wrapper->netagent->netagent_flags &
2442 		    (NETAGENT_FLAG_NEXUS_PROVIDER |
2443 		    NETAGENT_FLAG_NEXUS_LISTENER |
2444 		    NETAGENT_FLAG_CUSTOM_IP_NEXUS |
2445 		    NETAGENT_FLAG_CUSTOM_ETHER_NEXUS |
2446 		    NETAGENT_FLAG_INTERPOSE_NEXUS)) != 0);
2447 		if (!is_nexus_agent) {
2448 			NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
2449 			// Agent is not a nexus provider
2450 			error = EINVAL;
2451 			goto done;
2452 		}
2453 
2454 		if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
2455 			// Agent not active
2456 			NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
2457 			error = EINVAL;
2458 			goto done;
2459 		}
2460 	} else if (message_type == NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS ||
2461 	    message_type == NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2462 		bool is_group_agent = ((wrapper->netagent->netagent_flags & (NETAGENT_FLAG_SUPPORTS_GROUPS)) != 0);
2463 		if (!is_group_agent) {
2464 			NETAGENTLOG0(LOG_ERR, "Requested netagent for group operation is not a group provider");
2465 			error = EINVAL;
2466 			goto done;
2467 		}
2468 
2469 		if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
2470 			// Agent not active
2471 			NETAGENTLOG0(LOG_INFO, "Requested netagent for group operation is not active");
2472 			error = EINVAL;
2473 			goto done;
2474 		}
2475 	}
2476 
2477 	if (wrapper->control_unit == 0) {
2478 		if (wrapper->event_handler == NULL) {
2479 			// No event handler registered for kernel agent
2480 			error = EINVAL;
2481 		} else {
2482 			// We hold the shared lock during the event handler callout, so it is expected
2483 			// that the event handler will not lead to any registrations or unregistrations
2484 			// of network agents.
2485 			error = wrapper->event_handler(message_type, necp_client_uuid, pid, handle,
2486 			    wrapper->event_context, parameters,
2487 			    assigned_results, assigned_results_length);
2488 			if (error != 0) {
2489 				VERIFY(assigned_results == NULL || *assigned_results == NULL);
2490 				VERIFY(assigned_results_length == NULL || *assigned_results_length == 0);
2491 			}
2492 		}
2493 	} else {
2494 		// ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2495 		if (message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2496 			message_type = NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS;
2497 		}
2498 
2499 		if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_ERROR) {
2500 			const int32_t client_error = parameters->u.error;
2501 			if (wrapper->last_client_error != client_error || // Always notify for an error change
2502 			    (client_error == 0 && wrapper->client_error_count == 0) || // Only notify once for no-error
2503 			    (client_error != 0 && wrapper->client_error_count < NETAGENT_MAX_CLIENT_ERROR_COUNT)) {
2504 				if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
2505 					if (wrapper->last_client_error != client_error) {
2506 						wrapper->last_client_error = client_error;
2507 						wrapper->client_error_count = 1;
2508 					} else {
2509 						wrapper->client_error_count++;
2510 					}
2511 					error = netagent_send_error_message(wrapper, necp_client_uuid, message_type, client_error);
2512 				} else {
2513 					// If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2514 					should_unlock = FALSE;
2515 				}
2516 			}
2517 		} else if (message_type == NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS ||
2518 		    message_type == NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2519 			error = netagent_send_group_message(wrapper, necp_client_uuid, message_type, &parameters->u.group_members);
2520 		} else {
2521 			error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
2522 		}
2523 		if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2524 			if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
2525 				// Grab the lock exclusively to add a pending client to the list
2526 				struct netagent_client *new_pending_client = NULL;
2527 				new_pending_client = kalloc_type(struct netagent_client, Z_WAITOK);
2528 				if (new_pending_client == NULL) {
2529 					NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
2530 				} else {
2531 					uuid_copy(new_pending_client->client_id, necp_client_uuid);
2532 					if (parameters != NULL) {
2533 						new_pending_client->client_pid = parameters->u.nexus_request.epid;
2534 						uuid_copy(new_pending_client->client_proc_uuid, parameters->u.nexus_request.euuid);
2535 					} else {
2536 						struct proc *p = current_proc();
2537 						if (p != NULL) {
2538 							new_pending_client->client_pid = proc_pid(p);
2539 							proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
2540 						}
2541 					}
2542 					LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
2543 				}
2544 			} else {
2545 				// If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2546 				should_unlock = FALSE;
2547 			}
2548 		}
2549 	}
2550 	NETAGENTLOG(((error && error != ENOENT) ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
2551 	if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2552 		uuid_string_t uuid_str;
2553 		uuid_unparse(agent_uuid, uuid_str);
2554 		NETAGENTLOG(LOG_NOTICE, "Triggered network agent %s, error = %d", uuid_str, error);
2555 	}
2556 done:
2557 	if (should_unlock) {
2558 		lck_rw_done(&netagent_lock);
2559 	}
2560 	return error;
2561 }
2562 
2563 int
netagent_client_message(uuid_t agent_uuid,uuid_t necp_client_uuid,pid_t pid,void * handle,u_int8_t message_type)2564 netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, pid_t pid, void *handle, u_int8_t message_type)
2565 {
2566 	return netagent_client_message_with_params(agent_uuid, necp_client_uuid, pid, handle, message_type, NULL, NULL, NULL);
2567 }
2568 
2569 int
netagent_use(uuid_t agent_uuid,uint64_t * out_use_count)2570 netagent_use(uuid_t agent_uuid, uint64_t *out_use_count)
2571 {
2572 	int error = 0;
2573 
2574 	lck_rw_lock_exclusive(&netagent_lock);
2575 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2576 	if (wrapper == NULL) {
2577 		NETAGENTLOG0(LOG_ERR, "netagent_assert: Requested netagent UUID is not registered");
2578 		error = ENOENT;
2579 		goto done;
2580 	}
2581 
2582 	uint64_t current_count = wrapper->use_count;
2583 	wrapper->use_count++;
2584 
2585 	if (out_use_count != NULL) {
2586 		*out_use_count = current_count;
2587 	}
2588 
2589 done:
2590 	lck_rw_done(&netagent_lock);
2591 	return error;
2592 }
2593 
2594 int
netagent_copyout(uuid_t agent_uuid,user_addr_t user_addr,u_int32_t user_size)2595 netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
2596 {
2597 	int error = 0;
2598 
2599 	lck_rw_lock_shared(&netagent_lock);
2600 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2601 	if (wrapper == NULL) {
2602 		NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2603 		error = ENOENT;
2604 		goto done;
2605 	}
2606 
2607 	u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent->netagent_data_size);
2608 	if (user_size < total_size) {
2609 		NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
2610 		error = EINVAL;
2611 		goto done;
2612 	}
2613 
2614 	error = copyout(wrapper->netagent, user_addr, total_size);
2615 
2616 	NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
2617 done:
2618 	lck_rw_done(&netagent_lock);
2619 	return error;
2620 }
2621 
2622 int
netagent_acquire_token(uuid_t agent_uuid,user_addr_t user_addr,u_int32_t user_size,int * retval)2623 netagent_acquire_token(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size, int *retval)
2624 {
2625 	int error = 0;
2626 
2627 	lck_rw_lock_exclusive(&netagent_lock);
2628 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2629 	if (wrapper == NULL) {
2630 		NETAGENTLOG0(LOG_DEBUG, "Network agent for request UUID could not be found");
2631 		error = ENOENT;
2632 		goto done;
2633 	}
2634 
2635 	struct netagent_token *token = TAILQ_FIRST(&wrapper->token_list);
2636 	if (token == NULL) {
2637 		NETAGENTLOG0(LOG_DEBUG, "Network agent does not have any tokens");
2638 		if (wrapper->token_low_water != 0) {
2639 			(void)netagent_send_tokens_needed(wrapper);
2640 		}
2641 		error = ENODATA;
2642 		goto done;
2643 	}
2644 
2645 	if (user_size < token->token_length) {
2646 		NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, token->token_length);
2647 		error = EMSGSIZE;
2648 		goto done;
2649 	}
2650 
2651 	error = copyout(token->token_bytes, user_addr, token->token_length);
2652 	if (error == 0) {
2653 		*retval = (int)token->token_length;
2654 	}
2655 
2656 	NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied token content (error %d)", error);
2657 
2658 	TAILQ_REMOVE(&wrapper->token_list, token, token_chain);
2659 	netagent_token_free(token);
2660 	if (wrapper->token_count > 0) {
2661 		wrapper->token_count--;
2662 	}
2663 	if (wrapper->token_count < wrapper->token_low_water) {
2664 		(void)netagent_send_tokens_needed(wrapper);
2665 	}
2666 done:
2667 	lck_rw_done(&netagent_lock);
2668 	return error;
2669 }
2670 
2671 int
netagent_trigger(struct proc * p,struct netagent_trigger_args * uap,int32_t * retval)2672 netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
2673 {
2674 #pragma unused(p, retval)
2675 	uuid_t agent_uuid = {};
2676 	int error = 0;
2677 
2678 	if (uap == NULL) {
2679 		NETAGENTLOG0(LOG_ERR, "uap == NULL");
2680 		return EINVAL;
2681 	}
2682 
2683 	if (uap->agent_uuid) {
2684 		if (uap->agent_uuidlen != sizeof(uuid_t)) {
2685 			NETAGENTLOG(LOG_ERR, "Incorrect length (got %zu, expected %lu)",
2686 			    (size_t)uap->agent_uuidlen, sizeof(uuid_t));
2687 			return ERANGE;
2688 		}
2689 
2690 		error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
2691 		if (error) {
2692 			NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
2693 			return error;
2694 		}
2695 	}
2696 
2697 	if (uuid_is_null(agent_uuid)) {
2698 		NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
2699 		return EINVAL;
2700 	}
2701 
2702 	lck_rw_lock_shared(&netagent_lock);
2703 	struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2704 	if (wrapper == NULL) {
2705 		NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
2706 		error = ENOENT;
2707 		goto done;
2708 	}
2709 
2710 	if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2711 		// Agent does not accept triggers
2712 		NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
2713 		error = ENOTSUP;
2714 		goto done;
2715 	}
2716 
2717 	if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2718 		// Agent already active
2719 		NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
2720 		error = 0;
2721 		goto done;
2722 	}
2723 
2724 	error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
2725 	NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
2726 done:
2727 	lck_rw_done(&netagent_lock);
2728 	return error;
2729 }
2730