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>
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 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
66 #define NETAGENTLOG0(level, msg) do { \
67 if (level <= netagent_debug) \
68 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: %s\n", __FUNCTION__, msg); \
71 struct netagent_client
{
72 LIST_ENTRY(netagent_client
) client_chain
;
74 uuid_t client_proc_uuid
;
78 LIST_HEAD(netagent_client_list_s
, netagent_client
);
80 struct netagent_wrapper
{
81 LIST_ENTRY(netagent_wrapper
) master_chain
;
82 u_int32_t control_unit
;
83 netagent_event_f event_handler
;
87 struct netagent_client_list_s pending_triggers_list
;
88 struct netagent netagent
;
91 struct netagent_session
{
92 u_int32_t control_unit
; // A control unit of 0 indicates an agent owned by the kernel
93 struct netagent_wrapper
*wrapper
;
94 netagent_event_f event_handler
;
99 kNetagentErrorDomainPOSIX
= 0,
100 kNetagentErrorDomainUserDefined
= 1,
101 } netagent_error_domain_t
;
103 static LIST_HEAD(_netagent_list
, netagent_wrapper
) master_netagent_list
;
105 // Protected by netagent_lock
106 static u_int32_t g_next_generation
= 1;
108 static kern_ctl_ref netagent_kctlref
;
109 static u_int32_t netagent_family
;
110 static OSMallocTag netagent_malloc_tag
;
111 static lck_grp_attr_t
*netagent_grp_attr
= NULL
;
112 static lck_attr_t
*netagent_mtx_attr
= NULL
;
113 static lck_grp_t
*netagent_mtx_grp
= NULL
;
114 decl_lck_rw_data(static, netagent_lock
);
116 static errno_t
netagent_register_control(void);
117 static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
119 static errno_t
netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
);
120 static errno_t
netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
121 mbuf_t m
, int flags
);
122 static void netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
);
123 static errno_t
netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
124 int opt
, void *data
, size_t *len
);
125 static errno_t
netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
126 int opt
, void *data
, size_t len
);
128 static int netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
);
130 static struct netagent_session
*netagent_create_session(u_int32_t control_unit
);
131 static void netagent_delete_session(struct netagent_session
*session
);
134 static void netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
135 u_int32_t payload_length
, mbuf_t packet
, int offset
);
136 static errno_t
netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
137 u_int32_t payload_length
);
140 static void netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
141 u_int32_t payload_length
, mbuf_t packet
, int offset
);
142 static errno_t
netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
143 u_int32_t payload_length
);
146 static void netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
147 u_int32_t payload_length
, mbuf_t packet
, int offset
);
148 static errno_t
netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
149 u_int32_t payload_length
);
152 static void netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
153 u_int32_t payload_length
, mbuf_t packet
, int offset
);
154 static errno_t
netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
155 u_int32_t payload_length
);
157 // Set/get assert count
158 static errno_t
netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
);
159 static errno_t
netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
);
161 static void netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
162 u_int32_t payload_length
, mbuf_t packet
, int offset
);
164 static struct netagent_wrapper
*netagent_find_agent_with_uuid(uuid_t uuid
);
171 result
= netagent_register_control();
176 netagent_grp_attr
= lck_grp_attr_alloc_init();
177 if (netagent_grp_attr
== NULL
) {
178 NETAGENTLOG0(LOG_ERR
, "lck_grp_attr_alloc_init failed");
183 netagent_mtx_grp
= lck_grp_alloc_init(NETAGENT_CONTROL_NAME
, netagent_grp_attr
);
184 if (netagent_mtx_grp
== NULL
) {
185 NETAGENTLOG0(LOG_ERR
, "lck_grp_alloc_init failed");
190 netagent_mtx_attr
= lck_attr_alloc_init();
191 if (netagent_mtx_attr
== NULL
) {
192 NETAGENTLOG0(LOG_ERR
, "lck_attr_alloc_init failed");
197 lck_rw_init(&netagent_lock
, netagent_mtx_grp
, netagent_mtx_attr
);
199 LIST_INIT(&master_netagent_list
);
203 if (netagent_mtx_attr
!= NULL
) {
204 lck_attr_free(netagent_mtx_attr
);
205 netagent_mtx_attr
= NULL
;
207 if (netagent_mtx_grp
!= NULL
) {
208 lck_grp_free(netagent_mtx_grp
);
209 netagent_mtx_grp
= NULL
;
211 if (netagent_grp_attr
!= NULL
) {
212 lck_grp_attr_free(netagent_grp_attr
);
213 netagent_grp_attr
= NULL
;
215 if (netagent_kctlref
!= NULL
) {
216 ctl_deregister(netagent_kctlref
);
217 netagent_kctlref
= NULL
;
224 netagent_register_control(void)
226 struct kern_ctl_reg kern_ctl
;
229 // Create a tag to allocate memory
230 netagent_malloc_tag
= OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME
, OSMT_DEFAULT
);
232 // Find a unique value for our interface family
233 result
= mbuf_tag_id_find(NETAGENT_CONTROL_NAME
, &netagent_family
);
235 NETAGENTLOG(LOG_ERR
, "mbuf_tag_id_find_internal failed: %d", result
);
239 bzero(&kern_ctl
, sizeof(kern_ctl
));
240 strlcpy(kern_ctl
.ctl_name
, NETAGENT_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
241 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
242 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; // Require root
243 kern_ctl
.ctl_sendsize
= 64 * 1024;
244 kern_ctl
.ctl_recvsize
= 64 * 1024;
245 kern_ctl
.ctl_connect
= netagent_ctl_connect
;
246 kern_ctl
.ctl_disconnect
= netagent_ctl_disconnect
;
247 kern_ctl
.ctl_send
= netagent_ctl_send
;
248 kern_ctl
.ctl_rcvd
= netagent_ctl_rcvd
;
249 kern_ctl
.ctl_setopt
= netagent_ctl_setopt
;
250 kern_ctl
.ctl_getopt
= netagent_ctl_getopt
;
252 result
= ctl_register(&kern_ctl
, &netagent_kctlref
);
254 NETAGENTLOG(LOG_ERR
, "ctl_register failed: %d", result
);
262 netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
, void **unitinfo
)
264 #pragma unused(kctlref)
265 *unitinfo
= netagent_create_session(sac
->sc_unit
);
266 if (*unitinfo
== NULL
) {
267 // Could not allocate session
275 netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
)
277 #pragma unused(kctlref, unit)
278 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
279 if (session
!= NULL
) {
280 netagent_delete_session(session
);
288 netagent_post_event(uuid_t agent_uuid
, u_int32_t event_code
, bool update_necp
)
291 necp_update_all_clients();
294 struct kev_msg ev_msg
;
295 memset(&ev_msg
, 0, sizeof(ev_msg
));
297 struct kev_netagent_data event_data
;
299 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
300 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
301 ev_msg
.kev_subclass
= KEV_NETAGENT_SUBCLASS
;
302 ev_msg
.event_code
= event_code
;
304 uuid_copy(event_data
.netagent_uuid
, agent_uuid
);
305 ev_msg
.dv
[0].data_ptr
= &event_data
;
306 ev_msg
.dv
[0].data_length
= sizeof(event_data
);
308 kev_post_msg(&ev_msg
);
313 netagent_buffer_write_message_header(u_int8_t
*buffer
, u_int8_t message_type
, u_int8_t flags
,
314 u_int32_t message_id
, u_int32_t error
, u_int32_t payload_length
)
316 ((struct netagent_message_header
*)(void *)buffer
)->message_type
= message_type
;
317 ((struct netagent_message_header
*)(void *)buffer
)->message_flags
= flags
;
318 ((struct netagent_message_header
*)(void *)buffer
)->message_id
= message_id
;
319 ((struct netagent_message_header
*)(void *)buffer
)->message_error
= error
;
320 ((struct netagent_message_header
*)(void *)buffer
)->message_payload_length
= payload_length
;
321 return buffer
+ sizeof(struct netagent_message_header
);
325 netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
)
327 if (netagent_kctlref
== NULL
|| control_unit
== 0 || buffer
== NULL
|| buffer_size
== 0) {
331 return ctl_enqueuedata(netagent_kctlref
, control_unit
, buffer
, buffer_size
, CTL_DATA_EOR
);
335 netagent_send_trigger(struct netagent_wrapper
*wrapper
, struct proc
*p
, u_int32_t flags
, u_int32_t trigger_type
)
338 struct netagent_trigger_message
*trigger_message
= NULL
;
339 u_int8_t
*trigger
= NULL
;
340 size_t trigger_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_trigger_message
);
342 MALLOC(trigger
, u_int8_t
*, trigger_size
, M_NETAGENT
, M_WAITOK
);
343 if (trigger
== NULL
) {
347 (void)netagent_buffer_write_message_header(trigger
, trigger_type
, 0, 0, 0, sizeof(struct netagent_trigger_message
));
349 trigger_message
= (struct netagent_trigger_message
*)(void *)(trigger
+ sizeof(struct netagent_message_header
));
350 trigger_message
->trigger_flags
= flags
;
352 trigger_message
->trigger_pid
= proc_pid(p
);
353 proc_getexecutableuuid(p
, trigger_message
->trigger_proc_uuid
, sizeof(trigger_message
->trigger_proc_uuid
));
355 trigger_message
->trigger_pid
= 0;
356 uuid_clear(trigger_message
->trigger_proc_uuid
);
359 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)trigger
, trigger_size
))) {
360 NETAGENTLOG(LOG_ERR
, "Failed to send trigger message on control unit %d", wrapper
->control_unit
);
363 FREE(trigger
, M_NETAGENT
);
368 netagent_send_client_message(struct netagent_wrapper
*wrapper
, uuid_t client_id
, u_int8_t message_type
)
371 struct netagent_client_message
*client_message
= NULL
;
372 u_int8_t
*message
= NULL
;
373 size_t message_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_client_message
);
375 MALLOC(message
, u_int8_t
*, message_size
, M_NETAGENT
, M_WAITOK
);
376 if (message
== NULL
) {
380 (void)netagent_buffer_write_message_header(message
, message_type
, 0, 0, 0, sizeof(struct netagent_client_message
));
382 client_message
= (struct netagent_client_message
*)(void *)(message
+ sizeof(struct netagent_message_header
));
383 uuid_copy(client_message
->client_id
, client_id
);
385 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)message
, message_size
))) {
386 NETAGENTLOG(LOG_ERR
, "Failed to send client message %d on control unit %d", message_type
, wrapper
->control_unit
);
389 FREE(message
, M_NETAGENT
);
394 netagent_send_success_response(struct netagent_session
*session
, u_int8_t message_type
, u_int32_t message_id
)
397 u_int8_t
*response
= NULL
;
398 size_t response_size
= sizeof(struct netagent_message_header
);
399 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
400 if (response
== NULL
) {
403 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0, 0);
405 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
406 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
409 FREE(response
, M_NETAGENT
);
414 netagent_send_error_response(struct netagent_session
*session
, u_int8_t message_type
,
415 u_int32_t message_id
, u_int32_t error_code
)
418 u_int8_t
*response
= NULL
;
419 size_t response_size
= sizeof(struct netagent_message_header
);
421 if (session
== NULL
) {
422 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
426 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
427 if (response
== NULL
) {
430 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
,
431 message_id
, error_code
, 0);
433 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
434 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
437 FREE(response
, M_NETAGENT
);
442 netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, mbuf_t packet
, int flags
)
444 #pragma unused(kctlref, unit, flags)
445 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
446 struct netagent_message_header header
;
449 if (session
== NULL
) {
450 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
455 if (mbuf_pkthdr_len(packet
) < sizeof(header
)) {
456 NETAGENTLOG(LOG_ERR
, "Got a bad packet, length (%lu) < sizeof header (%lu)",
457 mbuf_pkthdr_len(packet
), sizeof(header
));
462 error
= mbuf_copydata(packet
, 0, sizeof(header
), &header
);
464 NETAGENTLOG(LOG_ERR
, "mbuf_copydata failed for the header: %d", error
);
469 switch (header
.message_type
) {
470 case NETAGENT_MESSAGE_TYPE_REGISTER
: {
471 netagent_handle_register_message(session
, header
.message_id
, header
.message_payload_length
,
472 packet
, sizeof(header
));
475 case NETAGENT_MESSAGE_TYPE_UNREGISTER
: {
476 netagent_handle_unregister_message(session
, header
.message_id
, header
.message_payload_length
,
477 packet
, sizeof(header
));
480 case NETAGENT_MESSAGE_TYPE_UPDATE
: {
481 netagent_handle_update_message(session
, header
.message_id
, header
.message_payload_length
,
482 packet
, sizeof(header
));
485 case NETAGENT_MESSAGE_TYPE_GET
: {
486 netagent_handle_get(session
, header
.message_id
, header
.message_payload_length
,
487 packet
, sizeof(header
));
490 case NETAGENT_MESSAGE_TYPE_ASSERT
: {
491 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
494 case NETAGENT_MESSAGE_TYPE_UNASSERT
: {
495 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
498 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
: {
499 netagent_handle_assign_nexus_message(session
, header
.message_id
, header
.message_payload_length
,
500 packet
, sizeof(header
));
504 NETAGENTLOG(LOG_ERR
, "Received unknown message type %d", header
.message_type
);
505 netagent_send_error_response(session
, header
.message_type
, header
.message_id
,
506 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE
);
517 netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
519 #pragma unused(kctlref, unit, unitinfo, flags)
524 netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
525 void *data
, size_t *len
)
527 #pragma unused(kctlref, unit)
528 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
531 if (session
== NULL
) {
532 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
538 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
539 NETAGENTLOG0(LOG_DEBUG
, "Request to get use count");
540 error
= netagent_handle_use_count_getopt(session
, data
, len
);
544 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
554 netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
555 void *data
, size_t len
)
557 #pragma unused(kctlref, unit)
558 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
561 if (session
== NULL
) {
562 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
568 case NETAGENT_OPTION_TYPE_REGISTER
: {
569 NETAGENTLOG0(LOG_DEBUG
, "Request for registration");
570 error
= netagent_handle_register_setopt(session
, data
, len
);
573 case NETAGENT_OPTION_TYPE_UPDATE
: {
574 NETAGENTLOG0(LOG_DEBUG
, "Request for update");
575 error
= netagent_handle_update_setopt(session
, data
, len
);
578 case NETAGENT_OPTION_TYPE_UNREGISTER
: {
579 NETAGENTLOG0(LOG_DEBUG
, "Request for unregistration");
580 error
= netagent_handle_unregister_setopt(session
, data
, len
);
583 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS
: {
584 NETAGENTLOG0(LOG_DEBUG
, "Request for assigning nexus");
585 error
= netagent_handle_assign_nexus_setopt(session
, data
, len
);
588 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
589 NETAGENTLOG0(LOG_DEBUG
, "Request to set use count");
590 error
= netagent_handle_use_count_setopt(session
, data
, len
);
594 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
603 // Session Management
604 static struct netagent_session
*
605 netagent_create_session(u_int32_t control_unit
)
607 struct netagent_session
*new_session
= NULL
;
609 MALLOC(new_session
, struct netagent_session
*, sizeof(*new_session
), M_NETAGENT
, M_WAITOK
);
610 if (new_session
== NULL
) {
613 NETAGENTLOG(LOG_DEBUG
, "Create agent session, control unit %d", control_unit
);
614 memset(new_session
, 0, sizeof(*new_session
));
615 new_session
->control_unit
= control_unit
;
616 new_session
->wrapper
= NULL
;
622 netagent_create(netagent_event_f event_handler
, void *context
)
624 struct netagent_session
*session
= netagent_create_session(0);
625 if (session
== NULL
) {
629 session
->event_handler
= event_handler
;
630 session
->event_context
= context
;
635 netagent_free_wrapper(struct netagent_wrapper
*wrapper
)
637 // Free any pending client triggers
638 struct netagent_client
*search_client
= NULL
;
639 struct netagent_client
*temp_client
= NULL
;
640 LIST_FOREACH_SAFE(search_client
, &wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
641 LIST_REMOVE(search_client
, client_chain
);
642 FREE(search_client
, M_NETAGENT
);
645 // Free wrapper itself
646 FREE(wrapper
, M_NETAGENT
);
650 netagent_unregister_session_wrapper(struct netagent_session
*session
)
652 bool unregistered
= FALSE
;
653 uuid_t unregistered_uuid
;
654 struct netagent_wrapper
*wrapper
= NULL
;
655 lck_rw_lock_exclusive(&netagent_lock
);
656 if (session
!= NULL
) {
657 wrapper
= session
->wrapper
;
658 if (wrapper
!= NULL
) {
659 if (netagent_registered_count
> 0) {
660 netagent_registered_count
--;
662 if ((session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
663 netagent_active_count
> 0) {
664 netagent_active_count
--;
667 LIST_REMOVE(wrapper
, master_chain
);
670 uuid_copy(unregistered_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
672 netagent_free_wrapper(session
->wrapper
);
673 session
->wrapper
= NULL
;
674 NETAGENTLOG0(LOG_DEBUG
, "Unregistered agent");
677 lck_rw_done(&netagent_lock
);
680 ifnet_clear_netagent(unregistered_uuid
);
681 netagent_post_event(unregistered_uuid
, KEV_NETAGENT_UNREGISTERED
, TRUE
);
686 netagent_delete_session(struct netagent_session
*session
)
688 if (session
!= NULL
) {
689 netagent_unregister_session_wrapper(session
);
690 FREE(session
, M_NETAGENT
);
695 netagent_destroy(netagent_session_t session
)
697 return netagent_delete_session((struct netagent_session
*)session
);
701 netagent_packet_get_netagent_data_size(mbuf_t packet
, int offset
, int *err
)
705 struct netagent netagent_peek
;
706 memset(&netagent_peek
, 0, sizeof(netagent_peek
));
710 error
= mbuf_copydata(packet
, offset
, sizeof(netagent_peek
), &netagent_peek
);
716 return netagent_peek
.netagent_data_size
;
720 netagent_handle_register_inner(struct netagent_session
*session
, struct netagent_wrapper
*new_wrapper
)
722 lck_rw_lock_exclusive(&netagent_lock
);
724 new_wrapper
->control_unit
= session
->control_unit
;
725 new_wrapper
->event_handler
= session
->event_handler
;
726 new_wrapper
->event_context
= session
->event_context
;
727 new_wrapper
->generation
= g_next_generation
++;
729 session
->wrapper
= new_wrapper
;
730 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
731 LIST_INIT(&new_wrapper
->pending_triggers_list
);
733 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
734 netagent_registered_count
++;
735 if (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) {
736 netagent_active_count
++;
739 lck_rw_done(&netagent_lock
);
745 netagent_register(netagent_session_t _session
, struct netagent
*agent
)
748 struct netagent_wrapper
*new_wrapper
= NULL
;
750 struct netagent_session
*session
= (struct netagent_session
*)_session
;
751 if (session
== NULL
) {
752 NETAGENTLOG0(LOG_ERR
, "Cannot register agent on NULL session");
757 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
761 if (session
->wrapper
!= NULL
) {
762 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
766 data_size
= agent
->netagent_data_size
;
767 if (data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
768 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %d",
773 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
774 if (new_wrapper
== NULL
) {
775 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
779 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
780 memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
782 int error
= netagent_handle_register_inner(session
, new_wrapper
);
784 FREE(new_wrapper
, M_NETAGENT
);
788 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
789 netagent_post_event(new_wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
);
795 netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
796 u_int32_t payload_length
)
799 struct netagent_wrapper
*new_wrapper
= NULL
;
800 u_int32_t response_error
= 0;
801 struct netagent
*register_netagent
= (struct netagent
*)(void *)payload
;
803 if (session
== NULL
) {
804 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
805 response_error
= EINVAL
;
809 if (payload
== NULL
) {
810 NETAGENTLOG0(LOG_ERR
, "No payload received");
811 response_error
= EINVAL
;
815 if (session
->wrapper
!= NULL
) {
816 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
817 response_error
= EINVAL
;
821 if (payload_length
< sizeof(struct netagent
)) {
822 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%u < %lu)",
823 payload_length
, sizeof(struct netagent
));
824 response_error
= EINVAL
;
828 data_size
= register_netagent
->netagent_data_size
;
829 if (data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
830 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %d", data_size
);
831 response_error
= EINVAL
;
835 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
836 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
837 response_error
= EINVAL
;
841 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
842 if (new_wrapper
== NULL
) {
843 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
844 response_error
= ENOMEM
;
848 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
849 memcpy(&new_wrapper
->netagent
, register_netagent
, sizeof(struct netagent
) + data_size
);
851 response_error
= netagent_handle_register_inner(session
, new_wrapper
);
852 if (response_error
!= 0) {
853 FREE(new_wrapper
, M_NETAGENT
);
857 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
858 netagent_post_event(new_wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
);
861 return response_error
;
865 netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
866 u_int32_t payload_length
, mbuf_t packet
, int offset
)
870 struct netagent_wrapper
*new_wrapper
= NULL
;
871 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
872 uuid_t netagent_uuid
;
873 uuid_clear(netagent_uuid
);
875 if (session
== NULL
) {
876 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
877 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
881 if (session
->wrapper
!= NULL
) {
882 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
883 response_error
= NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED
;
887 if (payload_length
< sizeof(struct netagent
)) {
888 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%u < %lu)",
889 payload_length
, sizeof(struct netagent
));
890 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
894 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
895 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
896 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, error %d data_size %d",
898 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
902 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
903 if (new_wrapper
== NULL
) {
904 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
905 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
909 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
911 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
,
912 &new_wrapper
->netagent
);
914 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
915 FREE(new_wrapper
, M_NETAGENT
);
916 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
920 (void)netagent_handle_register_inner(session
, new_wrapper
);
922 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
923 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
);
924 netagent_post_event(new_wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
);
927 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
, response_error
);
931 netagent_unregister(netagent_session_t _session
)
933 struct netagent_session
*session
= (struct netagent_session
*)_session
;
934 if (session
== NULL
) {
935 NETAGENTLOG0(LOG_ERR
, "Cannot unregister NULL session");
939 netagent_unregister_session_wrapper(session
);
944 netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
945 u_int32_t payload_length
)
947 #pragma unused(payload, payload_length)
948 u_int32_t response_error
= 0;
950 if (session
== NULL
) {
951 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
952 response_error
= EINVAL
;
956 netagent_unregister_session_wrapper(session
);
959 return response_error
;
963 netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
964 u_int32_t payload_length
, mbuf_t packet
, int offset
)
966 #pragma unused(payload_length, packet, offset)
967 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
969 if (session
== NULL
) {
970 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
971 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
975 netagent_unregister_session_wrapper(session
);
977 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
);
980 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
, response_error
);
984 netagent_send_cellular_failed_event(struct netagent_wrapper
*wrapper
,
985 pid_t pid
, uuid_t proc_uuid
)
987 if (strncmp(wrapper
->netagent
.netagent_domain
, "Cellular", NETAGENT_DOMAINSIZE
) != 0) {
991 struct kev_netpolicy_ifdenied ev_ifdenied
;
993 bzero(&ev_ifdenied
, sizeof(ev_ifdenied
));
995 ev_ifdenied
.ev_data
.epid
= pid
;
996 uuid_copy(ev_ifdenied
.ev_data
.euuid
, proc_uuid
);
997 ev_ifdenied
.ev_if_functional_type
= IFRTYPE_FUNCTIONAL_CELLULAR
;
999 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED
, &ev_ifdenied
.ev_data
, sizeof(ev_ifdenied
));
1003 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
)
1005 u_int32_t response_error
= 0;
1007 if (agent_changed
== NULL
) {
1008 NETAGENTLOG0(LOG_ERR
, "Invalid argument: agent_changed");
1012 lck_rw_lock_exclusive(&netagent_lock
);
1014 if (uuid_compare(session
->wrapper
->netagent
.netagent_uuid
, new_wrapper
->netagent
.netagent_uuid
) != 0 ||
1015 memcmp(&session
->wrapper
->netagent
.netagent_domain
, &new_wrapper
->netagent
.netagent_domain
,
1016 sizeof(new_wrapper
->netagent
.netagent_domain
)) != 0 ||
1017 memcmp(&session
->wrapper
->netagent
.netagent_type
, &new_wrapper
->netagent
.netagent_type
,
1018 sizeof(new_wrapper
->netagent
.netagent_type
)) != 0) {
1019 lck_rw_done(&netagent_lock
);
1020 NETAGENTLOG0(LOG_ERR
, "Basic agent parameters do not match, cannot update");
1021 if (error_domain
== kNetagentErrorDomainPOSIX
) {
1022 response_error
= EINVAL
;
1023 } else if (error_domain
== kNetagentErrorDomainUserDefined
) {
1024 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE
;
1026 return response_error
;
1029 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
1030 if (session
->wrapper
->netagent
.netagent_data_size
== new_wrapper
->netagent
.netagent_data_size
&&
1031 memcmp(&session
->wrapper
->netagent
, &new_wrapper
->netagent
, sizeof(struct netagent
) + data_size
) == 0) {
1032 // Agent is exactly identical, don't increment the generation count
1034 // Make a copy of the list of pending clients, and clear the current list
1035 struct netagent_client_list_s pending_triggers_list_copy
;
1036 LIST_INIT(&pending_triggers_list_copy
);
1037 struct netagent_client
*search_client
= NULL
;
1038 struct netagent_client
*temp_client
= NULL
;
1039 LIST_FOREACH_SAFE(search_client
, &session
->wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
1040 LIST_REMOVE(search_client
, client_chain
);
1041 LIST_INSERT_HEAD(&pending_triggers_list_copy
, search_client
, client_chain
);
1043 lck_rw_done(&netagent_lock
);
1045 // Update pending client triggers without holding a lock
1046 search_client
= NULL
;
1048 LIST_FOREACH_SAFE(search_client
, &pending_triggers_list_copy
, client_chain
, temp_client
) {
1049 necp_force_update_client(search_client
->client_id
, session
->wrapper
->netagent
.netagent_uuid
, session
->wrapper
->generation
);
1050 netagent_send_cellular_failed_event(new_wrapper
, search_client
->client_pid
, search_client
->client_proc_uuid
);
1051 LIST_REMOVE(search_client
, client_chain
);
1052 FREE(search_client
, M_NETAGENT
);
1054 NETAGENTLOG0(LOG_DEBUG
, "Updated agent (no changes)");
1055 *agent_changed
= FALSE
;
1056 return response_error
;
1059 new_wrapper
->generation
= g_next_generation
++;
1060 new_wrapper
->use_count
= session
->wrapper
->use_count
;
1062 if ((new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1063 !(session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1064 netagent_active_count
++;
1065 } else if (!(new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1066 (session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
1067 netagent_active_count
> 0) {
1068 netagent_active_count
--;
1071 LIST_REMOVE(session
->wrapper
, master_chain
);
1072 netagent_free_wrapper(session
->wrapper
);
1073 session
->wrapper
= new_wrapper
;
1074 new_wrapper
->control_unit
= session
->control_unit
;
1075 new_wrapper
->event_handler
= session
->event_handler
;
1076 new_wrapper
->event_context
= session
->event_context
;
1077 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
1078 LIST_INIT(&new_wrapper
->pending_triggers_list
);
1080 NETAGENTLOG0(LOG_DEBUG
, "Updated agent");
1081 *agent_changed
= TRUE
;
1083 lck_rw_done(&netagent_lock
);
1085 return response_error
;
1089 netagent_update(netagent_session_t _session
, struct netagent
*agent
)
1091 u_int8_t agent_changed
;
1093 struct netagent_wrapper
*new_wrapper
= NULL
;
1095 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1096 if (session
== NULL
) {
1097 NETAGENTLOG0(LOG_ERR
, "Cannot update agent on NULL session");
1101 if (agent
== NULL
) {
1102 NETAGENTLOG0(LOG_ERR
, "Cannot register NULL agent");
1106 if (session
->wrapper
== NULL
) {
1107 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1111 data_size
= agent
->netagent_data_size
;
1112 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1113 NETAGENTLOG(LOG_ERR
, "Update message size (%u > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1117 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1118 if (new_wrapper
== NULL
) {
1119 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1123 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1124 memcpy(&new_wrapper
->netagent
, agent
, sizeof(struct netagent
) + data_size
);
1126 int error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1128 netagent_post_event(session
->wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
);
1129 if (agent_changed
== FALSE
) {
1130 // The session wrapper does not need the "new_wrapper" as nothing changed
1131 FREE(new_wrapper
, M_NETAGENT
);
1134 FREE(new_wrapper
, M_NETAGENT
);
1142 netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
, u_int32_t payload_length
)
1144 u_int32_t data_size
= 0;
1145 struct netagent_wrapper
*new_wrapper
= NULL
;
1146 errno_t response_error
= 0;
1147 struct netagent
*update_netagent
= (struct netagent
*)(void *)payload
;
1148 u_int8_t agent_changed
;
1150 if (session
== NULL
) {
1151 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1152 response_error
= EINVAL
;
1156 if (payload
== NULL
) {
1157 NETAGENTLOG0(LOG_ERR
, "No payload received");
1158 response_error
= EINVAL
;
1162 if (session
->wrapper
== NULL
) {
1163 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1164 response_error
= ENOENT
;
1168 if (payload_length
< sizeof(struct netagent
)) {
1169 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%u < %lu)",
1170 payload_length
, sizeof(struct netagent
));
1171 response_error
= EINVAL
;
1175 data_size
= update_netagent
->netagent_data_size
;
1176 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1177 NETAGENTLOG(LOG_ERR
, "Update message size (%u > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1178 response_error
= EINVAL
;
1182 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
1183 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
1184 response_error
= EINVAL
;
1188 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1189 if (new_wrapper
== NULL
) {
1190 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1191 response_error
= ENOMEM
;
1195 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1196 memcpy(&new_wrapper
->netagent
, update_netagent
, sizeof(struct netagent
) + data_size
);
1198 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1199 if (response_error
== 0) {
1200 netagent_post_event(session
->wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
);
1201 if (agent_changed
== FALSE
) {
1202 // The session wrapper does not need the "new_wrapper" as nothing changed
1203 FREE(new_wrapper
, M_NETAGENT
);
1206 FREE(new_wrapper
, M_NETAGENT
);
1210 return response_error
;
1214 netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
1215 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1219 struct netagent_wrapper
*new_wrapper
= NULL
;
1220 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1221 u_int8_t agent_changed
;
1223 if (session
== NULL
) {
1224 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1225 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1229 if (session
->wrapper
== NULL
) {
1230 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1231 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1235 if (payload_length
< sizeof(struct netagent
)) {
1236 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%u < %lu)",
1237 payload_length
, sizeof(struct netagent
));
1238 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1242 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
1243 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
1244 NETAGENTLOG(LOG_ERR
, "Update message size could not be read, error %d data_size %d",
1246 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1250 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1251 if (new_wrapper
== NULL
) {
1252 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1253 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1257 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1259 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
, &new_wrapper
->netagent
);
1261 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
1262 FREE(new_wrapper
, M_NETAGENT
);
1263 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1267 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainUserDefined
);
1268 if (response_error
!= 0) {
1269 FREE(new_wrapper
, M_NETAGENT
);
1273 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
);
1274 netagent_post_event(session
->wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
);
1276 if (agent_changed
== FALSE
) {
1277 // The session wrapper does not need the "new_wrapper" as nothing changed
1278 FREE(new_wrapper
, M_NETAGENT
);
1283 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
, response_error
);
1287 netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
1288 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1290 #pragma unused(payload_length, packet, offset)
1291 u_int8_t
*response
= NULL
;
1292 u_int8_t
*cursor
= NULL
;
1293 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1295 if (session
== NULL
) {
1296 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1297 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1301 if (session
->wrapper
== NULL
) {
1302 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1303 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1307 lck_rw_lock_shared(&netagent_lock
);
1309 size_t response_size
= sizeof(struct netagent_message_header
) + sizeof(session
->wrapper
->netagent
)
1310 + session
->wrapper
->netagent
.netagent_data_size
;
1311 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
1312 if (response
== NULL
) {
1317 cursor
= netagent_buffer_write_message_header(cursor
, NETAGENT_MESSAGE_TYPE_GET
,
1318 NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0,
1319 response_size
- sizeof(struct netagent_message_header
));
1320 memcpy(cursor
, &session
->wrapper
->netagent
, sizeof(session
->wrapper
->netagent
) +
1321 session
->wrapper
->netagent
.netagent_data_size
);
1323 lck_rw_done(&netagent_lock
);
1325 if (!netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
)) {
1326 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
1328 FREE(response
, M_NETAGENT
);
1331 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_GET
, message_id
, response_error
);
1335 netagent_assign_nexus(netagent_session_t _session
, uuid_t necp_client_uuid
,
1336 void *assign_message
, size_t assigned_results_length
)
1338 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1339 if (session
== NULL
) {
1340 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1344 if (session
->wrapper
== NULL
) {
1345 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1349 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1350 int error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, necp_client_uuid
, assign_message
, assigned_results_length
);
1352 // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1353 NETAGENTLOG((error
== ENOENT
? LOG_DEBUG
: LOG_ERR
), "Client assignment failed: %d", error
);
1357 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1362 netagent_update_flow_protoctl_event(netagent_session_t _session
,
1363 uuid_t client_id
, uint32_t protoctl_event_code
,
1364 uint32_t protoctl_event_val
, uint32_t protoctl_event_tcp_seq_number
)
1366 struct netagent_session
*session
= (struct netagent_session
*)_session
;
1369 if (session
== NULL
) {
1370 NETAGENTLOG0(LOG_ERR
, "Cannot assign nexus from NULL session");
1374 if (session
->wrapper
== NULL
) {
1375 NETAGENTLOG0(LOG_ERR
, "Session has no agent");
1379 error
= necp_update_flow_protoctl_event(session
->wrapper
->netagent
.netagent_uuid
,
1380 client_id
, protoctl_event_code
, protoctl_event_val
, protoctl_event_tcp_seq_number
);
1386 netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
1387 u_int32_t payload_length
)
1389 errno_t response_error
= 0;
1390 struct netagent_assign_nexus_message
*assign_nexus_netagent
= (struct netagent_assign_nexus_message
*)(void *)payload
;
1392 u_int8_t
*assigned_results
= NULL
;
1394 if (session
== NULL
) {
1395 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1396 response_error
= ENOENT
;
1400 if (payload
== NULL
) {
1401 NETAGENTLOG0(LOG_ERR
, "No payload received");
1402 response_error
= EINVAL
;
1406 if (session
->wrapper
== NULL
) {
1407 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1408 response_error
= ENOENT
;
1412 if (payload_length
< sizeof(uuid_t
)) {
1413 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1414 response_error
= EINVAL
;
1418 memcpy(client_id
, assign_nexus_netagent
->assign_client_id
, sizeof(client_id
));
1419 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1421 if (assigned_results_length
> 0) {
1422 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1423 if (assigned_results
== NULL
) {
1424 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1425 response_error
= ENOMEM
;
1428 memcpy(assigned_results
, assign_nexus_netagent
->assign_necp_results
, assigned_results_length
);
1431 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1432 response_error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1433 if (response_error
) {
1434 // necp_assign_client_result returns POSIX errors
1435 if (assigned_results
) {
1436 FREE(assigned_results
, M_NETAGENT
);
1438 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", response_error
);
1442 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1444 return response_error
;
1449 netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
1450 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1453 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1455 u_int8_t
*assigned_results
= NULL
;
1457 if (session
== NULL
) {
1458 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1459 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1463 if (session
->wrapper
== NULL
) {
1464 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1465 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1469 if (payload_length
< sizeof(uuid_t
)) {
1470 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1471 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1475 error
= mbuf_copydata(packet
, offset
, sizeof(client_id
), &client_id
);
1477 NETAGENTLOG(LOG_ERR
, "Failed to read uuid for assign message: %d", error
);
1478 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1482 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1483 if (assigned_results_length
> 0) {
1484 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1485 if (assigned_results
== NULL
) {
1486 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1487 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1491 error
= mbuf_copydata(packet
, offset
+ sizeof(client_id
), assigned_results_length
, assigned_results
);
1493 FREE(assigned_results
, M_NETAGENT
);
1494 NETAGENTLOG(LOG_ERR
, "Failed to read assign message: %d", error
);
1495 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1500 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1501 error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1503 if (assigned_results
) {
1504 FREE(assigned_results
, M_NETAGENT
);
1506 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", error
);
1507 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN
;
1511 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1512 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
);
1515 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
, response_error
);
1519 netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
)
1521 errno_t response_error
= 0;
1522 uint64_t use_count
= 0;
1524 if (session
== NULL
) {
1525 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1526 response_error
= ENOENT
;
1530 if (payload
== NULL
) {
1531 NETAGENTLOG0(LOG_ERR
, "No payload received");
1532 response_error
= EINVAL
;
1536 if (payload_length
!= sizeof(use_count
)) {
1537 NETAGENTLOG(LOG_ERR
, "Payload length is invalid (%lu)", payload_length
);
1538 response_error
= EINVAL
;
1542 memcpy(&use_count
, payload
, sizeof(use_count
));
1544 lck_rw_lock_shared(&netagent_lock
);
1546 if (session
->wrapper
== NULL
) {
1547 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1548 response_error
= ENOENT
;
1549 lck_rw_done(&netagent_lock
);
1553 session
->wrapper
->use_count
= use_count
;
1555 lck_rw_done(&netagent_lock
);
1558 return response_error
;
1562 netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
)
1564 errno_t response_error
= 0;
1565 uint64_t use_count
= 0;
1567 if (session
== NULL
) {
1568 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1569 response_error
= ENOENT
;
1573 if (buffer
== NULL
) {
1574 NETAGENTLOG0(LOG_ERR
, "No payload received");
1575 response_error
= EINVAL
;
1579 if (*buffer_length
!= sizeof(use_count
)) {
1580 NETAGENTLOG(LOG_ERR
, "Buffer length is invalid (%lu)", *buffer_length
);
1581 response_error
= EINVAL
;
1585 lck_rw_lock_shared(&netagent_lock
);
1587 if (session
->wrapper
== NULL
) {
1588 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1589 response_error
= ENOENT
;
1590 lck_rw_done(&netagent_lock
);
1594 use_count
= session
->wrapper
->use_count
;
1595 lck_rw_done(&netagent_lock
);
1597 memcpy(buffer
, &use_count
, sizeof(use_count
));
1598 *buffer_length
= sizeof(use_count
);
1601 return response_error
;
1604 static struct netagent_wrapper
*
1605 netagent_find_agent_with_uuid(uuid_t uuid
)
1607 struct netagent_wrapper
*search_netagent
= NULL
;
1609 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1610 if (uuid_compare(search_netagent
->netagent
.netagent_uuid
, uuid
) == 0) {
1611 return search_netagent
;
1619 netagent_post_updated_interfaces(uuid_t uuid
)
1621 struct netagent_wrapper
*wrapper
= NULL
;
1622 lck_rw_lock_shared(&netagent_lock
);
1623 wrapper
= netagent_find_agent_with_uuid(uuid
);
1624 lck_rw_done(&netagent_lock
);
1626 if (wrapper
!= NULL
) {
1627 netagent_post_event(uuid
, KEV_NETAGENT_UPDATED_INTERFACES
, TRUE
);
1629 NETAGENTLOG0(LOG_DEBUG
, "Interface event with no associated agent");
1636 netagent_dump_get_data_size_locked()
1638 struct netagent_wrapper
*search_netagent
= NULL
;
1639 u_int32_t total_netagent_data_size
= 0;
1640 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1641 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1642 total_netagent_data_size
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1644 return total_netagent_data_size
;
1648 netagent_dump_copy_data_locked(u_int8_t
*buffer
, u_int32_t buffer_length
)
1650 size_t response_size
= 0;
1651 u_int8_t
*cursor
= NULL
;
1652 struct netagent_wrapper
*search_netagent
= NULL
;
1654 response_size
= buffer_length
; // We already know that buffer_length is the same as total_netagent_data_size.
1656 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1657 memcpy(cursor
, search_netagent
->netagent
.netagent_uuid
, sizeof(search_netagent
->netagent
.netagent_uuid
));
1658 cursor
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1663 netagent_ioctl(u_long cmd
, caddr_t data
)
1668 case SIOCGIFAGENTLIST32
:
1669 case SIOCGIFAGENTLIST64
: {
1670 /* Check entitlement if the client requests agent dump */
1671 errno_t cred_result
= priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES
, 0);
1672 if (cred_result
!= 0) {
1673 NETAGENTLOG0(LOG_ERR
, "Client does not hold the necessary entitlement to get netagent information");
1682 lck_rw_lock_shared(&netagent_lock
);
1684 case SIOCGIFAGENTDATA32
: {
1685 struct netagent_req32
*ifsir32
= (struct netagent_req32
*)(void *)data
;
1686 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir32
->netagent_uuid
);
1687 if (wrapper
== NULL
) {
1691 uuid_copy(ifsir32
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1692 memcpy(ifsir32
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir32
->netagent_domain
));
1693 memcpy(ifsir32
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir32
->netagent_type
));
1694 memcpy(ifsir32
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir32
->netagent_desc
));
1695 ifsir32
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1696 if (ifsir32
->netagent_data_size
== 0) {
1697 // First pass, client wants data size
1698 ifsir32
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1699 } else if (ifsir32
->netagent_data
!= USER_ADDR_NULL
&&
1700 ifsir32
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1701 // Second pass, client wants data buffer filled out
1702 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir32
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1708 case SIOCGIFAGENTDATA64
: {
1709 struct netagent_req64
*ifsir64
= (struct netagent_req64
*)(void *)data
;
1710 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir64
->netagent_uuid
);
1711 if (wrapper
== NULL
) {
1715 uuid_copy(ifsir64
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1716 memcpy(ifsir64
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir64
->netagent_domain
));
1717 memcpy(ifsir64
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir64
->netagent_type
));
1718 memcpy(ifsir64
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir64
->netagent_desc
));
1719 ifsir64
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1720 if (ifsir64
->netagent_data_size
== 0) {
1721 // First pass, client wants data size
1722 ifsir64
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1723 } else if (ifsir64
->netagent_data
!= USER_ADDR_NULL
&&
1724 ifsir64
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1725 // Second pass, client wants data buffer filled out
1726 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir64
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1732 case SIOCGIFAGENTLIST32
: {
1733 struct netagentlist_req32
*ifsir32
= (struct netagentlist_req32
*)(void *)data
;
1734 if (ifsir32
->data_size
== 0) {
1735 // First pass, client wants data size
1736 ifsir32
->data_size
= netagent_dump_get_data_size_locked();
1737 } else if (ifsir32
->data
!= USER_ADDR_NULL
&&
1738 ifsir32
->data_size
> 0 &&
1739 ifsir32
->data_size
== netagent_dump_get_data_size_locked()) {
1740 // Second pass, client wants data buffer filled out
1741 u_int8_t
*response
= NULL
;
1742 MALLOC(response
, u_int8_t
*, ifsir32
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1743 if (response
== NULL
) {
1748 netagent_dump_copy_data_locked(response
, ifsir32
->data_size
);
1749 error
= copyout(response
, ifsir32
->data
, ifsir32
->data_size
);
1750 FREE(response
, M_NETAGENT
);
1756 case SIOCGIFAGENTLIST64
: {
1757 struct netagentlist_req64
*ifsir64
= (struct netagentlist_req64
*)(void *)data
;
1758 if (ifsir64
->data_size
== 0) {
1759 // First pass, client wants data size
1760 ifsir64
->data_size
= netagent_dump_get_data_size_locked();
1761 } else if (ifsir64
->data
!= USER_ADDR_NULL
&&
1762 ifsir64
->data_size
> 0 &&
1763 ifsir64
->data_size
== netagent_dump_get_data_size_locked()) {
1764 // Second pass, client wants data buffer filled out
1765 u_int8_t
*response
= NULL
;
1766 MALLOC(response
, u_int8_t
*, ifsir64
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1767 if (response
== NULL
) {
1772 netagent_dump_copy_data_locked(response
, ifsir64
->data_size
);
1773 error
= copyout(response
, ifsir64
->data
, ifsir64
->data_size
);
1774 FREE(response
, M_NETAGENT
);
1785 lck_rw_done(&netagent_lock
);
1790 netagent_get_flags(uuid_t uuid
)
1792 u_int32_t flags
= 0;
1793 lck_rw_lock_shared(&netagent_lock
);
1794 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1795 if (wrapper
!= NULL
) {
1796 flags
= wrapper
->netagent
.netagent_flags
;
1798 NETAGENTLOG0(LOG_DEBUG
, "Flags requested for invalid netagent");
1800 lck_rw_done(&netagent_lock
);
1806 netagent_get_generation(uuid_t uuid
)
1808 u_int32_t generation
= 0;
1809 lck_rw_lock_shared(&netagent_lock
);
1810 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1811 if (wrapper
!= NULL
) {
1812 generation
= wrapper
->generation
;
1814 NETAGENTLOG0(LOG_DEBUG
, "Generation requested for invalid netagent");
1816 lck_rw_done(&netagent_lock
);
1822 netagent_get_agent_domain_and_type(uuid_t uuid
, char *domain
, char *type
)
1825 if (domain
== NULL
|| type
== NULL
) {
1826 NETAGENTLOG(LOG_ERR
, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain
, type
);
1830 lck_rw_lock_shared(&netagent_lock
);
1831 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1832 if (wrapper
!= NULL
) {
1834 memcpy(domain
, wrapper
->netagent
.netagent_domain
, NETAGENT_DOMAINSIZE
);
1835 memcpy(type
, wrapper
->netagent
.netagent_type
, NETAGENT_TYPESIZE
);
1837 NETAGENTLOG0(LOG_ERR
, "Type requested for invalid netagent");
1839 lck_rw_done(&netagent_lock
);
1845 netagent_kernel_trigger(uuid_t uuid
)
1849 lck_rw_lock_shared(&netagent_lock
);
1850 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1851 if (wrapper
== NULL
) {
1852 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger could not be found");
1857 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_KERNEL_ACTIVATED
) == 0) {
1858 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger is not kernel activated");
1859 // Agent does not accept kernel triggers
1864 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1865 // Agent already active
1866 NETAGENTLOG0(LOG_INFO
, "Requested netagent for kernel trigger is already active");
1871 error
= netagent_send_trigger(wrapper
, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
1872 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent from kernel (error %d)", error
);
1874 lck_rw_done(&netagent_lock
);
1879 netagent_client_message_with_params(uuid_t agent_uuid
,
1880 uuid_t necp_client_uuid
,
1883 u_int8_t message_type
,
1884 struct necp_client_nexus_parameters
*parameters
,
1885 void **assigned_results
,
1886 size_t *assigned_results_length
)
1890 if (message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
&&
1891 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT
&&
1892 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT
&&
1893 message_type
!= NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
&&
1894 message_type
!= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
&&
1895 message_type
!= NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1896 NETAGENTLOG(LOG_ERR
, "Client netagent message type (%d) is invalid", message_type
);
1900 lck_rw_lock_shared(&netagent_lock
);
1901 bool should_unlock
= TRUE
;
1902 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1903 if (wrapper
== NULL
) {
1904 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
1909 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1910 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
1911 // Agent does not accept user triggers
1912 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1916 pid_t report_pid
= 0;
1917 uuid_t report_proc_uuid
= {};
1918 if (parameters
!= NULL
) {
1919 report_pid
= parameters
->epid
;
1920 uuid_copy(report_proc_uuid
, parameters
->euuid
);
1922 struct proc
*p
= current_proc();
1924 report_pid
= proc_pid(p
);
1925 proc_getexecutableuuid(p
, report_proc_uuid
, sizeof(report_proc_uuid
));
1928 netagent_send_cellular_failed_event(wrapper
, report_pid
, report_proc_uuid
);
1931 } else if (message_type
== NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
||
1932 message_type
== NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
||
1933 message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1934 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_NEXUS_PROVIDER
) == 0) {
1935 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance is not a nexus provider");
1936 // Agent is not a nexus provider
1941 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) == 0) {
1943 NETAGENTLOG0(LOG_INFO
, "Requested netagent for nexus instance is not active");
1949 if (wrapper
->control_unit
== 0) {
1950 if (wrapper
->event_handler
== NULL
) {
1951 // No event handler registered for kernel agent
1954 // We hold the shared lock during the event handler callout, so it is expected
1955 // that the event handler will not lead to any registrations or unregistrations
1956 // of network agents.
1957 error
= wrapper
->event_handler(message_type
, necp_client_uuid
, pid
, handle
,
1958 wrapper
->event_context
, parameters
,
1959 assigned_results
, assigned_results_length
);
1961 VERIFY(assigned_results
== NULL
|| *assigned_results
== NULL
);
1962 VERIFY(assigned_results_length
== NULL
|| *assigned_results_length
== 0);
1966 // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
1967 if (message_type
== NETAGENT_MESSAGE_TYPE_ABORT_NEXUS
) {
1968 message_type
= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
;
1971 error
= netagent_send_client_message(wrapper
, necp_client_uuid
, message_type
);
1972 if (error
== 0 && message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1973 if (lck_rw_lock_shared_to_exclusive(&netagent_lock
)) {
1974 // Grab the lock exclusively to add a pending client to the list
1975 struct netagent_client
*new_pending_client
= NULL
;
1976 MALLOC(new_pending_client
, struct netagent_client
*, sizeof(*new_pending_client
), M_NETAGENT
, M_WAITOK
);
1977 if (new_pending_client
== NULL
) {
1978 NETAGENTLOG0(LOG_ERR
, "Failed to allocate client for trigger");
1980 uuid_copy(new_pending_client
->client_id
, necp_client_uuid
);
1981 if (parameters
!= NULL
) {
1982 new_pending_client
->client_pid
= parameters
->epid
;
1983 uuid_copy(new_pending_client
->client_proc_uuid
, parameters
->euuid
);
1985 struct proc
*p
= current_proc();
1987 new_pending_client
->client_pid
= proc_pid(p
);
1988 proc_getexecutableuuid(p
, new_pending_client
->client_proc_uuid
, sizeof(new_pending_client
->client_proc_uuid
));
1991 LIST_INSERT_HEAD(&wrapper
->pending_triggers_list
, new_pending_client
, client_chain
);
1994 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
1995 should_unlock
= FALSE
;
1999 NETAGENTLOG(((error
&& error
!= ENOENT
) ? LOG_ERR
: LOG_INFO
), "Send message %d for client (error %d)", message_type
, error
);
2000 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
2001 uuid_string_t uuid_str
;
2002 uuid_unparse(agent_uuid
, uuid_str
);
2003 NETAGENTLOG(LOG_NOTICE
, "Triggered network agent %s, error = %d", uuid_str
, error
);
2006 if (should_unlock
) {
2007 lck_rw_done(&netagent_lock
);
2013 netagent_client_message(uuid_t agent_uuid
, uuid_t necp_client_uuid
, pid_t pid
, void *handle
, u_int8_t message_type
)
2015 return netagent_client_message_with_params(agent_uuid
, necp_client_uuid
, pid
, handle
, message_type
, NULL
, NULL
, NULL
);
2019 netagent_use(uuid_t agent_uuid
, uint64_t *out_use_count
)
2023 lck_rw_lock_exclusive(&netagent_lock
);
2024 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2025 if (wrapper
== NULL
) {
2026 NETAGENTLOG0(LOG_ERR
, "netagent_assert: Requested netagent UUID is not registered");
2031 uint64_t current_count
= wrapper
->use_count
;
2032 wrapper
->use_count
++;
2034 if (out_use_count
!= NULL
) {
2035 *out_use_count
= current_count
;
2039 lck_rw_done(&netagent_lock
);
2044 netagent_copyout(uuid_t agent_uuid
, user_addr_t user_addr
, u_int32_t user_size
)
2048 lck_rw_lock_shared(&netagent_lock
);
2049 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2050 if (wrapper
== NULL
) {
2051 NETAGENTLOG0(LOG_DEBUG
, "Requested netagent for nexus instance could not be found");
2056 u_int32_t total_size
= (sizeof(struct netagent
) + wrapper
->netagent
.netagent_data_size
);
2057 if (user_size
< total_size
) {
2058 NETAGENTLOG(LOG_ERR
, "Provided user buffer is too small (%u < %u)", user_size
, total_size
);
2063 error
= copyout(&wrapper
->netagent
, user_addr
, total_size
);
2065 NETAGENTLOG((error
? LOG_ERR
: LOG_DEBUG
), "Copied agent content (error %d)", error
);
2067 lck_rw_done(&netagent_lock
);
2072 netagent_trigger(struct proc
*p
, struct netagent_trigger_args
*uap
, int32_t *retval
)
2074 #pragma unused(p, retval)
2079 NETAGENTLOG0(LOG_ERR
, "uap == NULL");
2083 if (uap
->agent_uuid
) {
2084 if (uap
->agent_uuidlen
!= sizeof(uuid_t
)) {
2085 NETAGENTLOG(LOG_ERR
, "Incorrect length (got %llu, expected %lu)",
2086 uap
->agent_uuidlen
, sizeof(uuid_t
));
2090 error
= copyin(uap
->agent_uuid
, agent_uuid
, sizeof(uuid_t
));
2092 NETAGENTLOG(LOG_ERR
, "copyin error (%d)", error
);
2097 if (uuid_is_null(agent_uuid
)) {
2098 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is empty");
2102 lck_rw_lock_shared(&netagent_lock
);
2103 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
2104 if (wrapper
== NULL
) {
2105 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not registered");
2110 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
2111 // Agent does not accept triggers
2112 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not eligible for triggering");
2117 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
2118 // Agent already active
2119 NETAGENTLOG0(LOG_INFO
, "Requested netagent UUID is already active");
2124 error
= netagent_send_trigger(wrapper
, p
, NETAGENT_TRIGGER_FLAG_USER
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
2125 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent (error %d)", error
);
2127 lck_rw_done(&netagent_lock
);