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 <libkern/OSMalloc.h>
36 #include <sys/kernel.h>
37 #include <sys/kern_control.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/sysctl.h>
42 #include <sys/kern_event.h>
43 #include <sys/sysproto.h>
44 #include <net/network_agent.h>
45 #include <net/if_var.h>
49 u_int32_t netagent_debug
= LOG_NOTICE
; // 0=None, 1=Basic
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, "");
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, "");
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, "");
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__); \
67 os_log(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
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); \
77 os_log(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
82 struct netagent_client
{
83 LIST_ENTRY(netagent_client
) client_chain
;
85 uuid_t client_proc_uuid
;
89 LIST_HEAD(netagent_client_list_s
, netagent_client
);
91 struct netagent_wrapper
{
92 LIST_ENTRY(netagent_wrapper
) master_chain
;
93 u_int32_t control_unit
;
94 netagent_event_f event_handler
;
98 struct netagent_client_list_s pending_triggers_list
;
99 struct netagent netagent
;
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
;
110 kNetagentErrorDomainPOSIX
= 0,
111 kNetagentErrorDomainUserDefined
= 1,
112 } netagent_error_domain_t
;
114 static LIST_HEAD(_netagent_list
, netagent_wrapper
) master_netagent_list
;
116 // Protected by netagent_lock
117 static u_int32_t g_next_generation
= 1;
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
);
127 static errno_t
netagent_register_control(void);
128 static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
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
);
139 static int netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
);
141 static struct netagent_session
*netagent_create_session(u_int32_t control_unit
);
142 static void netagent_delete_session(struct netagent_session
*session
);
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
);
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
);
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
);
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
);
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
);
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
);
175 static struct netagent_wrapper
*netagent_find_agent_with_uuid(uuid_t uuid
);
182 result
= netagent_register_control();
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");
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");
201 netagent_mtx_attr
= lck_attr_alloc_init();
202 if (netagent_mtx_attr
== NULL
) {
203 NETAGENTLOG0(LOG_ERR
, "lck_attr_alloc_init failed");
208 lck_rw_init(&netagent_lock
, netagent_mtx_grp
, netagent_mtx_attr
);
210 LIST_INIT(&master_netagent_list
);
214 if (netagent_mtx_attr
!= NULL
) {
215 lck_attr_free(netagent_mtx_attr
);
216 netagent_mtx_attr
= NULL
;
218 if (netagent_mtx_grp
!= NULL
) {
219 lck_grp_free(netagent_mtx_grp
);
220 netagent_mtx_grp
= NULL
;
222 if (netagent_grp_attr
!= NULL
) {
223 lck_grp_attr_free(netagent_grp_attr
);
224 netagent_grp_attr
= NULL
;
226 if (netagent_kctlref
!= NULL
) {
227 ctl_deregister(netagent_kctlref
);
228 netagent_kctlref
= NULL
;
235 netagent_register_control(void)
237 struct kern_ctl_reg kern_ctl
;
240 // Create a tag to allocate memory
241 netagent_malloc_tag
= OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME
, OSMT_DEFAULT
);
243 // Find a unique value for our interface family
244 result
= mbuf_tag_id_find(NETAGENT_CONTROL_NAME
, &netagent_family
);
246 NETAGENTLOG(LOG_ERR
, "mbuf_tag_id_find_internal failed: %d", result
);
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
;
263 result
= ctl_register(&kern_ctl
, &netagent_kctlref
);
265 NETAGENTLOG(LOG_ERR
, "ctl_register failed: %d", result
);
273 netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
, void **unitinfo
)
275 #pragma unused(kctlref)
276 *unitinfo
= netagent_create_session(sac
->sc_unit
);
277 if (*unitinfo
== NULL
) {
278 // Could not allocate session
286 netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
)
288 #pragma unused(kctlref, unit)
289 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
290 if (session
!= NULL
) {
291 netagent_delete_session(session
);
299 netagent_post_event(uuid_t agent_uuid
, u_int32_t event_code
, bool update_necp
, bool should_update_immediately
)
302 necp_update_all_clients_immediately_if_needed(should_update_immediately
);
305 struct kev_msg ev_msg
;
306 memset(&ev_msg
, 0, sizeof(ev_msg
));
308 struct kev_netagent_data event_data
;
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
;
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
);
319 kev_post_msg(&ev_msg
);
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
)
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
);
336 netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
)
338 if (netagent_kctlref
== NULL
|| control_unit
== 0 || buffer
== NULL
|| buffer_size
== 0) {
342 return ctl_enqueuedata(netagent_kctlref
, control_unit
, buffer
, buffer_size
, CTL_DATA_EOR
);
346 netagent_send_trigger(struct netagent_wrapper
*wrapper
, struct proc
*p
, u_int32_t flags
, u_int32_t trigger_type
)
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
);
353 MALLOC(trigger
, u_int8_t
*, trigger_size
, M_NETAGENT
, M_WAITOK
);
354 if (trigger
== NULL
) {
358 (void)netagent_buffer_write_message_header(trigger
, trigger_type
, 0, 0, 0, sizeof(struct netagent_trigger_message
));
360 trigger_message
= (struct netagent_trigger_message
*)(void *)(trigger
+ sizeof(struct netagent_message_header
));
361 trigger_message
->trigger_flags
= flags
;
363 trigger_message
->trigger_pid
= proc_pid(p
);
364 proc_getexecutableuuid(p
, trigger_message
->trigger_proc_uuid
, sizeof(trigger_message
->trigger_proc_uuid
));
366 trigger_message
->trigger_pid
= 0;
367 uuid_clear(trigger_message
->trigger_proc_uuid
);
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
);
374 FREE(trigger
, M_NETAGENT
);
379 netagent_send_client_message(struct netagent_wrapper
*wrapper
, uuid_t client_id
, u_int8_t message_type
)
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
);
386 MALLOC(message
, u_int8_t
*, message_size
, M_NETAGENT
, M_WAITOK
);
387 if (message
== NULL
) {
391 (void)netagent_buffer_write_message_header(message
, message_type
, 0, 0, 0, sizeof(struct netagent_client_message
));
393 client_message
= (struct netagent_client_message
*)(void *)(message
+ sizeof(struct netagent_message_header
));
394 uuid_copy(client_message
->client_id
, client_id
);
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
);
400 FREE(message
, M_NETAGENT
);
405 netagent_send_success_response(struct netagent_session
*session
, u_int8_t message_type
, u_int32_t message_id
)
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
) {
414 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0, 0);
416 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
417 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
420 FREE(response
, M_NETAGENT
);
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
)
429 u_int8_t
*response
= NULL
;
430 size_t response_size
= sizeof(struct netagent_message_header
);
432 if (session
== NULL
) {
433 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
437 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
438 if (response
== NULL
) {
441 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
,
442 message_id
, error_code
, 0);
444 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
445 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
448 FREE(response
, M_NETAGENT
);
453 netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, mbuf_t packet
, int flags
)
455 #pragma unused(kctlref, unit, flags)
456 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
457 struct netagent_message_header header
;
460 if (session
== NULL
) {
461 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
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
));
473 error
= mbuf_copydata(packet
, 0, sizeof(header
), &header
);
475 NETAGENTLOG(LOG_ERR
, "mbuf_copydata failed for the header: %d", error
);
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
));
486 case NETAGENT_MESSAGE_TYPE_UNREGISTER
: {
487 netagent_handle_unregister_message(session
, header
.message_id
, header
.message_payload_length
,
488 packet
, sizeof(header
));
491 case NETAGENT_MESSAGE_TYPE_UPDATE
: {
492 netagent_handle_update_message(session
, header
.message_id
, header
.message_payload_length
,
493 packet
, sizeof(header
));
496 case NETAGENT_MESSAGE_TYPE_GET
: {
497 netagent_handle_get(session
, header
.message_id
, header
.message_payload_length
,
498 packet
, sizeof(header
));
501 case NETAGENT_MESSAGE_TYPE_ASSERT
: {
502 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
505 case NETAGENT_MESSAGE_TYPE_UNASSERT
: {
506 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
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
));
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
);
528 netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
530 #pragma unused(kctlref, unit, unitinfo, flags)
535 netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
536 void *data
, size_t *len
)
538 #pragma unused(kctlref, unit)
539 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
542 if (session
== NULL
) {
543 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
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
);
555 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
565 netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
566 void *data
, size_t len
)
568 #pragma unused(kctlref, unit)
569 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
572 if (session
== NULL
) {
573 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
579 case NETAGENT_OPTION_TYPE_REGISTER
: {
580 NETAGENTLOG0(LOG_DEBUG
, "Request for registration");
581 error
= netagent_handle_register_setopt(session
, data
, len
);
584 case NETAGENT_OPTION_TYPE_UPDATE
: {
585 NETAGENTLOG0(LOG_DEBUG
, "Request for update");
586 error
= netagent_handle_update_setopt(session
, data
, len
);
589 case NETAGENT_OPTION_TYPE_UNREGISTER
: {
590 NETAGENTLOG0(LOG_DEBUG
, "Request for unregistration");
591 error
= netagent_handle_unregister_setopt(session
, data
, len
);
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
);
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
);
605 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
614 // Session Management
615 static struct netagent_session
*
616 netagent_create_session(u_int32_t control_unit
)
618 struct netagent_session
*new_session
= NULL
;
620 MALLOC(new_session
, struct netagent_session
*, sizeof(*new_session
), M_NETAGENT
, M_WAITOK
);
621 if (new_session
== NULL
) {
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
;
633 netagent_create(netagent_event_f event_handler
, void *context
)
635 struct netagent_session
*session
= netagent_create_session(0);
636 if (session
== NULL
) {
640 session
->event_handler
= event_handler
;
641 session
->event_context
= context
;
646 netagent_free_wrapper(struct netagent_wrapper
*wrapper
)
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
);
656 // Free wrapper itself
657 FREE(wrapper
, M_NETAGENT
);
661 netagent_unregister_session_wrapper(struct netagent_session
*session
)
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
--;
673 if ((session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
674 netagent_active_count
> 0) {
675 netagent_active_count
--;
678 LIST_REMOVE(wrapper
, master_chain
);
681 uuid_copy(unregistered_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
683 netagent_free_wrapper(session
->wrapper
);
684 session
->wrapper
= NULL
;
685 NETAGENTLOG0(LOG_DEBUG
, "Unregistered agent");
688 lck_rw_done(&netagent_lock
);
691 ifnet_clear_netagent(unregistered_uuid
);
692 netagent_post_event(unregistered_uuid
, KEV_NETAGENT_UNREGISTERED
, TRUE
, false);
697 netagent_delete_session(struct netagent_session
*session
)
699 if (session
!= NULL
) {
700 netagent_unregister_session_wrapper(session
);
701 FREE(session
, M_NETAGENT
);
706 netagent_destroy(netagent_session_t session
)
708 return netagent_delete_session((struct netagent_session
*)session
);
712 netagent_packet_get_netagent_data_size(mbuf_t packet
, int offset
, int *err
)
716 struct netagent netagent_peek
;
717 memset(&netagent_peek
, 0, sizeof(netagent_peek
));
721 error
= mbuf_copydata(packet
, offset
, sizeof(netagent_peek
), &netagent_peek
);
727 return netagent_peek
.netagent_data_size
;
731 netagent_handle_register_inner(struct netagent_session
*session
, struct netagent_wrapper
*new_wrapper
)
733 lck_rw_lock_exclusive(&netagent_lock
);
735 if (session
->wrapper
!= NULL
) {
736 lck_rw_done(&netagent_lock
);
740 new_wrapper
->control_unit
= session
->control_unit
;
741 new_wrapper
->event_handler
= session
->event_handler
;
742 new_wrapper
->event_context
= session
->event_context
;
743 new_wrapper
->generation
= g_next_generation
++;
745 session
->wrapper
= new_wrapper
;
746 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
747 LIST_INIT(&new_wrapper
->pending_triggers_list
);
749 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
750 netagent_registered_count
++;
751 if (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) {
752 netagent_active_count
++;
755 lck_rw_done(&netagent_lock
);
761 netagent_register(netagent_session_t _session
, struct netagent
*agent
)
764 struct netagent_wrapper
*new_wrapper
= NULL
;
765 uuid_t registered_uuid
;
767 struct netagent_session
*session
= (struct netagent_session
*)_session
;
768 if (session
== NULL
) {
769 NETAGENTLOG0(LOG_ERR
, "Cannot register agent on NULL session");
774 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
778 if (session
->wrapper
!= NULL
) {
779 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
783 data_size
= agent
->netagent_data_size
;
784 if (data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
785 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %d",
790 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
791 if (new_wrapper
== NULL
) {
792 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
796 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
797 __nochk_memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
799 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
801 int error
= netagent_handle_register_inner(session
, new_wrapper
);
803 FREE(new_wrapper
, M_NETAGENT
);
807 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
808 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
814 netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
815 u_int32_t payload_length
)
818 struct netagent_wrapper
*new_wrapper
= NULL
;
819 u_int32_t response_error
= 0;
820 struct netagent
*register_netagent
= (struct netagent
*)(void *)payload
;
821 uuid_t registered_uuid
;
823 if (session
== NULL
) {
824 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
825 response_error
= EINVAL
;
829 if (payload
== NULL
) {
830 NETAGENTLOG0(LOG_ERR
, "No payload received");
831 response_error
= EINVAL
;
835 if (session
->wrapper
!= NULL
) {
836 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
837 response_error
= EINVAL
;
841 if (payload_length
< sizeof(struct netagent
)) {
842 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%u < %lu)",
843 payload_length
, sizeof(struct netagent
));
844 response_error
= EINVAL
;
848 data_size
= register_netagent
->netagent_data_size
;
849 if (data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
850 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %d", data_size
);
851 response_error
= EINVAL
;
855 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
856 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
857 response_error
= EINVAL
;
861 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
862 if (new_wrapper
== NULL
) {
863 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
864 response_error
= ENOMEM
;
868 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
869 __nochk_memcpy(&new_wrapper
->netagent
, register_netagent
, sizeof(struct netagent
) + data_size
);
871 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
873 response_error
= netagent_handle_register_inner(session
, new_wrapper
);
874 if (response_error
!= 0) {
875 FREE(new_wrapper
, M_NETAGENT
);
879 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
880 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
883 return response_error
;
887 netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
888 u_int32_t payload_length
, mbuf_t packet
, int offset
)
892 struct netagent_wrapper
*new_wrapper
= NULL
;
893 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
894 uuid_t registered_uuid
;
896 if (session
== NULL
) {
897 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
898 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
902 if (session
->wrapper
!= NULL
) {
903 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
904 response_error
= NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED
;
908 if (payload_length
< sizeof(struct netagent
)) {
909 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%u < %lu)",
910 payload_length
, sizeof(struct netagent
));
911 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
915 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
916 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
917 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, error %d data_size %d",
919 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
923 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
924 if (new_wrapper
== NULL
) {
925 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
926 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
930 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
932 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
,
933 &new_wrapper
->netagent
);
935 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
936 FREE(new_wrapper
, M_NETAGENT
);
937 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
941 uuid_copy(registered_uuid
, new_wrapper
->netagent
.netagent_uuid
);
943 error
= netagent_handle_register_inner(session
, new_wrapper
);
945 NETAGENTLOG(LOG_ERR
, "Failed to register agent: %d", error
);
946 FREE(new_wrapper
, M_NETAGENT
);
947 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
951 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
952 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
);
953 netagent_post_event(registered_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
, false);
956 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
, response_error
);
960 netagent_unregister(netagent_session_t _session
)
962 struct netagent_session
*session
= (struct netagent_session
*)_session
;
963 if (session
== NULL
) {
964 NETAGENTLOG0(LOG_ERR
, "Cannot unregister NULL session");
968 netagent_unregister_session_wrapper(session
);
973 netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
974 u_int32_t payload_length
)
976 #pragma unused(payload, payload_length)
977 u_int32_t response_error
= 0;
979 if (session
== NULL
) {
980 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
981 response_error
= EINVAL
;
985 netagent_unregister_session_wrapper(session
);
988 return response_error
;
992 netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
993 u_int32_t payload_length
, mbuf_t packet
, int offset
)
995 #pragma unused(payload_length, packet, offset)
996 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
998 if (session
== NULL
) {
999 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1000 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1004 netagent_unregister_session_wrapper(session
);
1006 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
);
1009 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
, response_error
);
1013 netagent_send_cellular_failed_event(struct netagent_wrapper
*wrapper
,
1014 pid_t pid
, uuid_t proc_uuid
)
1016 if (strncmp(wrapper
->netagent
.netagent_domain
, "Cellular", NETAGENT_DOMAINSIZE
) != 0) {
1020 struct kev_netpolicy_ifdenied ev_ifdenied
;
1022 bzero(&ev_ifdenied
, sizeof(ev_ifdenied
));
1024 ev_ifdenied
.ev_data
.epid
= pid
;
1025 uuid_copy(ev_ifdenied
.ev_data
.euuid
, proc_uuid
);
1026 ev_ifdenied
.ev_if_functional_type
= IFRTYPE_FUNCTIONAL_CELLULAR
;
1028 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED
, &ev_ifdenied
.ev_data
, sizeof(ev_ifdenied
));
1032 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
)
1034 u_int32_t response_error
= 0;
1036 if (agent_changed
== NULL
) {
1037 NETAGENTLOG0(LOG_ERR
, "Invalid argument: agent_changed");
1041 lck_rw_lock_exclusive(&netagent_lock
);
1043 if (uuid_compare(session
->wrapper
->netagent
.netagent_uuid
, new_wrapper
->netagent
.netagent_uuid
) != 0 ||
1044 memcmp(&session
->wrapper
->netagent
.netagent_domain
, &new_wrapper
->netagent
.netagent_domain
,
1045 sizeof(new_wrapper
->netagent
.netagent_domain
)) != 0 ||
1046 memcmp(&session
->wrapper
->netagent
.netagent_type
, &new_wrapper
->netagent
.netagent_type
,
1047 sizeof(new_wrapper
->netagent
.netagent_type
)) != 0) {
1048 lck_rw_done(&netagent_lock
);
1049 NETAGENTLOG0(LOG_ERR
, "Basic agent parameters do not match, cannot update");
1050 if (error_domain
== kNetagentErrorDomainPOSIX
) {
1051 response_error
= EINVAL
;
1052 } else if (error_domain
== kNetagentErrorDomainUserDefined
) {
1053 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE
;
1055 return response_error
;
1058 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
1059 if (session
->wrapper
->netagent
.netagent_data_size
== new_wrapper
->netagent
.netagent_data_size
&&
1060 memcmp(&session
->wrapper
->netagent
, &new_wrapper
->netagent
, sizeof(struct netagent
) + data_size
) == 0) {
1061 // Agent is exactly identical, don't increment the generation count
1063 // Make a copy of the list of pending clients, and clear the current list
1064 struct netagent_client_list_s pending_triggers_list_copy
;
1065 LIST_INIT(&pending_triggers_list_copy
);
1066 struct netagent_client
*search_client
= NULL
;
1067 struct netagent_client
*temp_client
= NULL
;
1068 LIST_FOREACH_SAFE(search_client
, &session
->wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
1069 LIST_REMOVE(search_client
, client_chain
);
1070 LIST_INSERT_HEAD(&pending_triggers_list_copy
, search_client
, client_chain
);
1072 lck_rw_done(&netagent_lock
);
1074 // Update pending client triggers without holding a lock
1075 search_client
= NULL
;
1077 LIST_FOREACH_SAFE(search_client
, &pending_triggers_list_copy
, client_chain
, temp_client
) {
1078 necp_force_update_client(search_client
->client_id
, session
->wrapper
->netagent
.netagent_uuid
, session
->wrapper
->generation
);
1079 netagent_send_cellular_failed_event(new_wrapper
, search_client
->client_pid
, search_client
->client_proc_uuid
);
1080 LIST_REMOVE(search_client
, client_chain
);
1081 FREE(search_client
, M_NETAGENT
);
1083 NETAGENTLOG0(LOG_DEBUG
, "Updated agent (no changes)");
1084 *agent_changed
= FALSE
;
1085 return response_error
;
1088 new_wrapper
->generation
= g_next_generation
++;
1089 new_wrapper
->use_count
= session
->wrapper
->use_count
;
1091 if ((new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1092 !(session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1093 netagent_active_count
++;
1094 } else if (!(new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1095 (session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1096 netagent_active_count
> 0) {
1097 netagent_active_count
--;
1100 LIST_REMOVE(session
->wrapper
, master_chain
);
1101 netagent_free_wrapper(session
->wrapper
);
1102 session
->wrapper
= new_wrapper
;
1103 new_wrapper
->control_unit
= session
->control_unit
;
1104 new_wrapper
->event_handler
= session
->event_handler
;
1105 new_wrapper
->event_context
= session
->event_context
;
1106 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
1107 LIST_INIT(&new_wrapper
->pending_triggers_list
);
1109 NETAGENTLOG0(LOG_DEBUG
, "Updated agent");
1110 *agent_changed
= TRUE
;
1112 lck_rw_done(&netagent_lock
);
1114 return response_error
;
1118 netagent_update(netagent_session_t _session
, struct netagent
*agent
)
1120 u_int8_t agent_changed
;
1122 struct netagent_wrapper
*new_wrapper
= NULL
;
1123 bool should_update_immediately
;
1124 uuid_t updated_uuid
;
1126 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1127 if (session
== NULL
) {
1128 NETAGENTLOG0(LOG_ERR
, "Cannot update agent on NULL session");
1132 if (agent
== NULL
) {
1133 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
1137 if (session
->wrapper
== NULL
) {
1138 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1142 data_size
= agent
->netagent_data_size
;
1143 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1144 NETAGENTLOG(LOG_ERR
, "Update message size (%u > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1148 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1149 if (new_wrapper
== NULL
) {
1150 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1154 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1155 __nochk_memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
1157 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1158 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1160 int error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1162 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1163 if (agent_changed
== FALSE
) {
1164 // The session wrapper does not need the "new_wrapper" as nothing changed
1165 FREE(new_wrapper
, M_NETAGENT
);
1168 FREE(new_wrapper
, M_NETAGENT
);
1176 netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
, u_int32_t payload_length
)
1178 u_int32_t data_size
= 0;
1179 struct netagent_wrapper
*new_wrapper
= NULL
;
1180 errno_t response_error
= 0;
1181 struct netagent
*update_netagent
= (struct netagent
*)(void *)payload
;
1182 u_int8_t agent_changed
;
1183 bool should_update_immediately
;
1184 uuid_t updated_uuid
;
1186 if (session
== NULL
) {
1187 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1188 response_error
= EINVAL
;
1192 if (payload
== NULL
) {
1193 NETAGENTLOG0(LOG_ERR
, "No payload received");
1194 response_error
= EINVAL
;
1198 if (session
->wrapper
== NULL
) {
1199 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1200 response_error
= ENOENT
;
1204 if (payload_length
< sizeof(struct netagent
)) {
1205 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%u < %lu)",
1206 payload_length
, sizeof(struct netagent
));
1207 response_error
= EINVAL
;
1211 data_size
= update_netagent
->netagent_data_size
;
1212 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1213 NETAGENTLOG(LOG_ERR
, "Update message size (%u > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1214 response_error
= EINVAL
;
1218 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
1219 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
1220 response_error
= EINVAL
;
1224 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1225 if (new_wrapper
== NULL
) {
1226 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1227 response_error
= ENOMEM
;
1231 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1232 __nochk_memcpy(&new_wrapper
->netagent
, update_netagent
, sizeof(struct netagent
) + data_size
);
1234 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1235 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1237 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1238 if (response_error
== 0) {
1239 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1240 if (agent_changed
== FALSE
) {
1241 // The session wrapper does not need the "new_wrapper" as nothing changed
1242 FREE(new_wrapper
, M_NETAGENT
);
1245 FREE(new_wrapper
, M_NETAGENT
);
1249 return response_error
;
1253 netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
1254 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1258 struct netagent_wrapper
*new_wrapper
= NULL
;
1259 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1260 u_int8_t agent_changed
;
1261 uuid_t updated_uuid
;
1262 bool should_update_immediately
;
1264 if (session
== NULL
) {
1265 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1266 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1270 if (session
->wrapper
== NULL
) {
1271 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1272 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1276 if (payload_length
< sizeof(struct netagent
)) {
1277 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%u < %lu)",
1278 payload_length
, sizeof(struct netagent
));
1279 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1283 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
1284 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
1285 NETAGENTLOG(LOG_ERR
, "Update message size could not be read, error %d data_size %d",
1287 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1291 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1292 if (new_wrapper
== NULL
) {
1293 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1294 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1298 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1300 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
, &new_wrapper
->netagent
);
1302 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
1303 FREE(new_wrapper
, M_NETAGENT
);
1304 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1308 uuid_copy(updated_uuid
, new_wrapper
->netagent
.netagent_uuid
);
1309 should_update_immediately
= (NETAGENT_FLAG_UPDATE_IMMEDIATELY
== (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_UPDATE_IMMEDIATELY
));
1311 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainUserDefined
);
1312 if (response_error
!= 0) {
1313 FREE(new_wrapper
, M_NETAGENT
);
1317 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
);
1318 netagent_post_event(updated_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
, should_update_immediately
);
1320 if (agent_changed
== FALSE
) {
1321 // The session wrapper does not need the "new_wrapper" as nothing changed
1322 FREE(new_wrapper
, M_NETAGENT
);
1327 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
, response_error
);
1331 netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
1332 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1334 #pragma unused(payload_length, packet, offset)
1335 u_int8_t
*response
= NULL
;
1336 u_int8_t
*cursor
= NULL
;
1337 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1339 if (session
== NULL
) {
1340 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1341 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1345 if (session
->wrapper
== NULL
) {
1346 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1347 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1351 lck_rw_lock_shared(&netagent_lock
);
1353 size_t response_size
= sizeof(struct netagent_message_header
) + sizeof(session
->wrapper
->netagent
)
1354 + session
->wrapper
->netagent
.netagent_data_size
;
1355 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
1356 if (response
== NULL
) {
1361 cursor
= netagent_buffer_write_message_header(cursor
, NETAGENT_MESSAGE_TYPE_GET
,
1362 NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0,
1363 response_size
- sizeof(struct netagent_message_header
));
1364 memcpy(cursor
, &session
->wrapper
->netagent
, sizeof(session
->wrapper
->netagent
) +
1365 session
->wrapper
->netagent
.netagent_data_size
);
1367 lck_rw_done(&netagent_lock
);
1369 if (!netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
)) {
1370 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
1372 FREE(response
, M_NETAGENT
);
1375 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_GET
, message_id
, response_error
);
1379 netagent_assign_nexus(netagent_session_t _session
, uuid_t necp_client_uuid
,
1380 void *assign_message
, size_t assigned_results_length
)
1382 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1383 if (session
== NULL
) {
1384 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1388 if (session
->wrapper
== NULL
) {
1389 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1393 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1394 int error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, necp_client_uuid
, assign_message
, assigned_results_length
);
1396 // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1397 NETAGENTLOG((error
== ENOENT
? LOG_DEBUG
: LOG_ERR
), "Client assignment failed: %d", error
);
1401 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1406 netagent_update_flow_protoctl_event(netagent_session_t _session
,
1407 uuid_t client_id
, uint32_t protoctl_event_code
,
1408 uint32_t protoctl_event_val
, uint32_t protoctl_event_tcp_seq_number
)
1410 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1413 if (session
== NULL
) {
1414 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1418 if (session
->wrapper
== NULL
) {
1419 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1423 error
= necp_update_flow_protoctl_event(session
->wrapper
->netagent
.netagent_uuid
,
1424 client_id
, protoctl_event_code
, protoctl_event_val
, protoctl_event_tcp_seq_number
);
1430 netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
1431 u_int32_t payload_length
)
1433 errno_t response_error
= 0;
1434 struct netagent_assign_nexus_message
*assign_nexus_netagent
= (struct netagent_assign_nexus_message
*)(void *)payload
;
1436 u_int8_t
*assigned_results
= NULL
;
1438 if (session
== NULL
) {
1439 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1440 response_error
= ENOENT
;
1444 if (payload
== NULL
) {
1445 NETAGENTLOG0(LOG_ERR
, "No payload received");
1446 response_error
= EINVAL
;
1450 if (session
->wrapper
== NULL
) {
1451 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1452 response_error
= ENOENT
;
1456 if (payload_length
< sizeof(uuid_t
)) {
1457 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1458 response_error
= EINVAL
;
1462 memcpy(client_id
, assign_nexus_netagent
->assign_client_id
, sizeof(client_id
));
1463 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1465 if (assigned_results_length
> 0) {
1466 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1467 if (assigned_results
== NULL
) {
1468 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1469 response_error
= ENOMEM
;
1472 memcpy(assigned_results
, assign_nexus_netagent
->assign_necp_results
, assigned_results_length
);
1475 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1476 response_error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1477 if (response_error
) {
1478 // necp_assign_client_result returns POSIX errors
1479 if (assigned_results
) {
1480 FREE(assigned_results
, M_NETAGENT
);
1482 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", response_error
);
1486 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1488 return response_error
;
1493 netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
1494 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1497 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1499 u_int8_t
*assigned_results
= NULL
;
1501 if (session
== NULL
) {
1502 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1503 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1507 if (session
->wrapper
== NULL
) {
1508 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1509 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1513 if (payload_length
< sizeof(uuid_t
)) {
1514 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1515 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1519 error
= mbuf_copydata(packet
, offset
, sizeof(client_id
), &client_id
);
1521 NETAGENTLOG(LOG_ERR
, "Failed to read uuid for assign message: %d", error
);
1522 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1526 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1527 if (assigned_results_length
> 0) {
1528 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1529 if (assigned_results
== NULL
) {
1530 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1531 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1535 error
= mbuf_copydata(packet
, offset
+ sizeof(client_id
), assigned_results_length
, assigned_results
);
1537 FREE(assigned_results
, M_NETAGENT
);
1538 NETAGENTLOG(LOG_ERR
, "Failed to read assign message: %d", error
);
1539 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1544 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1545 error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1547 if (assigned_results
) {
1548 FREE(assigned_results
, M_NETAGENT
);
1550 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", error
);
1551 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN
;
1555 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1556 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
);
1559 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
, response_error
);
1563 netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
)
1565 errno_t response_error
= 0;
1566 uint64_t use_count
= 0;
1568 if (session
== NULL
) {
1569 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1570 response_error
= ENOENT
;
1574 if (payload
== NULL
) {
1575 NETAGENTLOG0(LOG_ERR
, "No payload received");
1576 response_error
= EINVAL
;
1580 if (payload_length
!= sizeof(use_count
)) {
1581 NETAGENTLOG(LOG_ERR
, "Payload length is invalid (%lu)", payload_length
);
1582 response_error
= EINVAL
;
1586 memcpy(&use_count
, payload
, sizeof(use_count
));
1588 lck_rw_lock_shared(&netagent_lock
);
1590 if (session
->wrapper
== NULL
) {
1591 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1592 response_error
= ENOENT
;
1593 lck_rw_done(&netagent_lock
);
1597 session
->wrapper
->use_count
= use_count
;
1599 lck_rw_done(&netagent_lock
);
1602 return response_error
;
1606 netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
)
1608 errno_t response_error
= 0;
1609 uint64_t use_count
= 0;
1611 if (session
== NULL
) {
1612 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1613 response_error
= ENOENT
;
1617 if (buffer
== NULL
) {
1618 NETAGENTLOG0(LOG_ERR
, "No payload received");
1619 response_error
= EINVAL
;
1623 if (*buffer_length
!= sizeof(use_count
)) {
1624 NETAGENTLOG(LOG_ERR
, "Buffer length is invalid (%lu)", *buffer_length
);
1625 response_error
= EINVAL
;
1629 lck_rw_lock_shared(&netagent_lock
);
1631 if (session
->wrapper
== NULL
) {
1632 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1633 response_error
= ENOENT
;
1634 lck_rw_done(&netagent_lock
);
1638 use_count
= session
->wrapper
->use_count
;
1639 lck_rw_done(&netagent_lock
);
1641 memcpy(buffer
, &use_count
, sizeof(use_count
));
1642 *buffer_length
= sizeof(use_count
);
1645 return response_error
;
1648 static struct netagent_wrapper
*
1649 netagent_find_agent_with_uuid(uuid_t uuid
)
1651 struct netagent_wrapper
*search_netagent
= NULL
;
1653 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1654 if (uuid_compare(search_netagent
->netagent
.netagent_uuid
, uuid
) == 0) {
1655 return search_netagent
;
1663 netagent_post_updated_interfaces(uuid_t uuid
)
1665 struct netagent_wrapper
*wrapper
= NULL
;
1666 lck_rw_lock_shared(&netagent_lock
);
1667 wrapper
= netagent_find_agent_with_uuid(uuid
);
1668 lck_rw_done(&netagent_lock
);
1670 if (wrapper
!= NULL
) {
1671 netagent_post_event(uuid
, KEV_NETAGENT_UPDATED_INTERFACES
, TRUE
, false);
1673 NETAGENTLOG0(LOG_DEBUG
, "Interface event with no associated agent");
1680 netagent_dump_get_data_size_locked()
1682 struct netagent_wrapper
*search_netagent
= NULL
;
1683 u_int32_t total_netagent_data_size
= 0;
1684 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1685 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1686 total_netagent_data_size
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1688 return total_netagent_data_size
;
1692 netagent_dump_copy_data_locked(u_int8_t
*buffer
, u_int32_t buffer_length
)
1694 size_t response_size
= 0;
1695 u_int8_t
*cursor
= NULL
;
1696 struct netagent_wrapper
*search_netagent
= NULL
;
1698 response_size
= buffer_length
; // We already know that buffer_length is the same as total_netagent_data_size.
1700 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1701 memcpy(cursor
, search_netagent
->netagent
.netagent_uuid
, sizeof(search_netagent
->netagent
.netagent_uuid
));
1702 cursor
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1707 netagent_ioctl(u_long cmd
, caddr_t data
)
1712 case SIOCGIFAGENTLIST32
:
1713 case SIOCGIFAGENTLIST64
: {
1714 /* Check entitlement if the client requests agent dump */
1715 errno_t cred_result
= priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES
, 0);
1716 if (cred_result
!= 0) {
1717 NETAGENTLOG0(LOG_ERR
, "Client does not hold the necessary entitlement to get netagent information");
1726 lck_rw_lock_shared(&netagent_lock
);
1728 case SIOCGIFAGENTDATA32
: {
1729 struct netagent_req32
*ifsir32
= (struct netagent_req32
*)(void *)data
;
1730 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir32
->netagent_uuid
);
1731 if (wrapper
== NULL
) {
1735 uuid_copy(ifsir32
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1736 memcpy(ifsir32
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir32
->netagent_domain
));
1737 memcpy(ifsir32
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir32
->netagent_type
));
1738 memcpy(ifsir32
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir32
->netagent_desc
));
1739 ifsir32
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1740 if (ifsir32
->netagent_data_size
== 0) {
1741 // First pass, client wants data size
1742 ifsir32
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1743 } else if (ifsir32
->netagent_data
!= USER_ADDR_NULL
&&
1744 ifsir32
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1745 // Second pass, client wants data buffer filled out
1746 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir32
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1752 case SIOCGIFAGENTDATA64
: {
1753 struct netagent_req64
*ifsir64
= (struct netagent_req64
*)(void *)data
;
1754 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir64
->netagent_uuid
);
1755 if (wrapper
== NULL
) {
1759 uuid_copy(ifsir64
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1760 memcpy(ifsir64
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir64
->netagent_domain
));
1761 memcpy(ifsir64
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir64
->netagent_type
));
1762 memcpy(ifsir64
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir64
->netagent_desc
));
1763 ifsir64
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1764 if (ifsir64
->netagent_data_size
== 0) {
1765 // First pass, client wants data size
1766 ifsir64
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1767 } else if (ifsir64
->netagent_data
!= USER_ADDR_NULL
&&
1768 ifsir64
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1769 // Second pass, client wants data buffer filled out
1770 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir64
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1776 case SIOCGIFAGENTLIST32
: {
1777 struct netagentlist_req32
*ifsir32
= (struct netagentlist_req32
*)(void *)data
;
1778 if (ifsir32
->data_size
== 0) {
1779 // First pass, client wants data size
1780 ifsir32
->data_size
= netagent_dump_get_data_size_locked();
1781 } else if (ifsir32
->data
!= USER_ADDR_NULL
&&
1782 ifsir32
->data_size
> 0 &&
1783 ifsir32
->data_size
== netagent_dump_get_data_size_locked()) {
1784 // Second pass, client wants data buffer filled out
1785 u_int8_t
*response
= NULL
;
1786 MALLOC(response
, u_int8_t
*, ifsir32
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1787 if (response
== NULL
) {
1792 netagent_dump_copy_data_locked(response
, ifsir32
->data_size
);
1793 error
= copyout(response
, ifsir32
->data
, ifsir32
->data_size
);
1794 FREE(response
, M_NETAGENT
);
1800 case SIOCGIFAGENTLIST64
: {
1801 struct netagentlist_req64
*ifsir64
= (struct netagentlist_req64
*)(void *)data
;
1802 if (ifsir64
->data_size
== 0) {
1803 // First pass, client wants data size
1804 ifsir64
->data_size
= netagent_dump_get_data_size_locked();
1805 } else if (ifsir64
->data
!= USER_ADDR_NULL
&&
1806 ifsir64
->data_size
> 0 &&
1807 ifsir64
->data_size
== netagent_dump_get_data_size_locked()) {
1808 // Second pass, client wants data buffer filled out
1809 u_int8_t
*response
= NULL
;
1810 MALLOC(response
, u_int8_t
*, ifsir64
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1811 if (response
== NULL
) {
1816 netagent_dump_copy_data_locked(response
, ifsir64
->data_size
);
1817 error
= copyout(response
, ifsir64
->data
, ifsir64
->data_size
);
1818 FREE(response
, M_NETAGENT
);
1829 lck_rw_done(&netagent_lock
);
1834 netagent_get_flags(uuid_t uuid
)
1836 u_int32_t flags
= 0;
1837 lck_rw_lock_shared(&netagent_lock
);
1838 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1839 if (wrapper
!= NULL
) {
1840 flags
= wrapper
->netagent
.netagent_flags
;
1842 NETAGENTLOG0(LOG_DEBUG
, "Flags requested for invalid netagent");
1844 lck_rw_done(&netagent_lock
);
1850 netagent_set_flags(uuid_t uuid
, u_int32_t flags
)
1853 lck_rw_lock_exclusive(&netagent_lock
);
1854 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1855 if (wrapper
!= NULL
) {
1856 wrapper
->netagent
.netagent_flags
= flags
;
1858 NETAGENTLOG0(LOG_DEBUG
,
1859 "Attempt to set flags for invalid netagent");
1862 lck_rw_done(&netagent_lock
);
1868 netagent_get_generation(uuid_t uuid
)
1870 u_int32_t generation
= 0;
1871 lck_rw_lock_shared(&netagent_lock
);
1872 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1873 if (wrapper
!= NULL
) {
1874 generation
= wrapper
->generation
;
1876 NETAGENTLOG0(LOG_DEBUG
, "Generation requested for invalid netagent");
1878 lck_rw_done(&netagent_lock
);
1884 netagent_get_agent_domain_and_type(uuid_t uuid
, char *domain
, char *type
)
1887 if (domain
== NULL
|| type
== NULL
) {
1888 NETAGENTLOG(LOG_ERR
, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain
, type
);
1892 lck_rw_lock_shared(&netagent_lock
);
1893 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1894 if (wrapper
!= NULL
) {
1896 memcpy(domain
, wrapper
->netagent
.netagent_domain
, NETAGENT_DOMAINSIZE
);
1897 memcpy(type
, wrapper
->netagent
.netagent_type
, NETAGENT_TYPESIZE
);
1899 NETAGENTLOG0(LOG_ERR
, "Type requested for invalid netagent");
1901 lck_rw_done(&netagent_lock
);
1907 netagent_kernel_trigger(uuid_t uuid
)
1911 lck_rw_lock_shared(&netagent_lock
);
1912 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1913 if (wrapper
== NULL
) {
1914 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger could not be found");
1919 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_KERNEL_ACTIVATED
) == 0) {
1920 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger is not kernel activated");
1921 // Agent does not accept kernel triggers
1926 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1927 // Agent already active
1928 NETAGENTLOG0(LOG_INFO
, "Requested netagent for kernel trigger is already active");
1933 error
= netagent_send_trigger(wrapper
, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
1934 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent from kernel (error %d)", error
);
1936 lck_rw_done(&netagent_lock
);
1941 netagent_client_message_with_params(uuid_t agent_uuid
,
1942 uuid_t necp_client_uuid
,
1945 u_int8_t message_type
,
1946 struct necp_client_agent_parameters
*parameters
,
1947 void **assigned_results
,
1948 size_t *assigned_results_length
)
1952 if (message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
&&
1953 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT
&&
1954 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT
&&
1955 message_type
!= NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
&&
1956 message_type
!= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
&&
1957 message_type
!= NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1958 NETAGENTLOG(LOG_ERR
, "Client netagent message type (%d) is invalid", message_type
);
1962 lck_rw_lock_shared(&netagent_lock
);
1963 bool should_unlock
= TRUE
;
1964 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1965 if (wrapper
== NULL
) {
1966 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
1971 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1972 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
1973 // Agent does not accept user triggers
1974 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1978 pid_t report_pid
= 0;
1979 uuid_t report_proc_uuid
= {};
1980 if (parameters
!= NULL
) {
1981 report_pid
= parameters
->u
.nexus_request
.epid
;
1982 uuid_copy(report_proc_uuid
, parameters
->u
.nexus_request
.euuid
);
1984 struct proc
*p
= current_proc();
1986 report_pid
= proc_pid(p
);
1987 proc_getexecutableuuid(p
, report_proc_uuid
, sizeof(report_proc_uuid
));
1990 netagent_send_cellular_failed_event(wrapper
, report_pid
, report_proc_uuid
);
1993 } else if (message_type
== NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
||
1994 message_type
== NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
||
1995 message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1996 bool is_nexus_agent
= ((wrapper
->netagent
.netagent_flags
&
1997 (NETAGENT_FLAG_NEXUS_PROVIDER
|
1998 NETAGENT_FLAG_NEXUS_LISTENER
|
1999 NETAGENT_FLAG_CUSTOM_IP_NEXUS
|
2000 NETAGENT_FLAG_CUSTOM_ETHER_NEXUS
|
2001 NETAGENT_FLAG_INTERPOSE_NEXUS
)) != 0);
2002 if (!is_nexus_agent
) {
2003 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance is not a nexus provider");
2004 // Agent is not a nexus provider
2009 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) == 0) {
2011 NETAGENTLOG0(LOG_INFO
, "Requested netagent for nexus instance is not active");
2017 if (wrapper
->control_unit
== 0) {
2018 if (wrapper
->event_handler
== NULL
) {
2019 // No event handler registered for kernel agent
2022 // We hold the shared lock during the event handler callout, so it is expected
2023 // that the event handler will not lead to any registrations or unregistrations
2024 // of network agents.
2025 error
= wrapper
->event_handler(message_type
, necp_client_uuid
, pid
, handle
,
2026 wrapper
->event_context
, parameters
,
2027 assigned_results
, assigned_results_length
);
2029 VERIFY(assigned_results
== NULL
|| *assigned_results
== NULL
);
2030 VERIFY(assigned_results_length
== NULL
|| *assigned_results_length
== 0);
2034 // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2035 if (message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
2036 message_type
= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
;
2039 error
= netagent_send_client_message(wrapper
, necp_client_uuid
, message_type
);
2040 if (error
== 0 && message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
2041 if (lck_rw_lock_shared_to_exclusive(&netagent_lock
)) {
2042 // Grab the lock exclusively to add a pending client to the list
2043 struct netagent_client
*new_pending_client
= NULL
;
2044 MALLOC(new_pending_client
, struct netagent_client
*, sizeof(*new_pending_client
), M_NETAGENT
, M_WAITOK
);
2045 if (new_pending_client
== NULL
) {
2046 NETAGENTLOG0(LOG_ERR
, "Failed to allocate client for trigger");
2048 uuid_copy(new_pending_client
->client_id
, necp_client_uuid
);
2049 if (parameters
!= NULL
) {
2050 new_pending_client
->client_pid
= parameters
->u
.nexus_request
.epid
;
2051 uuid_copy(new_pending_client
->client_proc_uuid
, parameters
->u
.nexus_request
.euuid
);
2053 struct proc
*p
= current_proc();
2055 new_pending_client
->client_pid
= proc_pid(p
);
2056 proc_getexecutableuuid(p
, new_pending_client
->client_proc_uuid
, sizeof(new_pending_client
->client_proc_uuid
));
2059 LIST_INSERT_HEAD(&wrapper
->pending_triggers_list
, new_pending_client
, client_chain
);
2062 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2063 should_unlock
= FALSE
;
2067 NETAGENTLOG(((error
&& error
!= ENOENT
) ? LOG_ERR
: LOG_INFO
), "Send message %d for client (error %d)", message_type
, error
);
2068 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
2069 uuid_string_t uuid_str
;
2070 uuid_unparse(agent_uuid
, uuid_str
);
2071 NETAGENTLOG(LOG_NOTICE
, "Triggered network agent %s, error = %d", uuid_str
, error
);
2074 if (should_unlock
) {
2075 lck_rw_done(&netagent_lock
);
2081 netagent_client_message(uuid_t agent_uuid
, uuid_t necp_client_uuid
, pid_t pid
, void *handle
, u_int8_t message_type
)
2083 return netagent_client_message_with_params(agent_uuid
, necp_client_uuid
, pid
, handle
, message_type
, NULL
, NULL
, NULL
);
2087 netagent_use(uuid_t agent_uuid
, uint64_t *out_use_count
)
2091 lck_rw_lock_exclusive(&netagent_lock
);
2092 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2093 if (wrapper
== NULL
) {
2094 NETAGENTLOG0(LOG_ERR
, "netagent_assert: Requested netagent UUID is not registered");
2099 uint64_t current_count
= wrapper
->use_count
;
2100 wrapper
->use_count
++;
2102 if (out_use_count
!= NULL
) {
2103 *out_use_count
= current_count
;
2107 lck_rw_done(&netagent_lock
);
2112 netagent_copyout(uuid_t agent_uuid
, user_addr_t user_addr
, u_int32_t user_size
)
2116 lck_rw_lock_shared(&netagent_lock
);
2117 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2118 if (wrapper
== NULL
) {
2119 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
2124 u_int32_t total_size
= (sizeof(struct netagent
) + wrapper
->netagent
.netagent_data_size
);
2125 if (user_size
< total_size
) {
2126 NETAGENTLOG(LOG_ERR
, "Provided user buffer is too small (%u < %u)", user_size
, total_size
);
2131 error
= copyout(&wrapper
->netagent
, user_addr
, total_size
);
2133 NETAGENTLOG((error
? LOG_ERR
: LOG_DEBUG
), "Copied agent content (error %d)", error
);
2135 lck_rw_done(&netagent_lock
);
2140 netagent_trigger(struct proc
*p
, struct netagent_trigger_args
*uap
, int32_t *retval
)
2142 #pragma unused(p, retval)
2147 NETAGENTLOG0(LOG_ERR
, "uap == NULL");
2151 if (uap
->agent_uuid
) {
2152 if (uap
->agent_uuidlen
!= sizeof(uuid_t
)) {
2153 NETAGENTLOG(LOG_ERR
, "Incorrect length (got %zu, expected %lu)",
2154 (size_t)uap
->agent_uuidlen
, sizeof(uuid_t
));
2158 error
= copyin(uap
->agent_uuid
, agent_uuid
, sizeof(uuid_t
));
2160 NETAGENTLOG(LOG_ERR
, "copyin error (%d)", error
);
2165 if (uuid_is_null(agent_uuid
)) {
2166 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is empty");
2170 lck_rw_lock_shared(&netagent_lock
);
2171 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2172 if (wrapper
== NULL
) {
2173 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not registered");
2178 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
2179 // Agent does not accept triggers
2180 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not eligible for triggering");
2185 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
2186 // Agent already active
2187 NETAGENTLOG0(LOG_INFO
, "Requested netagent UUID is already active");
2192 error
= netagent_send_trigger(wrapper
, p
, NETAGENT_TRIGGER_FLAG_USER
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
2193 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent (error %d)", error
);
2195 lck_rw_done(&netagent_lock
);