]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/network_agent.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / bsd / net / network_agent.c
1 /*
2 * Copyright (c) 2014-2018 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 <libkern/OSMalloc.h>
36 #include <sys/kernel.h>
37 #include <sys/kern_control.h>
38 #include <sys/mbuf.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/sysctl.h>
41 #include <sys/priv.h>
42 #include <sys/kern_event.h>
43 #include <sys/sysproto.h>
44 #include <net/network_agent.h>
45 #include <net/if_var.h>
46 #include <net/necp.h>
47 #include <os/log.h>
48
49 u_int32_t netagent_debug = LOG_NOTICE; // 0=None, 1=Basic
50
51 SYSCTL_NODE(_net, OID_AUTO, netagent, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "NetworkAgent");
52 SYSCTL_INT(_net_netagent, OID_AUTO, debug, CTLFLAG_LOCKED | CTLFLAG_RW, &netagent_debug, 0, "");
53
54 static int netagent_registered_count = 0;
55 SYSCTL_INT(_net_netagent, OID_AUTO, registered_count, CTLFLAG_RD | CTLFLAG_LOCKED,
56 &netagent_registered_count, 0, "");
57
58 static int netagent_active_count = 0;
59 SYSCTL_INT(_net_netagent, OID_AUTO, active_count, CTLFLAG_RD | CTLFLAG_LOCKED,
60 &netagent_active_count, 0, "");
61
62 #define NETAGENTLOG(level, format, ...) do { \
63 if (level <= netagent_debug) { \
64 if (level == LOG_ERR) { \
65 os_log_error(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
66 } else { \
67 os_log(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
68 } \
69 } \
70 } while (0)
71
72 #define NETAGENTLOG0(level, msg) do { \
73 if (level <= netagent_debug) { \
74 if (level == LOG_ERR) { \
75 os_log_error(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
76 } else { \
77 os_log(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
78 } \
79 } \
80 } while (0)
81
82 struct netagent_client {
83 LIST_ENTRY(netagent_client) client_chain;
84 uuid_t client_id;
85 uuid_t client_proc_uuid;
86 pid_t client_pid;
87 };
88
89 LIST_HEAD(netagent_client_list_s, netagent_client);
90
91 struct netagent_wrapper {
92 LIST_ENTRY(netagent_wrapper) master_chain;
93 u_int32_t control_unit;
94 netagent_event_f event_handler;
95 void *event_context;
96 u_int32_t generation;
97 u_int64_t use_count;
98 struct netagent_client_list_s pending_triggers_list;
99 struct netagent netagent;
100 };
101
102 struct netagent_session {
103 u_int32_t control_unit; // A control unit of 0 indicates an agent owned by the kernel
104 struct netagent_wrapper *wrapper;
105 netagent_event_f event_handler;
106 void *event_context;
107 };
108
109 typedef enum {
110 kNetagentErrorDomainPOSIX = 0,
111 kNetagentErrorDomainUserDefined = 1,
112 } netagent_error_domain_t;
113
114 static LIST_HEAD(_netagent_list, netagent_wrapper) master_netagent_list;
115
116 // Protected by netagent_lock
117 static u_int32_t g_next_generation = 1;
118
119 static kern_ctl_ref netagent_kctlref;
120 static u_int32_t netagent_family;
121 static OSMallocTag netagent_malloc_tag;
122 static lck_grp_attr_t *netagent_grp_attr = NULL;
123 static lck_attr_t *netagent_mtx_attr = NULL;
124 static lck_grp_t *netagent_mtx_grp = NULL;
125 decl_lck_rw_data(static, netagent_lock);
126
127 static errno_t netagent_register_control(void);
128 static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
129 void **unitinfo);
130 static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
131 static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
132 mbuf_t m, int flags);
133 static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
134 static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
135 int opt, void *data, size_t *len);
136 static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
137 int opt, void *data, size_t len);
138
139 static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
140
141 static struct netagent_session *netagent_create_session(u_int32_t control_unit);
142 static void netagent_delete_session(struct netagent_session *session);
143
144 // Register
145 static void netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
146 u_int32_t payload_length, mbuf_t packet, int offset);
147 static errno_t netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
148 u_int32_t payload_length);
149
150 // Unregister
151 static void netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
152 u_int32_t payload_length, mbuf_t packet, int offset);
153 static errno_t netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
154 u_int32_t payload_length);
155
156 // Update
157 static void netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
158 u_int32_t payload_length, mbuf_t packet, int offset);
159 static errno_t netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload,
160 u_int32_t payload_length);
161
162 // Assign nexus
163 static void netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
164 u_int32_t payload_length, mbuf_t packet, int offset);
165 static errno_t netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
166 u_int32_t payload_length);
167
168 // Set/get assert count
169 static errno_t netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
170 static errno_t netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
171
172 static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
173 u_int32_t payload_length, mbuf_t packet, int offset);
174
175 static struct netagent_wrapper *netagent_find_agent_with_uuid(uuid_t uuid);
176
177 errno_t
178 netagent_init(void)
179 {
180 errno_t result = 0;
181
182 result = netagent_register_control();
183 if (result != 0) {
184 goto done;
185 }
186
187 netagent_grp_attr = lck_grp_attr_alloc_init();
188 if (netagent_grp_attr == NULL) {
189 NETAGENTLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed");
190 result = ENOMEM;
191 goto done;
192 }
193
194 netagent_mtx_grp = lck_grp_alloc_init(NETAGENT_CONTROL_NAME, netagent_grp_attr);
195 if (netagent_mtx_grp == NULL) {
196 NETAGENTLOG0(LOG_ERR, "lck_grp_alloc_init failed");
197 result = ENOMEM;
198 goto done;
199 }
200
201 netagent_mtx_attr = lck_attr_alloc_init();
202 if (netagent_mtx_attr == NULL) {
203 NETAGENTLOG0(LOG_ERR, "lck_attr_alloc_init failed");
204 result = ENOMEM;
205 goto done;
206 }
207
208 lck_rw_init(&netagent_lock, netagent_mtx_grp, netagent_mtx_attr);
209
210 LIST_INIT(&master_netagent_list);
211
212 done:
213 if (result != 0) {
214 if (netagent_mtx_attr != NULL) {
215 lck_attr_free(netagent_mtx_attr);
216 netagent_mtx_attr = NULL;
217 }
218 if (netagent_mtx_grp != NULL) {
219 lck_grp_free(netagent_mtx_grp);
220 netagent_mtx_grp = NULL;
221 }
222 if (netagent_grp_attr != NULL) {
223 lck_grp_attr_free(netagent_grp_attr);
224 netagent_grp_attr = NULL;
225 }
226 if (netagent_kctlref != NULL) {
227 ctl_deregister(netagent_kctlref);
228 netagent_kctlref = NULL;
229 }
230 }
231 return result;
232 }
233
234 static errno_t
235 netagent_register_control(void)
236 {
237 struct kern_ctl_reg kern_ctl;
238 errno_t result = 0;
239
240 // Create a tag to allocate memory
241 netagent_malloc_tag = OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME, OSMT_DEFAULT);
242
243 // Find a unique value for our interface family
244 result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
245 if (result != 0) {
246 NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
247 return result;
248 }
249
250 bzero(&kern_ctl, sizeof(kern_ctl));
251 strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
252 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
253 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
254 kern_ctl.ctl_sendsize = 64 * 1024;
255 kern_ctl.ctl_recvsize = 64 * 1024;
256 kern_ctl.ctl_connect = netagent_ctl_connect;
257 kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
258 kern_ctl.ctl_send = netagent_ctl_send;
259 kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
260 kern_ctl.ctl_setopt = netagent_ctl_setopt;
261 kern_ctl.ctl_getopt = netagent_ctl_getopt;
262
263 result = ctl_register(&kern_ctl, &netagent_kctlref);
264 if (result != 0) {
265 NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
266 return result;
267 }
268
269 return 0;
270 }
271
272 static errno_t
273 netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
274 {
275 #pragma unused(kctlref)
276 *unitinfo = netagent_create_session(sac->sc_unit);
277 if (*unitinfo == NULL) {
278 // Could not allocate session
279 return ENOBUFS;
280 }
281
282 return 0;
283 }
284
285 static errno_t
286 netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
287 {
288 #pragma unused(kctlref, unit)
289 struct netagent_session *session = (struct netagent_session *)unitinfo;
290 if (session != NULL) {
291 netagent_delete_session(session);
292 }
293
294 return 0;
295 }
296
297 // Kernel events
298 static void
299 netagent_post_event(uuid_t agent_uuid, u_int32_t event_code, bool update_necp, bool should_update_immediately)
300 {
301 if (update_necp) {
302 necp_update_all_clients_immediately_if_needed(should_update_immediately);
303 }
304
305 struct kev_msg ev_msg;
306 memset(&ev_msg, 0, sizeof(ev_msg));
307
308 struct kev_netagent_data event_data;
309
310 ev_msg.vendor_code = KEV_VENDOR_APPLE;
311 ev_msg.kev_class = KEV_NETWORK_CLASS;
312 ev_msg.kev_subclass = KEV_NETAGENT_SUBCLASS;
313 ev_msg.event_code = event_code;
314
315 uuid_copy(event_data.netagent_uuid, agent_uuid);
316 ev_msg.dv[0].data_ptr = &event_data;
317 ev_msg.dv[0].data_length = sizeof(event_data);
318
319 kev_post_msg(&ev_msg);
320 }
321
322 // Message handling
323 static u_int8_t *
324 netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
325 u_int32_t message_id, u_int32_t error, u_int32_t payload_length)
326 {
327 ((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
328 ((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
329 ((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
330 ((struct netagent_message_header *)(void *)buffer)->message_error = error;
331 ((struct netagent_message_header *)(void *)buffer)->message_payload_length = payload_length;
332 return buffer + sizeof(struct netagent_message_header);
333 }
334
335 static int
336 netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
337 {
338 if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
339 return EINVAL;
340 }
341
342 return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
343 }
344
345 static int
346 netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int32_t trigger_type)
347 {
348 int error = 0;
349 struct netagent_trigger_message *trigger_message = NULL;
350 u_int8_t *trigger = NULL;
351 size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
352
353 MALLOC(trigger, u_int8_t *, trigger_size, M_NETAGENT, M_WAITOK);
354 if (trigger == NULL) {
355 return ENOMEM;
356 }
357
358 (void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
359
360 trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
361 trigger_message->trigger_flags = flags;
362 if (p != NULL) {
363 trigger_message->trigger_pid = proc_pid(p);
364 proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
365 } else {
366 trigger_message->trigger_pid = 0;
367 uuid_clear(trigger_message->trigger_proc_uuid);
368 }
369
370 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)trigger, trigger_size))) {
371 NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
372 }
373
374 FREE(trigger, M_NETAGENT);
375 return error;
376 }
377
378 static int
379 netagent_send_client_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type)
380 {
381 int error = 0;
382 struct netagent_client_message *client_message = NULL;
383 u_int8_t *message = NULL;
384 size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_message);
385
386 MALLOC(message, u_int8_t *, message_size, M_NETAGENT, M_WAITOK);
387 if (message == NULL) {
388 return ENOMEM;
389 }
390
391 (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_message));
392
393 client_message = (struct netagent_client_message *)(void *)(message + sizeof(struct netagent_message_header));
394 uuid_copy(client_message->client_id, client_id);
395
396 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)message, message_size))) {
397 NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
398 }
399
400 FREE(message, M_NETAGENT);
401 return error;
402 }
403
404 static int
405 netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
406 {
407 int error = 0;
408 u_int8_t *response = NULL;
409 size_t response_size = sizeof(struct netagent_message_header);
410 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
411 if (response == NULL) {
412 return ENOMEM;
413 }
414 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
415
416 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
417 NETAGENTLOG0(LOG_ERR, "Failed to send response");
418 }
419
420 FREE(response, M_NETAGENT);
421 return error;
422 }
423
424 static int
425 netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
426 u_int32_t message_id, u_int32_t error_code)
427 {
428 int error = 0;
429 u_int8_t *response = NULL;
430 size_t response_size = sizeof(struct netagent_message_header);
431
432 if (session == NULL) {
433 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
434 return EINVAL;
435 }
436
437 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
438 if (response == NULL) {
439 return ENOMEM;
440 }
441 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
442 message_id, error_code, 0);
443
444 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
445 NETAGENTLOG0(LOG_ERR, "Failed to send response");
446 }
447
448 FREE(response, M_NETAGENT);
449 return error;
450 }
451
452 static errno_t
453 netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
454 {
455 #pragma unused(kctlref, unit, flags)
456 struct netagent_session *session = (struct netagent_session *)unitinfo;
457 struct netagent_message_header header;
458 int error = 0;
459
460 if (session == NULL) {
461 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
462 error = EINVAL;
463 goto done;
464 }
465
466 if (mbuf_pkthdr_len(packet) < sizeof(header)) {
467 NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
468 mbuf_pkthdr_len(packet), sizeof(header));
469 error = EINVAL;
470 goto done;
471 }
472
473 error = mbuf_copydata(packet, 0, sizeof(header), &header);
474 if (error) {
475 NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
476 error = ENOBUFS;
477 goto done;
478 }
479
480 switch (header.message_type) {
481 case NETAGENT_MESSAGE_TYPE_REGISTER: {
482 netagent_handle_register_message(session, header.message_id, header.message_payload_length,
483 packet, sizeof(header));
484 break;
485 }
486 case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
487 netagent_handle_unregister_message(session, header.message_id, header.message_payload_length,
488 packet, sizeof(header));
489 break;
490 }
491 case NETAGENT_MESSAGE_TYPE_UPDATE: {
492 netagent_handle_update_message(session, header.message_id, header.message_payload_length,
493 packet, sizeof(header));
494 break;
495 }
496 case NETAGENT_MESSAGE_TYPE_GET: {
497 netagent_handle_get(session, header.message_id, header.message_payload_length,
498 packet, sizeof(header));
499 break;
500 }
501 case NETAGENT_MESSAGE_TYPE_ASSERT: {
502 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
503 break;
504 }
505 case NETAGENT_MESSAGE_TYPE_UNASSERT: {
506 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
507 break;
508 }
509 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS: {
510 netagent_handle_assign_nexus_message(session, header.message_id, header.message_payload_length,
511 packet, sizeof(header));
512 break;
513 }
514 default: {
515 NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
516 netagent_send_error_response(session, header.message_type, header.message_id,
517 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
518 break;
519 }
520 }
521
522 done:
523 mbuf_freem(packet);
524 return error;
525 }
526
527 static void
528 netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
529 {
530 #pragma unused(kctlref, unit, unitinfo, flags)
531 return;
532 }
533
534 static errno_t
535 netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
536 void *data, size_t *len)
537 {
538 #pragma unused(kctlref, unit)
539 struct netagent_session *session = (struct netagent_session *)unitinfo;
540 errno_t error;
541
542 if (session == NULL) {
543 NETAGENTLOG0(LOG_ERR, "Received a NULL session");
544 error = EINVAL;
545 goto done;
546 }
547
548 switch (opt) {
549 case NETAGENT_OPTION_TYPE_USE_COUNT: {
550 NETAGENTLOG0(LOG_DEBUG, "Request to get use count");
551 error = netagent_handle_use_count_getopt(session, data, len);
552 }
553 break;
554 default:
555 NETAGENTLOG0(LOG_ERR, "Received unknown option");
556 error = ENOPROTOOPT;
557 break;
558 }
559
560 done:
561 return error;
562 }
563
564 static errno_t
565 netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
566 void *data, size_t len)
567 {
568 #pragma unused(kctlref, unit)
569 struct netagent_session *session = (struct netagent_session *)unitinfo;
570 errno_t error;
571
572 if (session == NULL) {
573 NETAGENTLOG0(LOG_ERR, "Received a NULL session");
574 error = EINVAL;
575 goto done;
576 }
577
578 switch (opt) {
579 case NETAGENT_OPTION_TYPE_REGISTER: {
580 NETAGENTLOG0(LOG_DEBUG, "Request for registration");
581 error = netagent_handle_register_setopt(session, data, len);
582 }
583 break;
584 case NETAGENT_OPTION_TYPE_UPDATE: {
585 NETAGENTLOG0(LOG_DEBUG, "Request for update");
586 error = netagent_handle_update_setopt(session, data, len);
587 }
588 break;
589 case NETAGENT_OPTION_TYPE_UNREGISTER: {
590 NETAGENTLOG0(LOG_DEBUG, "Request for unregistration");
591 error = netagent_handle_unregister_setopt(session, data, len);
592 }
593 break;
594 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS: {
595 NETAGENTLOG0(LOG_DEBUG, "Request for assigning nexus");
596 error = netagent_handle_assign_nexus_setopt(session, data, len);
597 }
598 break;
599 case NETAGENT_OPTION_TYPE_USE_COUNT: {
600 NETAGENTLOG0(LOG_DEBUG, "Request to set use count");
601 error = netagent_handle_use_count_setopt(session, data, len);
602 }
603 break;
604 default:
605 NETAGENTLOG0(LOG_ERR, "Received unknown option");
606 error = ENOPROTOOPT;
607 break;
608 }
609
610 done:
611 return error;
612 }
613
614 // Session Management
615 static struct netagent_session *
616 netagent_create_session(u_int32_t control_unit)
617 {
618 struct netagent_session *new_session = NULL;
619
620 MALLOC(new_session, struct netagent_session *, sizeof(*new_session), M_NETAGENT, M_WAITOK);
621 if (new_session == NULL) {
622 goto done;
623 }
624 NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
625 memset(new_session, 0, sizeof(*new_session));
626 new_session->control_unit = control_unit;
627 new_session->wrapper = NULL;
628 done:
629 return new_session;
630 }
631
632 netagent_session_t
633 netagent_create(netagent_event_f event_handler, void *context)
634 {
635 struct netagent_session *session = netagent_create_session(0);
636 if (session == NULL) {
637 return NULL;
638 }
639
640 session->event_handler = event_handler;
641 session->event_context = context;
642 return session;
643 }
644
645 static void
646 netagent_free_wrapper(struct netagent_wrapper *wrapper)
647 {
648 // Free any pending client triggers
649 struct netagent_client *search_client = NULL;
650 struct netagent_client *temp_client = NULL;
651 LIST_FOREACH_SAFE(search_client, &wrapper->pending_triggers_list, client_chain, temp_client) {
652 LIST_REMOVE(search_client, client_chain);
653 FREE(search_client, M_NETAGENT);
654 }
655
656 // Free wrapper itself
657 FREE(wrapper, M_NETAGENT);
658 }
659
660 static void
661 netagent_unregister_session_wrapper(struct netagent_session *session)
662 {
663 bool unregistered = FALSE;
664 uuid_t unregistered_uuid;
665 struct netagent_wrapper *wrapper = NULL;
666 lck_rw_lock_exclusive(&netagent_lock);
667 if (session != NULL) {
668 wrapper = session->wrapper;
669 if (wrapper != NULL) {
670 if (netagent_registered_count > 0) {
671 netagent_registered_count--;
672 }
673 if ((session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
674 netagent_active_count > 0) {
675 netagent_active_count--;
676 }
677
678 LIST_REMOVE(wrapper, master_chain);
679
680 unregistered = TRUE;
681 uuid_copy(unregistered_uuid, session->wrapper->netagent.netagent_uuid);
682
683 netagent_free_wrapper(session->wrapper);
684 session->wrapper = NULL;
685 NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
686 }
687 }
688 lck_rw_done(&netagent_lock);
689
690 if (unregistered) {
691 ifnet_clear_netagent(unregistered_uuid);
692 netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED, TRUE, false);
693 }
694 }
695
696 static void
697 netagent_delete_session(struct netagent_session *session)
698 {
699 if (session != NULL) {
700 netagent_unregister_session_wrapper(session);
701 FREE(session, M_NETAGENT);
702 }
703 }
704
705 void
706 netagent_destroy(netagent_session_t session)
707 {
708 return netagent_delete_session((struct netagent_session *)session);
709 }
710
711 static int
712 netagent_packet_get_netagent_data_size(mbuf_t packet, int offset, int *err)
713 {
714 int error = 0;
715
716 struct netagent netagent_peek;
717 memset(&netagent_peek, 0, sizeof(netagent_peek));
718
719 *err = 0;
720
721 error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
722 if (error) {
723 *err = ENOENT;
724 return -1;
725 }
726
727 return netagent_peek.netagent_data_size;
728 }
729
730 static errno_t
731 netagent_handle_register_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper)
732 {
733 lck_rw_lock_exclusive(&netagent_lock);
734
735 new_wrapper->control_unit = session->control_unit;
736 new_wrapper->event_handler = session->event_handler;
737 new_wrapper->event_context = session->event_context;
738 new_wrapper->generation = g_next_generation++;
739
740 session->wrapper = new_wrapper;
741 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
742 LIST_INIT(&new_wrapper->pending_triggers_list);
743
744 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
745 netagent_registered_count++;
746 if (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) {
747 netagent_active_count++;
748 }
749
750 lck_rw_done(&netagent_lock);
751
752 return 0;
753 }
754
755 errno_t
756 netagent_register(netagent_session_t _session, struct netagent *agent)
757 {
758 int data_size = 0;
759 struct netagent_wrapper *new_wrapper = NULL;
760
761 struct netagent_session *session = (struct netagent_session *)_session;
762 if (session == NULL) {
763 NETAGENTLOG0(LOG_ERR, "Cannot register agent on NULL session");
764 return EINVAL;
765 }
766
767 if (agent == NULL) {
768 NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
769 return EINVAL;
770 }
771
772 if (session->wrapper != NULL) {
773 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
774 return EINVAL;
775 }
776
777 data_size = agent->netagent_data_size;
778 if (data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
779 NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %d",
780 data_size);
781 return EINVAL;
782 }
783
784 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
785 if (new_wrapper == NULL) {
786 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
787 return ENOMEM;
788 }
789
790 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
791 __nochk_memcpy(&new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
792
793 int error = netagent_handle_register_inner(session, new_wrapper);
794 if (error != 0) {
795 FREE(new_wrapper, M_NETAGENT);
796 return error;
797 }
798
799 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
800 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
801
802 return 0;
803 }
804
805 static errno_t
806 netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
807 u_int32_t payload_length)
808 {
809 int data_size = 0;
810 struct netagent_wrapper *new_wrapper = NULL;
811 u_int32_t response_error = 0;
812 struct netagent *register_netagent = (struct netagent *)(void *)payload;
813
814 if (session == NULL) {
815 NETAGENTLOG0(LOG_ERR, "Failed to find session");
816 response_error = EINVAL;
817 goto done;
818 }
819
820 if (payload == NULL) {
821 NETAGENTLOG0(LOG_ERR, "No payload received");
822 response_error = EINVAL;
823 goto done;
824 }
825
826 if (session->wrapper != NULL) {
827 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
828 response_error = EINVAL;
829 goto done;
830 }
831
832 if (payload_length < sizeof(struct netagent)) {
833 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%u < %lu)",
834 payload_length, sizeof(struct netagent));
835 response_error = EINVAL;
836 goto done;
837 }
838
839 data_size = register_netagent->netagent_data_size;
840 if (data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
841 NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %d", data_size);
842 response_error = EINVAL;
843 goto done;
844 }
845
846 if (payload_length != (sizeof(struct netagent) + data_size)) {
847 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent) + data_size), payload_length);
848 response_error = EINVAL;
849 goto done;
850 }
851
852 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
853 if (new_wrapper == NULL) {
854 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
855 response_error = ENOMEM;
856 goto done;
857 }
858
859 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
860 __nochk_memcpy(&new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
861
862 response_error = netagent_handle_register_inner(session, new_wrapper);
863 if (response_error != 0) {
864 FREE(new_wrapper, M_NETAGENT);
865 goto done;
866 }
867
868 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
869 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
870
871 done:
872 return response_error;
873 }
874
875 static void
876 netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
877 u_int32_t payload_length, mbuf_t packet, int offset)
878 {
879 int error;
880 int data_size = 0;
881 struct netagent_wrapper *new_wrapper = NULL;
882 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
883 uuid_t netagent_uuid;
884 uuid_clear(netagent_uuid);
885
886 if (session == NULL) {
887 NETAGENTLOG0(LOG_ERR, "Failed to find session");
888 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
889 goto fail;
890 }
891
892 if (session->wrapper != NULL) {
893 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
894 response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
895 goto fail;
896 }
897
898 if (payload_length < sizeof(struct netagent)) {
899 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%u < %lu)",
900 payload_length, sizeof(struct netagent));
901 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
902 goto fail;
903 }
904
905 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
906 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
907 NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %d",
908 error, data_size);
909 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
910 goto fail;
911 }
912
913 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
914 if (new_wrapper == NULL) {
915 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
916 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
917 goto fail;
918 }
919
920 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
921
922 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
923 &new_wrapper->netagent);
924 if (error) {
925 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
926 FREE(new_wrapper, M_NETAGENT);
927 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
928 goto fail;
929 }
930
931 (void)netagent_handle_register_inner(session, new_wrapper);
932
933 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
934 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
935 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
936 return;
937 fail:
938 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
939 }
940
941 errno_t
942 netagent_unregister(netagent_session_t _session)
943 {
944 struct netagent_session *session = (struct netagent_session *)_session;
945 if (session == NULL) {
946 NETAGENTLOG0(LOG_ERR, "Cannot unregister NULL session");
947 return EINVAL;
948 }
949
950 netagent_unregister_session_wrapper(session);
951 return 0;
952 }
953
954 static errno_t
955 netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
956 u_int32_t payload_length)
957 {
958 #pragma unused(payload, payload_length)
959 u_int32_t response_error = 0;
960
961 if (session == NULL) {
962 NETAGENTLOG0(LOG_ERR, "Failed to find session");
963 response_error = EINVAL;
964 goto done;
965 }
966
967 netagent_unregister_session_wrapper(session);
968
969 done:
970 return response_error;
971 }
972
973 static void
974 netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
975 u_int32_t payload_length, mbuf_t packet, int offset)
976 {
977 #pragma unused(payload_length, packet, offset)
978 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
979
980 if (session == NULL) {
981 NETAGENTLOG0(LOG_ERR, "Failed to find session");
982 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
983 goto fail;
984 }
985
986 netagent_unregister_session_wrapper(session);
987
988 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
989 return;
990 fail:
991 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
992 }
993
994 static void
995 netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
996 pid_t pid, uuid_t proc_uuid)
997 {
998 if (strncmp(wrapper->netagent.netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
999 return;
1000 }
1001
1002 struct kev_netpolicy_ifdenied ev_ifdenied;
1003
1004 bzero(&ev_ifdenied, sizeof(ev_ifdenied));
1005
1006 ev_ifdenied.ev_data.epid = pid;
1007 uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
1008 ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
1009
1010 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
1011 }
1012
1013 static errno_t
1014 netagent_handle_update_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper, u_int32_t data_size, u_int8_t *agent_changed, netagent_error_domain_t error_domain)
1015 {
1016 u_int32_t response_error = 0;
1017
1018 if (agent_changed == NULL) {
1019 NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
1020 return EINVAL;
1021 }
1022
1023 lck_rw_lock_exclusive(&netagent_lock);
1024
1025 if (uuid_compare(session->wrapper->netagent.netagent_uuid, new_wrapper->netagent.netagent_uuid) != 0 ||
1026 memcmp(&session->wrapper->netagent.netagent_domain, &new_wrapper->netagent.netagent_domain,
1027 sizeof(new_wrapper->netagent.netagent_domain)) != 0 ||
1028 memcmp(&session->wrapper->netagent.netagent_type, &new_wrapper->netagent.netagent_type,
1029 sizeof(new_wrapper->netagent.netagent_type)) != 0) {
1030 lck_rw_done(&netagent_lock);
1031 NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
1032 if (error_domain == kNetagentErrorDomainPOSIX) {
1033 response_error = EINVAL;
1034 } else if (error_domain == kNetagentErrorDomainUserDefined) {
1035 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
1036 }
1037 return response_error;
1038 }
1039
1040 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
1041 if (session->wrapper->netagent.netagent_data_size == new_wrapper->netagent.netagent_data_size &&
1042 memcmp(&session->wrapper->netagent, &new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
1043 // Agent is exactly identical, don't increment the generation count
1044
1045 // Make a copy of the list of pending clients, and clear the current list
1046 struct netagent_client_list_s pending_triggers_list_copy;
1047 LIST_INIT(&pending_triggers_list_copy);
1048 struct netagent_client *search_client = NULL;
1049 struct netagent_client *temp_client = NULL;
1050 LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
1051 LIST_REMOVE(search_client, client_chain);
1052 LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
1053 }
1054 lck_rw_done(&netagent_lock);
1055
1056 // Update pending client triggers without holding a lock
1057 search_client = NULL;
1058 temp_client = NULL;
1059 LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
1060 necp_force_update_client(search_client->client_id, session->wrapper->netagent.netagent_uuid, session->wrapper->generation);
1061 netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
1062 LIST_REMOVE(search_client, client_chain);
1063 FREE(search_client, M_NETAGENT);
1064 }
1065 NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
1066 *agent_changed = FALSE;
1067 return response_error;
1068 }
1069
1070 new_wrapper->generation = g_next_generation++;
1071 new_wrapper->use_count = session->wrapper->use_count;
1072
1073 if ((new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1074 !(session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1075 netagent_active_count++;
1076 } else if (!(new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1077 (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1078 netagent_active_count > 0) {
1079 netagent_active_count--;
1080 }
1081
1082 LIST_REMOVE(session->wrapper, master_chain);
1083 netagent_free_wrapper(session->wrapper);
1084 session->wrapper = new_wrapper;
1085 new_wrapper->control_unit = session->control_unit;
1086 new_wrapper->event_handler = session->event_handler;
1087 new_wrapper->event_context = session->event_context;
1088 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
1089 LIST_INIT(&new_wrapper->pending_triggers_list);
1090
1091 NETAGENTLOG0(LOG_DEBUG, "Updated agent");
1092 *agent_changed = TRUE;
1093
1094 lck_rw_done(&netagent_lock);
1095
1096 return response_error;
1097 }
1098
1099 errno_t
1100 netagent_update(netagent_session_t _session, struct netagent *agent)
1101 {
1102 u_int8_t agent_changed;
1103 int data_size = 0;
1104 struct netagent_wrapper *new_wrapper = NULL;
1105
1106 struct netagent_session *session = (struct netagent_session *)_session;
1107 if (session == NULL) {
1108 NETAGENTLOG0(LOG_ERR, "Cannot update agent on NULL session");
1109 return EINVAL;
1110 }
1111
1112 if (agent == NULL) {
1113 NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
1114 return EINVAL;
1115 }
1116
1117 if (session->wrapper == NULL) {
1118 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1119 return EINVAL;
1120 }
1121
1122 data_size = agent->netagent_data_size;
1123 if (data_size > NETAGENT_MAX_DATA_SIZE) {
1124 NETAGENTLOG(LOG_ERR, "Update message size (%u > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1125 return EINVAL;
1126 }
1127
1128 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1129 if (new_wrapper == NULL) {
1130 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1131 return ENOMEM;
1132 }
1133
1134 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1135 __nochk_memcpy(&new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
1136
1137 int error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1138 if (error == 0) {
1139 bool should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1140 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1141 if (agent_changed == FALSE) {
1142 // The session wrapper does not need the "new_wrapper" as nothing changed
1143 FREE(new_wrapper, M_NETAGENT);
1144 }
1145 } else {
1146 FREE(new_wrapper, M_NETAGENT);
1147 return error;
1148 }
1149
1150 return 0;
1151 }
1152
1153 static errno_t
1154 netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, u_int32_t payload_length)
1155 {
1156 u_int32_t data_size = 0;
1157 struct netagent_wrapper *new_wrapper = NULL;
1158 errno_t response_error = 0;
1159 struct netagent *update_netagent = (struct netagent *)(void *)payload;
1160 u_int8_t agent_changed;
1161
1162 if (session == NULL) {
1163 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1164 response_error = EINVAL;
1165 goto done;
1166 }
1167
1168 if (payload == NULL) {
1169 NETAGENTLOG0(LOG_ERR, "No payload received");
1170 response_error = EINVAL;
1171 goto done;
1172 }
1173
1174 if (session->wrapper == NULL) {
1175 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1176 response_error = ENOENT;
1177 goto done;
1178 }
1179
1180 if (payload_length < sizeof(struct netagent)) {
1181 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%u < %lu)",
1182 payload_length, sizeof(struct netagent));
1183 response_error = EINVAL;
1184 goto done;
1185 }
1186
1187 data_size = update_netagent->netagent_data_size;
1188 if (data_size > NETAGENT_MAX_DATA_SIZE) {
1189 NETAGENTLOG(LOG_ERR, "Update message size (%u > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1190 response_error = EINVAL;
1191 goto done;
1192 }
1193
1194 if (payload_length != (sizeof(struct netagent) + data_size)) {
1195 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent) + data_size), payload_length);
1196 response_error = EINVAL;
1197 goto done;
1198 }
1199
1200 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1201 if (new_wrapper == NULL) {
1202 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1203 response_error = ENOMEM;
1204 goto done;
1205 }
1206
1207 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1208 __nochk_memcpy(&new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1209
1210 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1211 if (response_error == 0) {
1212 bool should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1213 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1214 if (agent_changed == FALSE) {
1215 // The session wrapper does not need the "new_wrapper" as nothing changed
1216 FREE(new_wrapper, M_NETAGENT);
1217 }
1218 } else {
1219 FREE(new_wrapper, M_NETAGENT);
1220 }
1221
1222 done:
1223 return response_error;
1224 }
1225
1226 static void
1227 netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1228 u_int32_t payload_length, mbuf_t packet, int offset)
1229 {
1230 int error;
1231 int data_size = 0;
1232 struct netagent_wrapper *new_wrapper = NULL;
1233 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1234 u_int8_t agent_changed;
1235
1236 if (session == NULL) {
1237 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1238 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1239 goto fail;
1240 }
1241
1242 if (session->wrapper == NULL) {
1243 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1244 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1245 goto fail;
1246 }
1247
1248 if (payload_length < sizeof(struct netagent)) {
1249 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%u < %lu)",
1250 payload_length, sizeof(struct netagent));
1251 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1252 goto fail;
1253 }
1254
1255 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1256 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
1257 NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %d",
1258 error, data_size);
1259 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1260 goto fail;
1261 }
1262
1263 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1264 if (new_wrapper == NULL) {
1265 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1266 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1267 goto fail;
1268 }
1269
1270 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1271
1272 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, &new_wrapper->netagent);
1273 if (error) {
1274 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1275 FREE(new_wrapper, M_NETAGENT);
1276 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1277 goto fail;
1278 }
1279
1280 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainUserDefined);
1281 if (response_error != 0) {
1282 FREE(new_wrapper, M_NETAGENT);
1283 goto fail;
1284 }
1285
1286 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1287 bool should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1288 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1289
1290 if (agent_changed == FALSE) {
1291 // The session wrapper does not need the "new_wrapper" as nothing changed
1292 FREE(new_wrapper, M_NETAGENT);
1293 }
1294
1295 return;
1296 fail:
1297 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1298 }
1299
1300 static void
1301 netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1302 u_int32_t payload_length, mbuf_t packet, int offset)
1303 {
1304 #pragma unused(payload_length, packet, offset)
1305 u_int8_t *response = NULL;
1306 u_int8_t *cursor = NULL;
1307 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1308
1309 if (session == NULL) {
1310 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1311 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1312 goto fail;
1313 }
1314
1315 if (session->wrapper == NULL) {
1316 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1317 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1318 goto fail;
1319 }
1320
1321 lck_rw_lock_shared(&netagent_lock);
1322
1323 size_t response_size = sizeof(struct netagent_message_header) + sizeof(session->wrapper->netagent)
1324 + session->wrapper->netagent.netagent_data_size;
1325 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
1326 if (response == NULL) {
1327 goto fail;
1328 }
1329
1330 cursor = response;
1331 cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1332 NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1333 response_size - sizeof(struct netagent_message_header));
1334 memcpy(cursor, &session->wrapper->netagent, sizeof(session->wrapper->netagent) +
1335 session->wrapper->netagent.netagent_data_size);
1336
1337 lck_rw_done(&netagent_lock);
1338
1339 if (!netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size)) {
1340 NETAGENTLOG0(LOG_ERR, "Failed to send response");
1341 }
1342 FREE(response, M_NETAGENT);
1343 return;
1344 fail:
1345 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1346 }
1347
1348 errno_t
1349 netagent_assign_nexus(netagent_session_t _session, uuid_t necp_client_uuid,
1350 void *assign_message, size_t assigned_results_length)
1351 {
1352 struct netagent_session *session = (struct netagent_session *)_session;
1353 if (session == NULL) {
1354 NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1355 return EINVAL;
1356 }
1357
1358 if (session->wrapper == NULL) {
1359 NETAGENTLOG0(LOG_ERR, "Session has no agent");
1360 return ENOENT;
1361 }
1362
1363 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1364 int error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, necp_client_uuid, assign_message, assigned_results_length);
1365 if (error) {
1366 // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1367 NETAGENTLOG((error == ENOENT ? LOG_DEBUG : LOG_ERR), "Client assignment failed: %d", error);
1368 return error;
1369 }
1370
1371 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1372 return 0;
1373 }
1374
1375 errno_t
1376 netagent_update_flow_protoctl_event(netagent_session_t _session,
1377 uuid_t client_id, uint32_t protoctl_event_code,
1378 uint32_t protoctl_event_val, uint32_t protoctl_event_tcp_seq_number)
1379 {
1380 struct netagent_session *session = (struct netagent_session *)_session;
1381 int error = 0;
1382
1383 if (session == NULL) {
1384 NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1385 return EINVAL;
1386 }
1387
1388 if (session->wrapper == NULL) {
1389 NETAGENTLOG0(LOG_ERR, "Session has no agent");
1390 return ENOENT;
1391 }
1392
1393 error = necp_update_flow_protoctl_event(session->wrapper->netagent.netagent_uuid,
1394 client_id, protoctl_event_code, protoctl_event_val, protoctl_event_tcp_seq_number);
1395
1396 return error;
1397 }
1398
1399 static errno_t
1400 netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1401 u_int32_t payload_length)
1402 {
1403 errno_t response_error = 0;
1404 struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1405 uuid_t client_id;
1406 u_int8_t *assigned_results = NULL;
1407
1408 if (session == NULL) {
1409 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1410 response_error = ENOENT;
1411 goto done;
1412 }
1413
1414 if (payload == NULL) {
1415 NETAGENTLOG0(LOG_ERR, "No payload received");
1416 response_error = EINVAL;
1417 goto done;
1418 }
1419
1420 if (session->wrapper == NULL) {
1421 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1422 response_error = ENOENT;
1423 goto done;
1424 }
1425
1426 if (payload_length < sizeof(uuid_t)) {
1427 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1428 response_error = EINVAL;
1429 goto done;
1430 }
1431
1432 memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1433 size_t assigned_results_length = (payload_length - sizeof(client_id));
1434
1435 if (assigned_results_length > 0) {
1436 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1437 if (assigned_results == NULL) {
1438 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1439 response_error = ENOMEM;
1440 goto done;
1441 }
1442 memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1443 }
1444
1445 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1446 response_error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1447 if (response_error) {
1448 // necp_assign_client_result returns POSIX errors
1449 if (assigned_results) {
1450 FREE(assigned_results, M_NETAGENT);
1451 }
1452 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1453 goto done;
1454 }
1455
1456 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1457 done:
1458 return response_error;
1459 }
1460
1461
1462 static void
1463 netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1464 u_int32_t payload_length, mbuf_t packet, int offset)
1465 {
1466 int error = 0;
1467 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1468 uuid_t client_id;
1469 u_int8_t *assigned_results = NULL;
1470
1471 if (session == NULL) {
1472 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1473 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1474 goto fail;
1475 }
1476
1477 if (session->wrapper == NULL) {
1478 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1479 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1480 goto fail;
1481 }
1482
1483 if (payload_length < sizeof(uuid_t)) {
1484 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1485 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1486 goto fail;
1487 }
1488
1489 error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1490 if (error) {
1491 NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1492 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1493 goto fail;
1494 }
1495
1496 size_t assigned_results_length = (payload_length - sizeof(client_id));
1497 if (assigned_results_length > 0) {
1498 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1499 if (assigned_results == NULL) {
1500 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1501 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1502 goto fail;
1503 }
1504
1505 error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1506 if (error) {
1507 FREE(assigned_results, M_NETAGENT);
1508 NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1509 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1510 goto fail;
1511 }
1512 }
1513
1514 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1515 error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1516 if (error) {
1517 if (assigned_results) {
1518 FREE(assigned_results, M_NETAGENT);
1519 }
1520 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1521 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1522 goto fail;
1523 }
1524
1525 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1526 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1527 return;
1528 fail:
1529 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1530 }
1531
1532 errno_t
1533 netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1534 {
1535 errno_t response_error = 0;
1536 uint64_t use_count = 0;
1537
1538 if (session == NULL) {
1539 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1540 response_error = ENOENT;
1541 goto done;
1542 }
1543
1544 if (payload == NULL) {
1545 NETAGENTLOG0(LOG_ERR, "No payload received");
1546 response_error = EINVAL;
1547 goto done;
1548 }
1549
1550 if (payload_length != sizeof(use_count)) {
1551 NETAGENTLOG(LOG_ERR, "Payload length is invalid (%lu)", payload_length);
1552 response_error = EINVAL;
1553 goto done;
1554 }
1555
1556 memcpy(&use_count, payload, sizeof(use_count));
1557
1558 lck_rw_lock_shared(&netagent_lock);
1559
1560 if (session->wrapper == NULL) {
1561 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1562 response_error = ENOENT;
1563 lck_rw_done(&netagent_lock);
1564 goto done;
1565 }
1566
1567 session->wrapper->use_count = use_count;
1568
1569 lck_rw_done(&netagent_lock);
1570
1571 done:
1572 return response_error;
1573 }
1574
1575 errno_t
1576 netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1577 {
1578 errno_t response_error = 0;
1579 uint64_t use_count = 0;
1580
1581 if (session == NULL) {
1582 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1583 response_error = ENOENT;
1584 goto done;
1585 }
1586
1587 if (buffer == NULL) {
1588 NETAGENTLOG0(LOG_ERR, "No payload received");
1589 response_error = EINVAL;
1590 goto done;
1591 }
1592
1593 if (*buffer_length != sizeof(use_count)) {
1594 NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1595 response_error = EINVAL;
1596 goto done;
1597 }
1598
1599 lck_rw_lock_shared(&netagent_lock);
1600
1601 if (session->wrapper == NULL) {
1602 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1603 response_error = ENOENT;
1604 lck_rw_done(&netagent_lock);
1605 goto done;
1606 }
1607
1608 use_count = session->wrapper->use_count;
1609 lck_rw_done(&netagent_lock);
1610
1611 memcpy(buffer, &use_count, sizeof(use_count));
1612 *buffer_length = sizeof(use_count);
1613
1614 done:
1615 return response_error;
1616 }
1617
1618 static struct netagent_wrapper *
1619 netagent_find_agent_with_uuid(uuid_t uuid)
1620 {
1621 struct netagent_wrapper *search_netagent = NULL;
1622
1623 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1624 if (uuid_compare(search_netagent->netagent.netagent_uuid, uuid) == 0) {
1625 return search_netagent;
1626 }
1627 }
1628
1629 return NULL;
1630 }
1631
1632 void
1633 netagent_post_updated_interfaces(uuid_t uuid)
1634 {
1635 struct netagent_wrapper *wrapper = NULL;
1636 lck_rw_lock_shared(&netagent_lock);
1637 wrapper = netagent_find_agent_with_uuid(uuid);
1638 lck_rw_done(&netagent_lock);
1639
1640 if (wrapper != NULL) {
1641 netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, TRUE, false);
1642 } else {
1643 NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
1644 }
1645
1646 return;
1647 }
1648
1649 static u_int32_t
1650 netagent_dump_get_data_size_locked()
1651 {
1652 struct netagent_wrapper *search_netagent = NULL;
1653 u_int32_t total_netagent_data_size = 0;
1654 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1655 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1656 total_netagent_data_size += sizeof(search_netagent->netagent.netagent_uuid);
1657 }
1658 return total_netagent_data_size;
1659 }
1660
1661 static void
1662 netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
1663 {
1664 size_t response_size = 0;
1665 u_int8_t *cursor = NULL;
1666 struct netagent_wrapper *search_netagent = NULL;
1667
1668 response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
1669 cursor = buffer;
1670 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1671 memcpy(cursor, search_netagent->netagent.netagent_uuid, sizeof(search_netagent->netagent.netagent_uuid));
1672 cursor += sizeof(search_netagent->netagent.netagent_uuid);
1673 }
1674 }
1675
1676 int
1677 netagent_ioctl(u_long cmd, caddr_t data)
1678 {
1679 int error = 0;
1680
1681 switch (cmd) {
1682 case SIOCGIFAGENTLIST32:
1683 case SIOCGIFAGENTLIST64: {
1684 /* Check entitlement if the client requests agent dump */
1685 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
1686 if (cred_result != 0) {
1687 NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
1688 return EINVAL;
1689 }
1690 break;
1691 }
1692 default:
1693 break;
1694 }
1695
1696 lck_rw_lock_shared(&netagent_lock);
1697 switch (cmd) {
1698 case SIOCGIFAGENTDATA32: {
1699 struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
1700 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
1701 if (wrapper == NULL) {
1702 error = ENOENT;
1703 break;
1704 }
1705 uuid_copy(ifsir32->netagent_uuid, wrapper->netagent.netagent_uuid);
1706 memcpy(ifsir32->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir32->netagent_domain));
1707 memcpy(ifsir32->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir32->netagent_type));
1708 memcpy(ifsir32->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir32->netagent_desc));
1709 ifsir32->netagent_flags = wrapper->netagent.netagent_flags;
1710 if (ifsir32->netagent_data_size == 0) {
1711 // First pass, client wants data size
1712 ifsir32->netagent_data_size = wrapper->netagent.netagent_data_size;
1713 } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
1714 ifsir32->netagent_data_size == wrapper->netagent.netagent_data_size) {
1715 // Second pass, client wants data buffer filled out
1716 error = copyout(wrapper->netagent.netagent_data, ifsir32->netagent_data, wrapper->netagent.netagent_data_size);
1717 } else {
1718 error = EINVAL;
1719 }
1720 break;
1721 }
1722 case SIOCGIFAGENTDATA64: {
1723 struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
1724 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
1725 if (wrapper == NULL) {
1726 error = ENOENT;
1727 break;
1728 }
1729 uuid_copy(ifsir64->netagent_uuid, wrapper->netagent.netagent_uuid);
1730 memcpy(ifsir64->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir64->netagent_domain));
1731 memcpy(ifsir64->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir64->netagent_type));
1732 memcpy(ifsir64->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir64->netagent_desc));
1733 ifsir64->netagent_flags = wrapper->netagent.netagent_flags;
1734 if (ifsir64->netagent_data_size == 0) {
1735 // First pass, client wants data size
1736 ifsir64->netagent_data_size = wrapper->netagent.netagent_data_size;
1737 } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
1738 ifsir64->netagent_data_size == wrapper->netagent.netagent_data_size) {
1739 // Second pass, client wants data buffer filled out
1740 error = copyout(wrapper->netagent.netagent_data, ifsir64->netagent_data, wrapper->netagent.netagent_data_size);
1741 } else {
1742 error = EINVAL;
1743 }
1744 break;
1745 }
1746 case SIOCGIFAGENTLIST32: {
1747 struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
1748 if (ifsir32->data_size == 0) {
1749 // First pass, client wants data size
1750 ifsir32->data_size = netagent_dump_get_data_size_locked();
1751 } else if (ifsir32->data != USER_ADDR_NULL &&
1752 ifsir32->data_size > 0 &&
1753 ifsir32->data_size == netagent_dump_get_data_size_locked()) {
1754 // Second pass, client wants data buffer filled out
1755 u_int8_t *response = NULL;
1756 MALLOC(response, u_int8_t *, ifsir32->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1757 if (response == NULL) {
1758 error = ENOMEM;
1759 break;
1760 }
1761
1762 netagent_dump_copy_data_locked(response, ifsir32->data_size);
1763 error = copyout(response, ifsir32->data, ifsir32->data_size);
1764 FREE(response, M_NETAGENT);
1765 } else {
1766 error = EINVAL;
1767 }
1768 break;
1769 }
1770 case SIOCGIFAGENTLIST64: {
1771 struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
1772 if (ifsir64->data_size == 0) {
1773 // First pass, client wants data size
1774 ifsir64->data_size = netagent_dump_get_data_size_locked();
1775 } else if (ifsir64->data != USER_ADDR_NULL &&
1776 ifsir64->data_size > 0 &&
1777 ifsir64->data_size == netagent_dump_get_data_size_locked()) {
1778 // Second pass, client wants data buffer filled out
1779 u_int8_t *response = NULL;
1780 MALLOC(response, u_int8_t *, ifsir64->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1781 if (response == NULL) {
1782 error = ENOMEM;
1783 break;
1784 }
1785
1786 netagent_dump_copy_data_locked(response, ifsir64->data_size);
1787 error = copyout(response, ifsir64->data, ifsir64->data_size);
1788 FREE(response, M_NETAGENT);
1789 } else {
1790 error = EINVAL;
1791 }
1792 break;
1793 }
1794 default: {
1795 error = EINVAL;
1796 break;
1797 }
1798 }
1799 lck_rw_done(&netagent_lock);
1800 return error;
1801 }
1802
1803 u_int32_t
1804 netagent_get_flags(uuid_t uuid)
1805 {
1806 u_int32_t flags = 0;
1807 lck_rw_lock_shared(&netagent_lock);
1808 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1809 if (wrapper != NULL) {
1810 flags = wrapper->netagent.netagent_flags;
1811 } else {
1812 NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
1813 }
1814 lck_rw_done(&netagent_lock);
1815
1816 return flags;
1817 }
1818
1819 errno_t
1820 netagent_set_flags(uuid_t uuid, u_int32_t flags)
1821 {
1822 errno_t error = 0;
1823 lck_rw_lock_exclusive(&netagent_lock);
1824 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1825 if (wrapper != NULL) {
1826 wrapper->netagent.netagent_flags = flags;
1827 } else {
1828 NETAGENTLOG0(LOG_DEBUG,
1829 "Attempt to set flags for invalid netagent");
1830 error = ENOENT;
1831 }
1832 lck_rw_done(&netagent_lock);
1833
1834 return error;
1835 }
1836
1837 u_int32_t
1838 netagent_get_generation(uuid_t uuid)
1839 {
1840 u_int32_t generation = 0;
1841 lck_rw_lock_shared(&netagent_lock);
1842 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1843 if (wrapper != NULL) {
1844 generation = wrapper->generation;
1845 } else {
1846 NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
1847 }
1848 lck_rw_done(&netagent_lock);
1849
1850 return generation;
1851 }
1852
1853 bool
1854 netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
1855 {
1856 bool found = FALSE;
1857 if (domain == NULL || type == NULL) {
1858 NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
1859 return FALSE;
1860 }
1861
1862 lck_rw_lock_shared(&netagent_lock);
1863 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1864 if (wrapper != NULL) {
1865 found = TRUE;
1866 memcpy(domain, wrapper->netagent.netagent_domain, NETAGENT_DOMAINSIZE);
1867 memcpy(type, wrapper->netagent.netagent_type, NETAGENT_TYPESIZE);
1868 } else {
1869 NETAGENTLOG0(LOG_ERR, "Type requested for invalid netagent");
1870 }
1871 lck_rw_done(&netagent_lock);
1872
1873 return found;
1874 }
1875
1876 int
1877 netagent_kernel_trigger(uuid_t uuid)
1878 {
1879 int error = 0;
1880
1881 lck_rw_lock_shared(&netagent_lock);
1882 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1883 if (wrapper == NULL) {
1884 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
1885 error = ENOENT;
1886 goto done;
1887 }
1888
1889 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
1890 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
1891 // Agent does not accept kernel triggers
1892 error = EINVAL;
1893 goto done;
1894 }
1895
1896 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1897 // Agent already active
1898 NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
1899 error = 0;
1900 goto done;
1901 }
1902
1903 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
1904 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
1905 done:
1906 lck_rw_done(&netagent_lock);
1907 return error;
1908 }
1909
1910 int
1911 netagent_client_message_with_params(uuid_t agent_uuid,
1912 uuid_t necp_client_uuid,
1913 pid_t pid,
1914 void *handle,
1915 u_int8_t message_type,
1916 struct necp_client_agent_parameters *parameters,
1917 void **assigned_results,
1918 size_t *assigned_results_length)
1919 {
1920 int error = 0;
1921
1922 if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
1923 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
1924 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
1925 message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
1926 message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS &&
1927 message_type != NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
1928 NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
1929 return EINVAL;
1930 }
1931
1932 lck_rw_lock_shared(&netagent_lock);
1933 bool should_unlock = TRUE;
1934 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1935 if (wrapper == NULL) {
1936 NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
1937 error = ENOENT;
1938 goto done;
1939 }
1940
1941 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1942 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1943 // Agent does not accept user triggers
1944 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1945 error = ENOTSUP;
1946
1947
1948 pid_t report_pid = 0;
1949 uuid_t report_proc_uuid = {};
1950 if (parameters != NULL) {
1951 report_pid = parameters->u.nexus_request.epid;
1952 uuid_copy(report_proc_uuid, parameters->u.nexus_request.euuid);
1953 } else {
1954 struct proc *p = current_proc();
1955 if (p != NULL) {
1956 report_pid = proc_pid(p);
1957 proc_getexecutableuuid(p, report_proc_uuid, sizeof(report_proc_uuid));
1958 }
1959 }
1960 netagent_send_cellular_failed_event(wrapper, report_pid, report_proc_uuid);
1961 goto done;
1962 }
1963 } else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
1964 message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS ||
1965 message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
1966 bool is_nexus_agent = ((wrapper->netagent.netagent_flags &
1967 (NETAGENT_FLAG_NEXUS_PROVIDER |
1968 NETAGENT_FLAG_NEXUS_LISTENER |
1969 NETAGENT_FLAG_CUSTOM_IP_NEXUS |
1970 NETAGENT_FLAG_CUSTOM_ETHER_NEXUS |
1971 NETAGENT_FLAG_INTERPOSE_NEXUS)) != 0);
1972 if (!is_nexus_agent) {
1973 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
1974 // Agent is not a nexus provider
1975 error = EINVAL;
1976 goto done;
1977 }
1978
1979 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
1980 // Agent not active
1981 NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
1982 error = EINVAL;
1983 goto done;
1984 }
1985 }
1986
1987 if (wrapper->control_unit == 0) {
1988 if (wrapper->event_handler == NULL) {
1989 // No event handler registered for kernel agent
1990 error = EINVAL;
1991 } else {
1992 // We hold the shared lock during the event handler callout, so it is expected
1993 // that the event handler will not lead to any registrations or unregistrations
1994 // of network agents.
1995 error = wrapper->event_handler(message_type, necp_client_uuid, pid, handle,
1996 wrapper->event_context, parameters,
1997 assigned_results, assigned_results_length);
1998 if (error != 0) {
1999 VERIFY(assigned_results == NULL || *assigned_results == NULL);
2000 VERIFY(assigned_results_length == NULL || *assigned_results_length == 0);
2001 }
2002 }
2003 } else {
2004 // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2005 if (message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2006 message_type = NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS;
2007 }
2008
2009 error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
2010 if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2011 if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
2012 // Grab the lock exclusively to add a pending client to the list
2013 struct netagent_client *new_pending_client = NULL;
2014 MALLOC(new_pending_client, struct netagent_client *, sizeof(*new_pending_client), M_NETAGENT, M_WAITOK);
2015 if (new_pending_client == NULL) {
2016 NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
2017 } else {
2018 uuid_copy(new_pending_client->client_id, necp_client_uuid);
2019 if (parameters != NULL) {
2020 new_pending_client->client_pid = parameters->u.nexus_request.epid;
2021 uuid_copy(new_pending_client->client_proc_uuid, parameters->u.nexus_request.euuid);
2022 } else {
2023 struct proc *p = current_proc();
2024 if (p != NULL) {
2025 new_pending_client->client_pid = proc_pid(p);
2026 proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
2027 }
2028 }
2029 LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
2030 }
2031 } else {
2032 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2033 should_unlock = FALSE;
2034 }
2035 }
2036 }
2037 NETAGENTLOG(((error && error != ENOENT) ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
2038 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2039 uuid_string_t uuid_str;
2040 uuid_unparse(agent_uuid, uuid_str);
2041 NETAGENTLOG(LOG_NOTICE, "Triggered network agent %s, error = %d", uuid_str, error);
2042 }
2043 done:
2044 if (should_unlock) {
2045 lck_rw_done(&netagent_lock);
2046 }
2047 return error;
2048 }
2049
2050 int
2051 netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, pid_t pid, void *handle, u_int8_t message_type)
2052 {
2053 return netagent_client_message_with_params(agent_uuid, necp_client_uuid, pid, handle, message_type, NULL, NULL, NULL);
2054 }
2055
2056 int
2057 netagent_use(uuid_t agent_uuid, uint64_t *out_use_count)
2058 {
2059 int error = 0;
2060
2061 lck_rw_lock_exclusive(&netagent_lock);
2062 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2063 if (wrapper == NULL) {
2064 NETAGENTLOG0(LOG_ERR, "netagent_assert: Requested netagent UUID is not registered");
2065 error = ENOENT;
2066 goto done;
2067 }
2068
2069 uint64_t current_count = wrapper->use_count;
2070 wrapper->use_count++;
2071
2072 if (out_use_count != NULL) {
2073 *out_use_count = current_count;
2074 }
2075
2076 done:
2077 lck_rw_done(&netagent_lock);
2078 return error;
2079 }
2080
2081 int
2082 netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
2083 {
2084 int error = 0;
2085
2086 lck_rw_lock_shared(&netagent_lock);
2087 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2088 if (wrapper == NULL) {
2089 NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2090 error = ENOENT;
2091 goto done;
2092 }
2093
2094 u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent.netagent_data_size);
2095 if (user_size < total_size) {
2096 NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
2097 error = EINVAL;
2098 goto done;
2099 }
2100
2101 error = copyout(&wrapper->netagent, user_addr, total_size);
2102
2103 NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
2104 done:
2105 lck_rw_done(&netagent_lock);
2106 return error;
2107 }
2108
2109 int
2110 netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
2111 {
2112 #pragma unused(p, retval)
2113 uuid_t agent_uuid;
2114 int error = 0;
2115
2116 if (uap == NULL) {
2117 NETAGENTLOG0(LOG_ERR, "uap == NULL");
2118 return EINVAL;
2119 }
2120
2121 if (uap->agent_uuid) {
2122 if (uap->agent_uuidlen != sizeof(uuid_t)) {
2123 NETAGENTLOG(LOG_ERR, "Incorrect length (got %zu, expected %lu)",
2124 (size_t)uap->agent_uuidlen, sizeof(uuid_t));
2125 return ERANGE;
2126 }
2127
2128 error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
2129 if (error) {
2130 NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
2131 return error;
2132 }
2133 }
2134
2135 if (uuid_is_null(agent_uuid)) {
2136 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
2137 return EINVAL;
2138 }
2139
2140 lck_rw_lock_shared(&netagent_lock);
2141 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2142 if (wrapper == NULL) {
2143 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
2144 error = ENOENT;
2145 goto done;
2146 }
2147
2148 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2149 // Agent does not accept triggers
2150 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
2151 error = ENOTSUP;
2152 goto done;
2153 }
2154
2155 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2156 // Agent already active
2157 NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
2158 error = 0;
2159 goto done;
2160 }
2161
2162 error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
2163 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
2164 done:
2165 lck_rw_done(&netagent_lock);
2166 return error;
2167 }