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