2 * Copyright (c) 2014-2018 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
38 #include <sys/kpi_mbuf.h>
39 #include <sys/sysctl.h>
41 #include <sys/kern_event.h>
42 #include <sys/sysproto.h>
43 #include <net/network_agent.h>
44 #include <net/if_var.h>
48 u_int32_t netagent_debug
= LOG_NOTICE
; // 0=None, 1=Basic
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, "");
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, "");
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, "");
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__); \
66 os_log(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
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); \
76 os_log(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
81 struct netagent_client
{
82 LIST_ENTRY(netagent_client
) client_chain
;
84 uuid_t client_proc_uuid
;
88 LIST_HEAD(netagent_client_list_s
, netagent_client
);
90 struct netagent_wrapper
{
91 LIST_ENTRY(netagent_wrapper
) master_chain
;
92 u_int32_t control_unit
;
93 netagent_event_f event_handler
;
97 struct netagent_client_list_s pending_triggers_list
;
98 struct netagent netagent
;
101 struct netagent_session
{
102 u_int32_t control_unit
; // A control unit of 0 indicates an agent owned by the kernel
103 struct netagent_wrapper
*wrapper
;
104 netagent_event_f event_handler
;
109 kNetagentErrorDomainPOSIX
= 0,
110 kNetagentErrorDomainUserDefined
= 1,
111 } netagent_error_domain_t
;
113 static LIST_HEAD(_netagent_list
, netagent_wrapper
) master_netagent_list
;
115 // Protected by netagent_lock
116 static u_int32_t g_next_generation
= 1;
118 static kern_ctl_ref netagent_kctlref
;
119 static u_int32_t netagent_family
;
120 static lck_grp_attr_t
*netagent_grp_attr
= NULL
;
121 static lck_attr_t
*netagent_mtx_attr
= NULL
;
122 static lck_grp_t
*netagent_mtx_grp
= NULL
;
123 decl_lck_rw_data(static, netagent_lock
);
125 static errno_t
netagent_register_control(void);
126 static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
128 static errno_t
netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
);
129 static errno_t
netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
130 mbuf_t m
, int flags
);
131 static void netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
);
132 static errno_t
netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
133 int opt
, void *data
, size_t *len
);
134 static errno_t
netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
135 int opt
, void *data
, size_t len
);
137 static int netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
);
139 static struct netagent_session
*netagent_create_session(u_int32_t control_unit
);
140 static void netagent_delete_session(struct netagent_session
*session
);
143 static void netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
144 size_t payload_length
, mbuf_t packet
, size_t offset
);
145 static errno_t
netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
146 size_t payload_length
);
149 static void netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
150 size_t payload_length
, mbuf_t packet
, size_t offset
);
151 static errno_t
netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
152 size_t payload_length
);
155 static void netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
156 size_t payload_length
, mbuf_t packet
, size_t offset
);
157 static errno_t
netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
158 size_t payload_length
);
161 static void netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
162 size_t payload_length
, mbuf_t packet
, size_t offset
);
163 static errno_t
netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
164 size_t payload_length
);
166 // Set/get assert count
167 static errno_t
netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
);
168 static errno_t
netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
);
170 static void netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
171 size_t payload_length
, mbuf_t packet
, size_t offset
);
173 static struct netagent_wrapper
*netagent_find_agent_with_uuid(uuid_t uuid
);
180 result
= netagent_register_control();
185 netagent_grp_attr
= lck_grp_attr_alloc_init();
186 if (netagent_grp_attr
== NULL
) {
187 NETAGENTLOG0(LOG_ERR
, "lck_grp_attr_alloc_init failed");
192 netagent_mtx_grp
= lck_grp_alloc_init(NETAGENT_CONTROL_NAME
, netagent_grp_attr
);
193 if (netagent_mtx_grp
== NULL
) {
194 NETAGENTLOG0(LOG_ERR
, "lck_grp_alloc_init failed");
199 netagent_mtx_attr
= lck_attr_alloc_init();
200 if (netagent_mtx_attr
== NULL
) {
201 NETAGENTLOG0(LOG_ERR
, "lck_attr_alloc_init failed");
206 lck_rw_init(&netagent_lock
, netagent_mtx_grp
, netagent_mtx_attr
);
208 LIST_INIT(&master_netagent_list
);
212 if (netagent_mtx_attr
!= NULL
) {
213 lck_attr_free(netagent_mtx_attr
);
214 netagent_mtx_attr
= NULL
;
216 if (netagent_mtx_grp
!= NULL
) {
217 lck_grp_free(netagent_mtx_grp
);
218 netagent_mtx_grp
= NULL
;
220 if (netagent_grp_attr
!= NULL
) {
221 lck_grp_attr_free(netagent_grp_attr
);
222 netagent_grp_attr
= NULL
;
224 if (netagent_kctlref
!= NULL
) {
225 ctl_deregister(netagent_kctlref
);
226 netagent_kctlref
= NULL
;
233 netagent_register_control(void)
235 struct kern_ctl_reg kern_ctl
;
238 // Find a unique value for our interface family
239 result
= mbuf_tag_id_find(NETAGENT_CONTROL_NAME
, &netagent_family
);
241 NETAGENTLOG(LOG_ERR
, "mbuf_tag_id_find_internal failed: %d", result
);
245 bzero(&kern_ctl
, sizeof(kern_ctl
));
246 strlcpy(kern_ctl
.ctl_name
, NETAGENT_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
247 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
248 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; // Require root
249 kern_ctl
.ctl_sendsize
= 64 * 1024;
250 kern_ctl
.ctl_recvsize
= 64 * 1024;
251 kern_ctl
.ctl_connect
= netagent_ctl_connect
;
252 kern_ctl
.ctl_disconnect
= netagent_ctl_disconnect
;
253 kern_ctl
.ctl_send
= netagent_ctl_send
;
254 kern_ctl
.ctl_rcvd
= netagent_ctl_rcvd
;
255 kern_ctl
.ctl_setopt
= netagent_ctl_setopt
;
256 kern_ctl
.ctl_getopt
= netagent_ctl_getopt
;
258 result
= ctl_register(&kern_ctl
, &netagent_kctlref
);
260 NETAGENTLOG(LOG_ERR
, "ctl_register failed: %d", result
);
268 netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
, void **unitinfo
)
270 #pragma unused(kctlref)
271 *unitinfo
= netagent_create_session(sac
->sc_unit
);
272 if (*unitinfo
== NULL
) {
273 // Could not allocate session
281 netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
)
283 #pragma unused(kctlref, unit)
284 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
285 if (session
!= NULL
) {
286 netagent_delete_session(session
);
294 netagent_post_event(uuid_t agent_uuid
, u_int32_t event_code
, bool update_necp
, bool should_update_immediately
)
297 necp_update_all_clients_immediately_if_needed(should_update_immediately
);
300 struct kev_msg ev_msg
;
301 memset(&ev_msg
, 0, sizeof(ev_msg
));
303 struct kev_netagent_data event_data
;
305 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
306 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
307 ev_msg
.kev_subclass
= KEV_NETAGENT_SUBCLASS
;
308 ev_msg
.event_code
= event_code
;
310 uuid_copy(event_data
.netagent_uuid
, agent_uuid
);
311 ev_msg
.dv
[0].data_ptr
= &event_data
;
312 ev_msg
.dv
[0].data_length
= sizeof(event_data
);
314 kev_post_msg(&ev_msg
);
319 netagent_buffer_write_message_header(u_int8_t
*buffer
, u_int8_t message_type
, u_int8_t flags
,
320 u_int32_t message_id
, u_int32_t error
, size_t payload_length
)
322 memset(buffer
, 0, sizeof(struct netagent_message_header
));
323 ((struct netagent_message_header
*)(void *)buffer
)->message_type
= message_type
;
324 ((struct netagent_message_header
*)(void *)buffer
)->message_flags
= flags
;
325 ((struct netagent_message_header
*)(void *)buffer
)->message_id
= message_id
;
326 ((struct netagent_message_header
*)(void *)buffer
)->message_error
= error
;
327 ((struct netagent_message_header
*)(void *)buffer
)->message_payload_length
= (u_int32_t
)payload_length
;
328 return buffer
+ sizeof(struct netagent_message_header
);
332 netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
)
334 if (netagent_kctlref
== NULL
|| control_unit
== 0 || buffer
== NULL
|| buffer_size
== 0) {
338 return ctl_enqueuedata(netagent_kctlref
, control_unit
, buffer
, buffer_size
, CTL_DATA_EOR
);
342 netagent_send_trigger(struct netagent_wrapper
*wrapper
, struct proc
*p
, u_int32_t flags
, u_int8_t trigger_type
)
345 struct netagent_trigger_message
*trigger_message
= NULL
;
346 u_int8_t
*trigger
= NULL
;
347 size_t trigger_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_trigger_message
);
349 MALLOC(trigger
, u_int8_t
*, trigger_size
, M_NETAGENT
, M_WAITOK
);
350 if (trigger
== NULL
) {
354 (void)netagent_buffer_write_message_header(trigger
, trigger_type
, 0, 0, 0, sizeof(struct netagent_trigger_message
));
356 trigger_message
= (struct netagent_trigger_message
*)(void *)(trigger
+ sizeof(struct netagent_message_header
));
357 trigger_message
->trigger_flags
= flags
;
359 trigger_message
->trigger_pid
= proc_pid(p
);
360 proc_getexecutableuuid(p
, trigger_message
->trigger_proc_uuid
, sizeof(trigger_message
->trigger_proc_uuid
));
362 trigger_message
->trigger_pid
= 0;
363 uuid_clear(trigger_message
->trigger_proc_uuid
);
366 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)trigger
, trigger_size
))) {
367 NETAGENTLOG(LOG_ERR
, "Failed to send trigger message on control unit %d", wrapper
->control_unit
);
370 FREE(trigger
, M_NETAGENT
);
375 netagent_send_client_message(struct netagent_wrapper
*wrapper
, uuid_t client_id
, u_int8_t message_type
)
378 struct netagent_client_message
*client_message
= NULL
;
379 u_int8_t
*message
= NULL
;
380 size_t message_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_client_message
);
382 MALLOC(message
, u_int8_t
*, message_size
, M_NETAGENT
, M_WAITOK
);
383 if (message
== NULL
) {
387 (void)netagent_buffer_write_message_header(message
, message_type
, 0, 0, 0, sizeof(struct netagent_client_message
));
389 client_message
= (struct netagent_client_message
*)(void *)(message
+ sizeof(struct netagent_message_header
));
390 uuid_copy(client_message
->client_id
, client_id
);
392 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)message
, message_size
))) {
393 NETAGENTLOG(LOG_ERR
, "Failed to send client message %d on control unit %d", message_type
, wrapper
->control_unit
);
396 FREE(message
, M_NETAGENT
);
401 netagent_send_success_response(struct netagent_session
*session
, u_int8_t message_type
, u_int32_t message_id
)
404 u_int8_t
*response
= NULL
;
405 size_t response_size
= sizeof(struct netagent_message_header
);
406 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
407 if (response
== NULL
) {
410 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0, 0);
412 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
413 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
416 FREE(response
, M_NETAGENT
);
421 netagent_send_error_response(struct netagent_session
*session
, u_int8_t message_type
,
422 u_int32_t message_id
, u_int32_t error_code
)
425 u_int8_t
*response
= NULL
;
426 size_t response_size
= sizeof(struct netagent_message_header
);
428 if (session
== NULL
) {
429 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
433 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
434 if (response
== NULL
) {
437 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
,
438 message_id
, error_code
, 0);
440 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
441 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
444 FREE(response
, M_NETAGENT
);
449 netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, mbuf_t packet
, int flags
)
451 #pragma unused(kctlref, unit, flags)
452 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
453 struct netagent_message_header header
;
456 if (session
== NULL
) {
457 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
462 if (mbuf_pkthdr_len(packet
) < sizeof(header
)) {
463 NETAGENTLOG(LOG_ERR
, "Got a bad packet, length (%lu) < sizeof header (%lu)",
464 mbuf_pkthdr_len(packet
), sizeof(header
));
469 error
= mbuf_copydata(packet
, 0, sizeof(header
), &header
);
471 NETAGENTLOG(LOG_ERR
, "mbuf_copydata failed for the header: %d", error
);
476 switch (header
.message_type
) {
477 case NETAGENT_MESSAGE_TYPE_REGISTER
: {
478 netagent_handle_register_message(session
, header
.message_id
, header
.message_payload_length
,
479 packet
, sizeof(header
));
482 case NETAGENT_MESSAGE_TYPE_UNREGISTER
: {
483 netagent_handle_unregister_message(session
, header
.message_id
, header
.message_payload_length
,
484 packet
, sizeof(header
));
487 case NETAGENT_MESSAGE_TYPE_UPDATE
: {
488 netagent_handle_update_message(session
, header
.message_id
, header
.message_payload_length
,
489 packet
, sizeof(header
));
492 case NETAGENT_MESSAGE_TYPE_GET
: {
493 netagent_handle_get(session
, header
.message_id
, header
.message_payload_length
,
494 packet
, sizeof(header
));
497 case NETAGENT_MESSAGE_TYPE_ASSERT
: {
498 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
501 case NETAGENT_MESSAGE_TYPE_UNASSERT
: {
502 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
505 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
: {
506 netagent_handle_assign_nexus_message(session
, header
.message_id
, header
.message_payload_length
,
507 packet
, sizeof(header
));
511 NETAGENTLOG(LOG_ERR
, "Received unknown message type %d", header
.message_type
);
512 netagent_send_error_response(session
, header
.message_type
, header
.message_id
,
513 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE
);
524 netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
526 #pragma unused(kctlref, unit, unitinfo, flags)
531 netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
532 void *data
, size_t *len
)
534 #pragma unused(kctlref, unit)
535 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
538 if (session
== NULL
) {
539 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
545 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
546 NETAGENTLOG0(LOG_DEBUG
, "Request to get use count");
547 error
= netagent_handle_use_count_getopt(session
, data
, len
);
551 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
561 netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
562 void *data
, size_t len
)
564 #pragma unused(kctlref, unit)
565 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
568 if (session
== NULL
) {
569 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
575 case NETAGENT_OPTION_TYPE_REGISTER
: {
576 NETAGENTLOG0(LOG_DEBUG
, "Request for registration");
577 error
= netagent_handle_register_setopt(session
, data
, len
);
580 case NETAGENT_OPTION_TYPE_UPDATE
: {
581 NETAGENTLOG0(LOG_DEBUG
, "Request for update");
582 error
= netagent_handle_update_setopt(session
, data
, len
);
585 case NETAGENT_OPTION_TYPE_UNREGISTER
: {
586 NETAGENTLOG0(LOG_DEBUG
, "Request for unregistration");
587 error
= netagent_handle_unregister_setopt(session
, data
, len
);
590 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS
: {
591 NETAGENTLOG0(LOG_DEBUG
, "Request for assigning nexus");
592 error
= netagent_handle_assign_nexus_setopt(session
, data
, len
);
595 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
596 NETAGENTLOG0(LOG_DEBUG
, "Request to set use count");
597 error
= netagent_handle_use_count_setopt(session
, data
, len
);
601 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
610 // Session Management
611 static struct netagent_session
*
612 netagent_create_session(u_int32_t control_unit
)
614 struct netagent_session
*new_session
= NULL
;
616 MALLOC(new_session
, struct netagent_session
*, sizeof(*new_session
), M_NETAGENT
, M_WAITOK
);
617 if (new_session
== NULL
) {
620 NETAGENTLOG(LOG_DEBUG
, "Create agent session, control unit %d", control_unit
);
621 memset(new_session
, 0, sizeof(*new_session
));
622 new_session
->control_unit
= control_unit
;
623 new_session
->wrapper
= NULL
;
629 netagent_create(netagent_event_f event_handler
, void *context
)
631 struct netagent_session
*session
= netagent_create_session(0);
632 if (session
== NULL
) {
636 session
->event_handler
= event_handler
;
637 session
->event_context
= context
;
642 netagent_free_wrapper(struct netagent_wrapper
*wrapper
)
644 // Free any pending client triggers
645 struct netagent_client
*search_client
= NULL
;
646 struct netagent_client
*temp_client
= NULL
;
647 LIST_FOREACH_SAFE(search_client
, &wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
648 LIST_REMOVE(search_client
, client_chain
);
649 FREE(search_client
, M_NETAGENT
);
652 // Free wrapper itself
653 FREE(wrapper
, M_NETAGENT
);
657 netagent_unregister_session_wrapper(struct netagent_session
*session
)
659 bool unregistered
= FALSE
;
660 uuid_t unregistered_uuid
;
661 struct netagent_wrapper
*wrapper
= NULL
;
662 lck_rw_lock_exclusive(&netagent_lock
);
663 if (session
!= NULL
) {
664 wrapper
= session
->wrapper
;
665 if (wrapper
!= NULL
) {
666 if (netagent_registered_count
> 0) {
667 netagent_registered_count
--;
669 if ((session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
670 netagent_active_count
> 0) {
671 netagent_active_count
--;
674 LIST_REMOVE(wrapper
, master_chain
);
677 uuid_copy(unregistered_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
679 netagent_free_wrapper(session
->wrapper
);
680 session
->wrapper
= NULL
;
681 NETAGENTLOG0(LOG_DEBUG
, "Unregistered agent");
684 lck_rw_done(&netagent_lock
);
687 ifnet_clear_netagent(unregistered_uuid
);
688 netagent_post_event(unregistered_uuid
, KEV_NETAGENT_UNREGISTERED
, TRUE
, false);
693 netagent_delete_session(struct netagent_session
*session
)
695 if (session
!= NULL
) {
696 netagent_unregister_session_wrapper(session
);
697 FREE(session
, M_NETAGENT
);
702 netagent_destroy(netagent_session_t session
)
704 return netagent_delete_session((struct netagent_session
*)session
);
708 netagent_packet_get_netagent_data_size(mbuf_t packet
, size_t offset
, int *err
)
712 struct netagent netagent_peek
;
713 memset(&netagent_peek
, 0, sizeof(netagent_peek
));
717 error
= mbuf_copydata(packet
, offset
, sizeof(netagent_peek
), &netagent_peek
);
723 return netagent_peek
.netagent_data_size
;
727 netagent_handle_register_inner(struct netagent_session
*session
, struct netagent_wrapper
*new_wrapper
)
729 lck_rw_lock_exclusive(&netagent_lock
);
731 if (session
->wrapper
!= NULL
) {
732 lck_rw_done(&netagent_lock
);
736 new_wrapper
->control_unit
= session
->control_unit
;
737 new_wrapper
->event_handler
= session
->event_handler
;
738 new_wrapper
->event_context
= session
->event_context
;
739 new_wrapper
->generation
= g_next_generation
++;
741 session
->wrapper
= new_wrapper
;
742 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
743 LIST_INIT(&new_wrapper
->pending_triggers_list
);
745 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
746 netagent_registered_count
++;
747 if (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) {
748 netagent_active_count
++;
751 lck_rw_done(&netagent_lock
);
757 netagent_register(netagent_session_t _session
, struct netagent
*agent
)
759 struct netagent_wrapper
*new_wrapper
= NULL
;
760 uuid_t registered_uuid
;
762 struct netagent_session
*session
= (struct netagent_session
*)_session
;
763 if (session
== NULL
) {
764 NETAGENTLOG0(LOG_ERR
, "Cannot register agent on NULL session");
769 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
773 if (session
->wrapper
!= NULL
) {
774 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
778 size_t data_size
= agent
->netagent_data_size
;
779 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
780 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %zu",
785 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
786 if (new_wrapper
== NULL
) {
787 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
791 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
792 __nochk_memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
794 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
796 errno_t error
= netagent_handle_register_inner(session
, new_wrapper
);
798 FREE(new_wrapper
, M_NETAGENT
);
802 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
803 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
809 netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
810 size_t payload_length
)
812 struct netagent_wrapper
*new_wrapper
= NULL
;
813 errno_t response_error
= 0;
814 struct netagent
*register_netagent
= (struct netagent
*)(void *)payload
;
815 uuid_t registered_uuid
;
817 if (session
== NULL
) {
818 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
819 response_error
= EINVAL
;
823 if (payload
== NULL
) {
824 NETAGENTLOG0(LOG_ERR
, "No payload received");
825 response_error
= EINVAL
;
829 if (session
->wrapper
!= NULL
) {
830 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
831 response_error
= EINVAL
;
835 if (payload_length
< sizeof(struct netagent
)) {
836 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%zu < %zu)",
837 payload_length
, sizeof(struct netagent
));
838 response_error
= EINVAL
;
842 size_t data_size
= register_netagent
->netagent_data_size
;
843 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
844 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %zu", data_size
);
845 response_error
= EINVAL
;
849 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
850 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent
) + data_size
), payload_length
);
851 response_error
= EINVAL
;
855 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
856 if (new_wrapper
== NULL
) {
857 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
858 response_error
= ENOMEM
;
862 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
863 __nochk_memcpy(&new_wrapper
->netagent
, register_netagent
, sizeof(struct netagent
) + data_size
);
865 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
867 response_error
= netagent_handle_register_inner(session
, new_wrapper
);
868 if (response_error
!= 0) {
869 FREE(new_wrapper
, M_NETAGENT
);
873 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
874 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
877 return response_error
;
881 netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
882 size_t payload_length
, mbuf_t packet
, size_t offset
)
885 struct netagent_wrapper
*new_wrapper
= NULL
;
886 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
887 uuid_t registered_uuid
;
889 if (session
== NULL
) {
890 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
891 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
895 if (session
->wrapper
!= NULL
) {
896 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
897 response_error
= NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED
;
901 if (payload_length
< sizeof(struct netagent
)) {
902 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%zu < %zu)",
903 payload_length
, sizeof(struct netagent
));
904 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
908 size_t data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
909 if (error
|| data_size
> NETAGENT_MAX_DATA_SIZE
) {
910 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, error %d data_size %zu",
912 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
916 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
917 if (new_wrapper
== NULL
) {
918 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
919 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
923 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
925 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
,
926 &new_wrapper
->netagent
);
928 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
929 FREE(new_wrapper
, M_NETAGENT
);
930 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
934 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
936 error
= netagent_handle_register_inner(session
, new_wrapper
);
938 NETAGENTLOG(LOG_ERR
, "Failed to register agent: %d", error
);
939 FREE(new_wrapper
, M_NETAGENT
);
940 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
944 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
945 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
);
946 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
949 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
, response_error
);
953 netagent_unregister(netagent_session_t _session
)
955 struct netagent_session
*session
= (struct netagent_session
*)_session
;
956 if (session
== NULL
) {
957 NETAGENTLOG0(LOG_ERR
, "Cannot unregister NULL session");
961 netagent_unregister_session_wrapper(session
);
966 netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
967 size_t payload_length
)
969 #pragma unused(payload, payload_length)
970 errno_t response_error
= 0;
972 if (session
== NULL
) {
973 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
974 response_error
= EINVAL
;
978 netagent_unregister_session_wrapper(session
);
981 return response_error
;
985 netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
986 size_t payload_length
, mbuf_t packet
, size_t offset
)
988 #pragma unused(payload_length, packet, offset)
989 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
991 if (session
== NULL
) {
992 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
993 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
997 netagent_unregister_session_wrapper(session
);
999 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
);
1002 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
, response_error
);
1006 netagent_send_cellular_failed_event(struct netagent_wrapper
*wrapper
,
1007 pid_t pid
, uuid_t proc_uuid
)
1009 if (strncmp(wrapper
->netagent
.netagent_domain
, "Cellular", NETAGENT_DOMAINSIZE
) != 0) {
1013 struct kev_netpolicy_ifdenied ev_ifdenied
;
1015 bzero(&ev_ifdenied
, sizeof(ev_ifdenied
));
1017 ev_ifdenied
.ev_data
.epid
= (u_int64_t
)pid
;
1018 uuid_copy(ev_ifdenied
.ev_data
.euuid
, proc_uuid
);
1019 ev_ifdenied
.ev_if_functional_type
= IFRTYPE_FUNCTIONAL_CELLULAR
;
1021 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED
, &ev_ifdenied
.ev_data
, sizeof(ev_ifdenied
));
1025 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
)
1027 errno_t response_error
= 0;
1029 if (agent_changed
== NULL
) {
1030 NETAGENTLOG0(LOG_ERR
, "Invalid argument: agent_changed");
1034 lck_rw_lock_exclusive(&netagent_lock
);
1036 if (session
->wrapper
== NULL
) {
1037 lck_rw_done(&netagent_lock
);
1038 response_error
= ENOENT
;
1039 return response_error
;
1042 if (uuid_compare(session
->wrapper
->netagent
.netagent_uuid
, new_wrapper
->netagent
.netagent_uuid
) != 0 ||
1043 memcmp(&session
->wrapper
->netagent
.netagent_domain
, &new_wrapper
->netagent
.netagent_domain
,
1044 sizeof(new_wrapper
->netagent
.netagent_domain
)) != 0 ||
1045 memcmp(&session
->wrapper
->netagent
.netagent_type
, &new_wrapper
->netagent
.netagent_type
,
1046 sizeof(new_wrapper
->netagent
.netagent_type
)) != 0) {
1047 lck_rw_done(&netagent_lock
);
1048 NETAGENTLOG0(LOG_ERR
, "Basic agent parameters do not match, cannot update");
1049 if (error_domain
== kNetagentErrorDomainPOSIX
) {
1050 response_error
= EINVAL
;
1051 } else if (error_domain
== kNetagentErrorDomainUserDefined
) {
1052 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE
;
1054 return response_error
;
1057 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
1058 if (session
->wrapper
->netagent
.netagent_data_size
== new_wrapper
->netagent
.netagent_data_size
&&
1059 memcmp(&session
->wrapper
->netagent
, &new_wrapper
->netagent
, sizeof(struct netagent
) + data_size
) == 0) {
1060 // Agent is exactly identical, don't increment the generation count
1062 // Make a copy of the list of pending clients, and clear the current list
1063 struct netagent_client_list_s pending_triggers_list_copy
;
1064 LIST_INIT(&pending_triggers_list_copy
);
1065 struct netagent_client
*search_client
= NULL
;
1066 struct netagent_client
*temp_client
= NULL
;
1067 LIST_FOREACH_SAFE(search_client
, &session
->wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
1068 LIST_REMOVE(search_client
, client_chain
);
1069 LIST_INSERT_HEAD(&pending_triggers_list_copy
, search_client
, client_chain
);
1071 lck_rw_done(&netagent_lock
);
1073 // Update pending client triggers without holding a lock
1074 search_client
= NULL
;
1076 LIST_FOREACH_SAFE(search_client
, &pending_triggers_list_copy
, client_chain
, temp_client
) {
1077 necp_force_update_client(search_client
->client_id
, session
->wrapper
->netagent
.netagent_uuid
, session
->wrapper
->generation
);
1078 netagent_send_cellular_failed_event(new_wrapper
, search_client
->client_pid
, search_client
->client_proc_uuid
);
1079 LIST_REMOVE(search_client
, client_chain
);
1080 FREE(search_client
, M_NETAGENT
);
1082 NETAGENTLOG0(LOG_DEBUG
, "Updated agent (no changes)");
1083 *agent_changed
= FALSE
;
1084 return response_error
;
1087 new_wrapper
->generation
= g_next_generation
++;
1088 new_wrapper
->use_count
= session
->wrapper
->use_count
;
1090 if ((new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1091 !(session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1092 netagent_active_count
++;
1093 } else if (!(new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1094 (session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1095 netagent_active_count
> 0) {
1096 netagent_active_count
--;
1099 LIST_REMOVE(session
->wrapper
, master_chain
);
1100 netagent_free_wrapper(session
->wrapper
);
1101 session
->wrapper
= new_wrapper
;
1102 new_wrapper
->control_unit
= session
->control_unit
;
1103 new_wrapper
->event_handler
= session
->event_handler
;
1104 new_wrapper
->event_context
= session
->event_context
;
1105 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
1106 LIST_INIT(&new_wrapper
->pending_triggers_list
);
1108 NETAGENTLOG0(LOG_DEBUG
, "Updated agent");
1109 *agent_changed
= TRUE
;
1111 lck_rw_done(&netagent_lock
);
1113 return response_error
;
1117 netagent_update(netagent_session_t _session
, struct netagent
*agent
)
1119 u_int8_t agent_changed
;
1120 struct netagent_wrapper
*new_wrapper
= NULL
;
1121 bool should_update_immediately
;
1122 uuid_t updated_uuid
;
1124 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1125 if (session
== NULL
) {
1126 NETAGENTLOG0(LOG_ERR
, "Cannot update agent on NULL session");
1130 if (agent
== NULL
) {
1131 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
1135 if (session
->wrapper
== NULL
) {
1136 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1140 size_t data_size
= agent
->netagent_data_size
;
1141 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1142 NETAGENTLOG(LOG_ERR
, "Update message size (%zu > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1146 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1147 if (new_wrapper
== NULL
) {
1148 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1152 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1153 __nochk_memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
1155 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1156 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1158 errno_t error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1160 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1161 if (agent_changed
== FALSE
) {
1162 // The session wrapper does not need the "new_wrapper" as nothing changed
1163 FREE(new_wrapper
, M_NETAGENT
);
1166 FREE(new_wrapper
, M_NETAGENT
);
1174 netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
)
1176 struct netagent_wrapper
*new_wrapper
= NULL
;
1177 errno_t response_error
= 0;
1178 struct netagent
*update_netagent
= (struct netagent
*)(void *)payload
;
1179 u_int8_t agent_changed
;
1180 bool should_update_immediately
;
1181 uuid_t updated_uuid
;
1183 if (session
== NULL
) {
1184 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1185 response_error
= EINVAL
;
1189 if (payload
== NULL
) {
1190 NETAGENTLOG0(LOG_ERR
, "No payload received");
1191 response_error
= EINVAL
;
1195 if (session
->wrapper
== NULL
) {
1196 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1197 response_error
= ENOENT
;
1201 if (payload_length
< sizeof(struct netagent
)) {
1202 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%zu < %zu)",
1203 payload_length
, sizeof(struct netagent
));
1204 response_error
= EINVAL
;
1208 size_t data_size
= update_netagent
->netagent_data_size
;
1209 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1210 NETAGENTLOG(LOG_ERR
, "Update message size (%zu > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1211 response_error
= EINVAL
;
1215 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
1216 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent
) + data_size
), payload_length
);
1217 response_error
= EINVAL
;
1221 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1222 if (new_wrapper
== NULL
) {
1223 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1224 response_error
= ENOMEM
;
1228 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1229 __nochk_memcpy(&new_wrapper
->netagent
, update_netagent
, sizeof(struct netagent
) + data_size
);
1231 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1232 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1234 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1235 if (response_error
== 0) {
1236 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1237 if (agent_changed
== FALSE
) {
1238 // The session wrapper does not need the "new_wrapper" as nothing changed
1239 FREE(new_wrapper
, M_NETAGENT
);
1242 FREE(new_wrapper
, M_NETAGENT
);
1246 return response_error
;
1250 netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
1251 size_t payload_length
, mbuf_t packet
, size_t offset
)
1254 struct netagent_wrapper
*new_wrapper
= NULL
;
1255 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1256 u_int8_t agent_changed
;
1257 uuid_t updated_uuid
;
1258 bool should_update_immediately
;
1260 if (session
== NULL
) {
1261 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1262 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1266 if (session
->wrapper
== NULL
) {
1267 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1268 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1272 if (payload_length
< sizeof(struct netagent
)) {
1273 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%zu < %zu)",
1274 payload_length
, sizeof(struct netagent
));
1275 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1279 size_t data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
1280 if (error
|| data_size
> NETAGENT_MAX_DATA_SIZE
) {
1281 NETAGENTLOG(LOG_ERR
, "Update message size could not be read, error %d data_size %zu",
1283 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1287 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1288 if (new_wrapper
== NULL
) {
1289 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1290 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1294 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1296 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
, &new_wrapper
->netagent
);
1298 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
1299 FREE(new_wrapper
, M_NETAGENT
);
1300 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1304 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1305 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1307 response_error
= (u_int32_t
)netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainUserDefined
);
1308 if (response_error
!= 0) {
1309 FREE(new_wrapper
, M_NETAGENT
);
1313 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
);
1314 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1316 if (agent_changed
== FALSE
) {
1317 // The session wrapper does not need the "new_wrapper" as nothing changed
1318 FREE(new_wrapper
, M_NETAGENT
);
1323 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
, response_error
);
1327 netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
1328 size_t payload_length
, mbuf_t packet
, size_t offset
)
1330 #pragma unused(payload_length, packet, offset)
1331 u_int8_t
*response
= NULL
;
1332 u_int8_t
*cursor
= NULL
;
1333 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1335 if (session
== NULL
) {
1336 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1337 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1341 lck_rw_lock_shared(&netagent_lock
);
1343 if (session
->wrapper
== NULL
) {
1344 lck_rw_done(&netagent_lock
);
1345 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1346 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1350 size_t response_size
= sizeof(struct netagent_message_header
) + sizeof(session
->wrapper
->netagent
)
1351 + session
->wrapper
->netagent
.netagent_data_size
;
1352 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
1353 if (response
== NULL
) {
1358 cursor
= netagent_buffer_write_message_header(cursor
, NETAGENT_MESSAGE_TYPE_GET
,
1359 NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0,
1360 response_size
- sizeof(struct netagent_message_header
));
1361 memcpy(cursor
, &session
->wrapper
->netagent
, sizeof(session
->wrapper
->netagent
) +
1362 session
->wrapper
->netagent
.netagent_data_size
);
1364 lck_rw_done(&netagent_lock
);
1366 if (!netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
)) {
1367 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
1369 FREE(response
, M_NETAGENT
);
1372 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_GET
, message_id
, response_error
);
1376 netagent_assign_nexus(netagent_session_t _session
, uuid_t necp_client_uuid
,
1377 void *assign_message
, size_t assigned_results_length
)
1379 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1380 uuid_t netagent_uuid
;
1381 if (session
== NULL
) {
1382 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1386 lck_rw_lock_shared(&netagent_lock
);
1387 if (session
->wrapper
== NULL
) {
1388 lck_rw_done(&netagent_lock
);
1389 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1392 uuid_copy(netagent_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
1393 lck_rw_done(&netagent_lock
);
1395 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1396 int error
= necp_assign_client_result(netagent_uuid
, necp_client_uuid
, assign_message
, assigned_results_length
);
1398 // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1399 NETAGENTLOG((error
== ENOENT
? LOG_DEBUG
: LOG_ERR
), "Client assignment failed: %d", error
);
1403 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1408 netagent_update_flow_protoctl_event(netagent_session_t _session
,
1409 uuid_t client_id
, uint32_t protoctl_event_code
,
1410 uint32_t protoctl_event_val
, uint32_t protoctl_event_tcp_seq_number
)
1412 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1413 uuid_t netagent_uuid
;
1416 if (session
== NULL
) {
1417 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1421 lck_rw_lock_shared(&netagent_lock
);
1422 if (session
->wrapper
== NULL
) {
1423 lck_rw_done(&netagent_lock
);
1424 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1427 uuid_copy(netagent_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
1428 lck_rw_done(&netagent_lock
);
1430 error
= necp_update_flow_protoctl_event(netagent_uuid
,
1431 client_id
, protoctl_event_code
, protoctl_event_val
, protoctl_event_tcp_seq_number
);
1437 netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
1438 size_t payload_length
)
1440 errno_t response_error
= 0;
1441 struct netagent_assign_nexus_message
*assign_nexus_netagent
= (struct netagent_assign_nexus_message
*)(void *)payload
;
1443 uuid_t netagent_uuid
;
1444 u_int8_t
*assigned_results
= NULL
;
1446 if (session
== NULL
) {
1447 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1448 response_error
= ENOENT
;
1452 if (payload
== NULL
) {
1453 NETAGENTLOG0(LOG_ERR
, "No payload received");
1454 response_error
= EINVAL
;
1458 lck_rw_lock_shared(&netagent_lock
);
1459 if (session
->wrapper
== NULL
) {
1460 lck_rw_done(&netagent_lock
);
1461 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1462 response_error
= ENOENT
;
1466 uuid_copy(netagent_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
1467 lck_rw_done(&netagent_lock
);
1469 if (payload_length
< sizeof(uuid_t
)) {
1470 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1471 response_error
= EINVAL
;
1475 memcpy(client_id
, assign_nexus_netagent
->assign_client_id
, sizeof(client_id
));
1476 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1478 if (assigned_results_length
> 0) {
1479 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1480 if (assigned_results
== NULL
) {
1481 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1482 response_error
= ENOMEM
;
1485 memcpy(assigned_results
, assign_nexus_netagent
->assign_necp_results
, assigned_results_length
);
1488 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1489 response_error
= necp_assign_client_result(netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1490 if (response_error
) {
1491 // necp_assign_client_result returns POSIX errors
1492 if (assigned_results
) {
1493 FREE(assigned_results
, M_NETAGENT
);
1495 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", response_error
);
1499 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1501 return response_error
;
1506 netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
1507 size_t payload_length
, mbuf_t packet
, size_t offset
)
1510 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1512 uuid_t netagent_uuid
;
1513 u_int8_t
*assigned_results
= NULL
;
1515 if (session
== NULL
) {
1516 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1517 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1521 lck_rw_lock_shared(&netagent_lock
);
1522 if (session
->wrapper
== NULL
) {
1523 lck_rw_done(&netagent_lock
);
1524 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1525 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1528 uuid_copy(netagent_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
1529 lck_rw_done(&netagent_lock
);
1531 if (payload_length
< sizeof(uuid_t
)) {
1532 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1533 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1537 error
= mbuf_copydata(packet
, offset
, sizeof(client_id
), &client_id
);
1539 NETAGENTLOG(LOG_ERR
, "Failed to read uuid for assign message: %d", error
);
1540 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1544 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1545 if (assigned_results_length
> 0) {
1546 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1547 if (assigned_results
== NULL
) {
1548 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1549 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1553 error
= mbuf_copydata(packet
, offset
+ sizeof(client_id
), assigned_results_length
, assigned_results
);
1555 FREE(assigned_results
, M_NETAGENT
);
1556 NETAGENTLOG(LOG_ERR
, "Failed to read assign message: %d", error
);
1557 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1562 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1563 error
= necp_assign_client_result(netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1565 if (assigned_results
) {
1566 FREE(assigned_results
, M_NETAGENT
);
1568 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", error
);
1569 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN
;
1573 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1574 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
);
1577 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
, response_error
);
1581 netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
)
1583 errno_t response_error
= 0;
1584 uint64_t use_count
= 0;
1586 if (session
== NULL
) {
1587 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1588 response_error
= ENOENT
;
1592 if (payload
== NULL
) {
1593 NETAGENTLOG0(LOG_ERR
, "No payload received");
1594 response_error
= EINVAL
;
1598 if (payload_length
!= sizeof(use_count
)) {
1599 NETAGENTLOG(LOG_ERR
, "Payload length is invalid (%lu)", payload_length
);
1600 response_error
= EINVAL
;
1604 memcpy(&use_count
, payload
, sizeof(use_count
));
1606 lck_rw_lock_shared(&netagent_lock
);
1608 if (session
->wrapper
== NULL
) {
1609 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1610 response_error
= ENOENT
;
1611 lck_rw_done(&netagent_lock
);
1615 session
->wrapper
->use_count
= use_count
;
1617 lck_rw_done(&netagent_lock
);
1620 return response_error
;
1624 netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
)
1626 errno_t response_error
= 0;
1627 uint64_t use_count
= 0;
1629 if (session
== NULL
) {
1630 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1631 response_error
= ENOENT
;
1635 if (buffer
== NULL
) {
1636 NETAGENTLOG0(LOG_ERR
, "No payload received");
1637 response_error
= EINVAL
;
1641 if (*buffer_length
!= sizeof(use_count
)) {
1642 NETAGENTLOG(LOG_ERR
, "Buffer length is invalid (%lu)", *buffer_length
);
1643 response_error
= EINVAL
;
1647 lck_rw_lock_shared(&netagent_lock
);
1649 if (session
->wrapper
== NULL
) {
1650 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1651 response_error
= ENOENT
;
1652 lck_rw_done(&netagent_lock
);
1656 use_count
= session
->wrapper
->use_count
;
1657 lck_rw_done(&netagent_lock
);
1659 memcpy(buffer
, &use_count
, sizeof(use_count
));
1660 *buffer_length
= sizeof(use_count
);
1663 return response_error
;
1666 static struct netagent_wrapper
*
1667 netagent_find_agent_with_uuid(uuid_t uuid
)
1669 struct netagent_wrapper
*search_netagent
= NULL
;
1671 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1672 if (uuid_compare(search_netagent
->netagent
.netagent_uuid
, uuid
) == 0) {
1673 return search_netagent
;
1681 netagent_post_updated_interfaces(uuid_t uuid
)
1683 struct netagent_wrapper
*wrapper
= NULL
;
1684 lck_rw_lock_shared(&netagent_lock
);
1685 wrapper
= netagent_find_agent_with_uuid(uuid
);
1686 lck_rw_done(&netagent_lock
);
1688 if (wrapper
!= NULL
) {
1689 netagent_post_event(uuid
, KEV_NETAGENT_UPDATED_INTERFACES
, TRUE
, false);
1691 NETAGENTLOG0(LOG_DEBUG
, "Interface event with no associated agent");
1698 netagent_dump_get_data_size_locked()
1700 struct netagent_wrapper
*search_netagent
= NULL
;
1701 u_int32_t total_netagent_data_size
= 0;
1702 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1703 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1704 total_netagent_data_size
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1706 return total_netagent_data_size
;
1710 netagent_dump_copy_data_locked(u_int8_t
*buffer
, u_int32_t buffer_length
)
1712 size_t response_size
= 0;
1713 u_int8_t
*cursor
= NULL
;
1714 struct netagent_wrapper
*search_netagent
= NULL
;
1716 response_size
= buffer_length
; // We already know that buffer_length is the same as total_netagent_data_size.
1718 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1719 memcpy(cursor
, search_netagent
->netagent
.netagent_uuid
, sizeof(search_netagent
->netagent
.netagent_uuid
));
1720 cursor
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1725 netagent_ioctl(u_long cmd
, caddr_t data
)
1730 case SIOCGIFAGENTLIST32
:
1731 case SIOCGIFAGENTLIST64
: {
1732 /* Check entitlement if the client requests agent dump */
1733 errno_t cred_result
= priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES
, 0);
1734 if (cred_result
!= 0) {
1735 NETAGENTLOG0(LOG_ERR
, "Client does not hold the necessary entitlement to get netagent information");
1744 lck_rw_lock_shared(&netagent_lock
);
1746 case SIOCGIFAGENTDATA32
: {
1747 struct netagent_req32
*ifsir32
= (struct netagent_req32
*)(void *)data
;
1748 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir32
->netagent_uuid
);
1749 if (wrapper
== NULL
) {
1753 uuid_copy(ifsir32
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1754 memcpy(ifsir32
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir32
->netagent_domain
));
1755 memcpy(ifsir32
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir32
->netagent_type
));
1756 memcpy(ifsir32
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir32
->netagent_desc
));
1757 ifsir32
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1758 if (ifsir32
->netagent_data_size
== 0) {
1759 // First pass, client wants data size
1760 ifsir32
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1761 } else if (ifsir32
->netagent_data
!= USER_ADDR_NULL
&&
1762 ifsir32
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1763 // Second pass, client wants data buffer filled out
1764 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir32
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1770 case SIOCGIFAGENTDATA64
: {
1771 struct netagent_req64
*ifsir64
= (struct netagent_req64
*)(void *)data
;
1772 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir64
->netagent_uuid
);
1773 if (wrapper
== NULL
) {
1777 uuid_copy(ifsir64
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1778 memcpy(ifsir64
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir64
->netagent_domain
));
1779 memcpy(ifsir64
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir64
->netagent_type
));
1780 memcpy(ifsir64
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir64
->netagent_desc
));
1781 ifsir64
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1782 if (ifsir64
->netagent_data_size
== 0) {
1783 // First pass, client wants data size
1784 ifsir64
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1785 } else if (ifsir64
->netagent_data
!= USER_ADDR_NULL
&&
1786 ifsir64
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1787 // Second pass, client wants data buffer filled out
1788 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir64
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1794 case SIOCGIFAGENTLIST32
: {
1795 struct netagentlist_req32
*ifsir32
= (struct netagentlist_req32
*)(void *)data
;
1796 if (ifsir32
->data_size
== 0) {
1797 // First pass, client wants data size
1798 ifsir32
->data_size
= netagent_dump_get_data_size_locked();
1799 } else if (ifsir32
->data
!= USER_ADDR_NULL
&&
1800 ifsir32
->data_size
> 0 &&
1801 ifsir32
->data_size
== netagent_dump_get_data_size_locked()) {
1802 // Second pass, client wants data buffer filled out
1803 u_int8_t
*response
= NULL
;
1804 MALLOC(response
, u_int8_t
*, ifsir32
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1805 if (response
== NULL
) {
1810 netagent_dump_copy_data_locked(response
, ifsir32
->data_size
);
1811 error
= copyout(response
, ifsir32
->data
, ifsir32
->data_size
);
1812 FREE(response
, M_NETAGENT
);
1818 case SIOCGIFAGENTLIST64
: {
1819 struct netagentlist_req64
*ifsir64
= (struct netagentlist_req64
*)(void *)data
;
1820 if (ifsir64
->data_size
== 0) {
1821 // First pass, client wants data size
1822 ifsir64
->data_size
= netagent_dump_get_data_size_locked();
1823 } else if (ifsir64
->data
!= USER_ADDR_NULL
&&
1824 ifsir64
->data_size
> 0 &&
1825 ifsir64
->data_size
== netagent_dump_get_data_size_locked()) {
1826 // Second pass, client wants data buffer filled out
1827 u_int8_t
*response
= NULL
;
1828 MALLOC(response
, u_int8_t
*, ifsir64
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1829 if (response
== NULL
) {
1834 netagent_dump_copy_data_locked(response
, ifsir64
->data_size
);
1835 error
= copyout(response
, ifsir64
->data
, ifsir64
->data_size
);
1836 FREE(response
, M_NETAGENT
);
1847 lck_rw_done(&netagent_lock
);
1852 netagent_get_flags(uuid_t uuid
)
1854 u_int32_t flags
= 0;
1855 lck_rw_lock_shared(&netagent_lock
);
1856 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1857 if (wrapper
!= NULL
) {
1858 flags
= wrapper
->netagent
.netagent_flags
;
1860 NETAGENTLOG0(LOG_DEBUG
, "Flags requested for invalid netagent");
1862 lck_rw_done(&netagent_lock
);
1868 netagent_set_flags(uuid_t uuid
, u_int32_t flags
)
1871 lck_rw_lock_exclusive(&netagent_lock
);
1872 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1873 if (wrapper
!= NULL
) {
1874 wrapper
->netagent
.netagent_flags
= flags
;
1876 NETAGENTLOG0(LOG_DEBUG
,
1877 "Attempt to set flags for invalid netagent");
1880 lck_rw_done(&netagent_lock
);
1886 netagent_get_generation(uuid_t uuid
)
1888 u_int32_t generation
= 0;
1889 lck_rw_lock_shared(&netagent_lock
);
1890 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1891 if (wrapper
!= NULL
) {
1892 generation
= wrapper
->generation
;
1894 NETAGENTLOG0(LOG_DEBUG
, "Generation requested for invalid netagent");
1896 lck_rw_done(&netagent_lock
);
1902 netagent_get_agent_domain_and_type(uuid_t uuid
, char *domain
, char *type
)
1905 if (domain
== NULL
|| type
== NULL
) {
1906 NETAGENTLOG(LOG_ERR
, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain
, type
);
1910 lck_rw_lock_shared(&netagent_lock
);
1911 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1912 if (wrapper
!= NULL
) {
1914 memcpy(domain
, wrapper
->netagent
.netagent_domain
, NETAGENT_DOMAINSIZE
);
1915 memcpy(type
, wrapper
->netagent
.netagent_type
, NETAGENT_TYPESIZE
);
1917 NETAGENTLOG0(LOG_ERR
, "Type requested for invalid netagent");
1919 lck_rw_done(&netagent_lock
);
1925 netagent_kernel_trigger(uuid_t uuid
)
1929 lck_rw_lock_shared(&netagent_lock
);
1930 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1931 if (wrapper
== NULL
) {
1932 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger could not be found");
1937 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_KERNEL_ACTIVATED
) == 0) {
1938 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger is not kernel activated");
1939 // Agent does not accept kernel triggers
1944 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1945 // Agent already active
1946 NETAGENTLOG0(LOG_INFO
, "Requested netagent for kernel trigger is already active");
1951 error
= netagent_send_trigger(wrapper
, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
1952 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent from kernel (error %d)", error
);
1954 lck_rw_done(&netagent_lock
);
1959 netagent_client_message_with_params(uuid_t agent_uuid
,
1960 uuid_t necp_client_uuid
,
1963 u_int8_t message_type
,
1964 struct necp_client_agent_parameters
*parameters
,
1965 void **assigned_results
,
1966 size_t *assigned_results_length
)
1970 if (message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
&&
1971 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT
&&
1972 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT
&&
1973 message_type
!= NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
&&
1974 message_type
!= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
&&
1975 message_type
!= NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1976 NETAGENTLOG(LOG_ERR
, "Client netagent message type (%d) is invalid", message_type
);
1980 lck_rw_lock_shared(&netagent_lock
);
1981 bool should_unlock
= TRUE
;
1982 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1983 if (wrapper
== NULL
) {
1984 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
1989 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1990 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
1991 // Agent does not accept user triggers
1992 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1996 pid_t report_pid
= 0;
1997 uuid_t report_proc_uuid
= {};
1998 if (parameters
!= NULL
) {
1999 report_pid
= parameters
->u
.nexus_request
.epid
;
2000 uuid_copy(report_proc_uuid
, parameters
->u
.nexus_request
.euuid
);
2002 struct proc
*p
= current_proc();
2004 report_pid
= proc_pid(p
);
2005 proc_getexecutableuuid(p
, report_proc_uuid
, sizeof(report_proc_uuid
));
2008 netagent_send_cellular_failed_event(wrapper
, report_pid
, report_proc_uuid
);
2011 } else if (message_type
== NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
||
2012 message_type
== NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
||
2013 message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
2014 bool is_nexus_agent
= ((wrapper
->netagent
.netagent_flags
&
2015 (NETAGENT_FLAG_NEXUS_PROVIDER
|
2016 NETAGENT_FLAG_NEXUS_LISTENER
|
2017 NETAGENT_FLAG_CUSTOM_IP_NEXUS
|
2018 NETAGENT_FLAG_CUSTOM_ETHER_NEXUS
|
2019 NETAGENT_FLAG_INTERPOSE_NEXUS
)) != 0);
2020 if (!is_nexus_agent
) {
2021 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance is not a nexus provider");
2022 // Agent is not a nexus provider
2027 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) == 0) {
2029 NETAGENTLOG0(LOG_INFO
, "Requested netagent for nexus instance is not active");
2035 if (wrapper
->control_unit
== 0) {
2036 if (wrapper
->event_handler
== NULL
) {
2037 // No event handler registered for kernel agent
2040 // We hold the shared lock during the event handler callout, so it is expected
2041 // that the event handler will not lead to any registrations or unregistrations
2042 // of network agents.
2043 error
= wrapper
->event_handler(message_type
, necp_client_uuid
, pid
, handle
,
2044 wrapper
->event_context
, parameters
,
2045 assigned_results
, assigned_results_length
);
2047 VERIFY(assigned_results
== NULL
|| *assigned_results
== NULL
);
2048 VERIFY(assigned_results_length
== NULL
|| *assigned_results_length
== 0);
2052 // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2053 if (message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
2054 message_type
= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
;
2057 error
= netagent_send_client_message(wrapper
, necp_client_uuid
, message_type
);
2058 if (error
== 0 && message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
2059 if (lck_rw_lock_shared_to_exclusive(&netagent_lock
)) {
2060 // Grab the lock exclusively to add a pending client to the list
2061 struct netagent_client
*new_pending_client
= NULL
;
2062 MALLOC(new_pending_client
, struct netagent_client
*, sizeof(*new_pending_client
), M_NETAGENT
, M_WAITOK
);
2063 if (new_pending_client
== NULL
) {
2064 NETAGENTLOG0(LOG_ERR
, "Failed to allocate client for trigger");
2066 uuid_copy(new_pending_client
->client_id
, necp_client_uuid
);
2067 if (parameters
!= NULL
) {
2068 new_pending_client
->client_pid
= parameters
->u
.nexus_request
.epid
;
2069 uuid_copy(new_pending_client
->client_proc_uuid
, parameters
->u
.nexus_request
.euuid
);
2071 struct proc
*p
= current_proc();
2073 new_pending_client
->client_pid
= proc_pid(p
);
2074 proc_getexecutableuuid(p
, new_pending_client
->client_proc_uuid
, sizeof(new_pending_client
->client_proc_uuid
));
2077 LIST_INSERT_HEAD(&wrapper
->pending_triggers_list
, new_pending_client
, client_chain
);
2080 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2081 should_unlock
= FALSE
;
2085 NETAGENTLOG(((error
&& error
!= ENOENT
) ? LOG_ERR
: LOG_INFO
), "Send message %d for client (error %d)", message_type
, error
);
2086 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
2087 uuid_string_t uuid_str
;
2088 uuid_unparse(agent_uuid
, uuid_str
);
2089 NETAGENTLOG(LOG_NOTICE
, "Triggered network agent %s, error = %d", uuid_str
, error
);
2092 if (should_unlock
) {
2093 lck_rw_done(&netagent_lock
);
2099 netagent_client_message(uuid_t agent_uuid
, uuid_t necp_client_uuid
, pid_t pid
, void *handle
, u_int8_t message_type
)
2101 return netagent_client_message_with_params(agent_uuid
, necp_client_uuid
, pid
, handle
, message_type
, NULL
, NULL
, NULL
);
2105 netagent_use(uuid_t agent_uuid
, uint64_t *out_use_count
)
2109 lck_rw_lock_exclusive(&netagent_lock
);
2110 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2111 if (wrapper
== NULL
) {
2112 NETAGENTLOG0(LOG_ERR
, "netagent_assert: Requested netagent UUID is not registered");
2117 uint64_t current_count
= wrapper
->use_count
;
2118 wrapper
->use_count
++;
2120 if (out_use_count
!= NULL
) {
2121 *out_use_count
= current_count
;
2125 lck_rw_done(&netagent_lock
);
2130 netagent_copyout(uuid_t agent_uuid
, user_addr_t user_addr
, u_int32_t user_size
)
2134 lck_rw_lock_shared(&netagent_lock
);
2135 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2136 if (wrapper
== NULL
) {
2137 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
2142 u_int32_t total_size
= (sizeof(struct netagent
) + wrapper
->netagent
.netagent_data_size
);
2143 if (user_size
< total_size
) {
2144 NETAGENTLOG(LOG_ERR
, "Provided user buffer is too small (%u < %u)", user_size
, total_size
);
2149 error
= copyout(&wrapper
->netagent
, user_addr
, total_size
);
2151 NETAGENTLOG((error
? LOG_ERR
: LOG_DEBUG
), "Copied agent content (error %d)", error
);
2153 lck_rw_done(&netagent_lock
);
2158 netagent_trigger(struct proc
*p
, struct netagent_trigger_args
*uap
, int32_t *retval
)
2160 #pragma unused(p, retval)
2161 uuid_t agent_uuid
= {};
2165 NETAGENTLOG0(LOG_ERR
, "uap == NULL");
2169 if (uap
->agent_uuid
) {
2170 if (uap
->agent_uuidlen
!= sizeof(uuid_t
)) {
2171 NETAGENTLOG(LOG_ERR
, "Incorrect length (got %zu, expected %lu)",
2172 (size_t)uap
->agent_uuidlen
, sizeof(uuid_t
));
2176 error
= copyin(uap
->agent_uuid
, agent_uuid
, sizeof(uuid_t
));
2178 NETAGENTLOG(LOG_ERR
, "copyin error (%d)", error
);
2183 if (uuid_is_null(agent_uuid
)) {
2184 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is empty");
2188 lck_rw_lock_shared(&netagent_lock
);
2189 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2190 if (wrapper
== NULL
) {
2191 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not registered");
2196 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
2197 // Agent does not accept triggers
2198 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not eligible for triggering");
2203 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
2204 // Agent already active
2205 NETAGENTLOG0(LOG_INFO
, "Requested netagent UUID is already active");
2210 error
= netagent_send_trigger(wrapper
, p
, NETAGENT_TRIGGER_FLAG_USER
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
2211 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent (error %d)", error
);
2213 lck_rw_done(&netagent_lock
);