2 * Copyright (c) 2014, 2016, 2017 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
;
85 struct netagent_client_list_s pending_triggers_list
;
86 struct netagent netagent
;
89 struct netagent_session
{
90 u_int32_t control_unit
;
91 struct netagent_wrapper
*wrapper
;
95 kNetagentErrorDomainPOSIX
= 0,
96 kNetagentErrorDomainUserDefined
= 1,
97 } netagent_error_domain_t
;
99 static LIST_HEAD(_netagent_list
, netagent_wrapper
) master_netagent_list
;
101 // Protected by netagent_lock
102 static u_int32_t g_next_generation
= 1;
104 static kern_ctl_ref netagent_kctlref
;
105 static u_int32_t netagent_family
;
106 static OSMallocTag netagent_malloc_tag
;
107 static lck_grp_attr_t
*netagent_grp_attr
= NULL
;
108 static lck_attr_t
*netagent_mtx_attr
= NULL
;
109 static lck_grp_t
*netagent_mtx_grp
= NULL
;
110 decl_lck_rw_data(static, netagent_lock
);
112 static errno_t
netagent_register_control(void);
113 static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
115 static errno_t
netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
);
116 static errno_t
netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
117 mbuf_t m
, int flags
);
118 static void netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
);
119 static errno_t
netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
120 int opt
, void *data
, size_t *len
);
121 static errno_t
netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
,
122 int opt
, void *data
, size_t len
);
124 static int netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
);
126 static struct netagent_session
*netagent_create_session(u_int32_t control_unit
);
127 static void netagent_delete_session(struct netagent_session
*session
);
130 static void netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
131 u_int32_t payload_length
, mbuf_t packet
, int offset
);
132 static errno_t
netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
133 u_int32_t payload_length
);
136 static void netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
137 u_int32_t payload_length
, mbuf_t packet
, int offset
);
138 static errno_t
netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
139 u_int32_t payload_length
);
142 static void netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
143 u_int32_t payload_length
, mbuf_t packet
, int offset
);
144 static errno_t
netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
145 u_int32_t payload_length
);
148 static void netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
149 u_int32_t payload_length
, mbuf_t packet
, int offset
);
150 static errno_t
netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
151 u_int32_t payload_length
);
153 // Set/get assert count
154 static errno_t
netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
);
155 static errno_t
netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
);
157 static void netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
158 u_int32_t payload_length
, mbuf_t packet
, int offset
);
160 static struct netagent_wrapper
*netagent_find_agent_with_uuid(uuid_t uuid
);
167 result
= netagent_register_control();
172 netagent_grp_attr
= lck_grp_attr_alloc_init();
173 if (netagent_grp_attr
== NULL
) {
174 NETAGENTLOG0(LOG_ERR
, "lck_grp_attr_alloc_init failed");
179 netagent_mtx_grp
= lck_grp_alloc_init(NETAGENT_CONTROL_NAME
, netagent_grp_attr
);
180 if (netagent_mtx_grp
== NULL
) {
181 NETAGENTLOG0(LOG_ERR
, "lck_grp_alloc_init failed");
186 netagent_mtx_attr
= lck_attr_alloc_init();
187 if (netagent_mtx_attr
== NULL
) {
188 NETAGENTLOG0(LOG_ERR
, "lck_attr_alloc_init failed");
193 lck_rw_init(&netagent_lock
, netagent_mtx_grp
, netagent_mtx_attr
);
195 LIST_INIT(&master_netagent_list
);
199 if (netagent_mtx_attr
!= NULL
) {
200 lck_attr_free(netagent_mtx_attr
);
201 netagent_mtx_attr
= NULL
;
203 if (netagent_mtx_grp
!= NULL
) {
204 lck_grp_free(netagent_mtx_grp
);
205 netagent_mtx_grp
= NULL
;
207 if (netagent_grp_attr
!= NULL
) {
208 lck_grp_attr_free(netagent_grp_attr
);
209 netagent_grp_attr
= NULL
;
211 if (netagent_kctlref
!= NULL
) {
212 ctl_deregister(netagent_kctlref
);
213 netagent_kctlref
= NULL
;
220 netagent_register_control(void)
222 struct kern_ctl_reg kern_ctl
;
225 // Create a tag to allocate memory
226 netagent_malloc_tag
= OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME
, OSMT_DEFAULT
);
228 // Find a unique value for our interface family
229 result
= mbuf_tag_id_find(NETAGENT_CONTROL_NAME
, &netagent_family
);
231 NETAGENTLOG(LOG_ERR
, "mbuf_tag_id_find_internal failed: %d", result
);
235 bzero(&kern_ctl
, sizeof(kern_ctl
));
236 strlcpy(kern_ctl
.ctl_name
, NETAGENT_CONTROL_NAME
, sizeof(kern_ctl
.ctl_name
));
237 kern_ctl
.ctl_name
[sizeof(kern_ctl
.ctl_name
) - 1] = 0;
238 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
; // Require root
239 kern_ctl
.ctl_sendsize
= 64 * 1024;
240 kern_ctl
.ctl_recvsize
= 64 * 1024;
241 kern_ctl
.ctl_connect
= netagent_ctl_connect
;
242 kern_ctl
.ctl_disconnect
= netagent_ctl_disconnect
;
243 kern_ctl
.ctl_send
= netagent_ctl_send
;
244 kern_ctl
.ctl_rcvd
= netagent_ctl_rcvd
;
245 kern_ctl
.ctl_setopt
= netagent_ctl_setopt
;
246 kern_ctl
.ctl_getopt
= netagent_ctl_getopt
;
248 result
= ctl_register(&kern_ctl
, &netagent_kctlref
);
250 NETAGENTLOG(LOG_ERR
, "ctl_register failed: %d", result
);
258 netagent_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
, void **unitinfo
)
260 #pragma unused(kctlref)
261 *unitinfo
= netagent_create_session(sac
->sc_unit
);
262 if (*unitinfo
== NULL
) {
263 // Could not allocate session
271 netagent_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
)
273 #pragma unused(kctlref, unit)
274 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
275 if (session
!= NULL
) {
276 netagent_delete_session(session
);
284 netagent_post_event(uuid_t agent_uuid
, u_int32_t event_code
, bool update_necp
)
287 necp_update_all_clients();
290 struct kev_msg ev_msg
;
291 memset(&ev_msg
, 0, sizeof(ev_msg
));
293 struct kev_netagent_data event_data
;
295 ev_msg
.vendor_code
= KEV_VENDOR_APPLE
;
296 ev_msg
.kev_class
= KEV_NETWORK_CLASS
;
297 ev_msg
.kev_subclass
= KEV_NETAGENT_SUBCLASS
;
298 ev_msg
.event_code
= event_code
;
300 uuid_copy(event_data
.netagent_uuid
, agent_uuid
);
301 ev_msg
.dv
[0].data_ptr
= &event_data
;
302 ev_msg
.dv
[0].data_length
= sizeof(event_data
);
304 kev_post_msg(&ev_msg
);
309 netagent_buffer_write_message_header(u_int8_t
*buffer
, u_int8_t message_type
, u_int8_t flags
,
310 u_int32_t message_id
, u_int32_t error
, u_int32_t payload_length
)
312 ((struct netagent_message_header
*)(void *)buffer
)->message_type
= message_type
;
313 ((struct netagent_message_header
*)(void *)buffer
)->message_flags
= flags
;
314 ((struct netagent_message_header
*)(void *)buffer
)->message_id
= message_id
;
315 ((struct netagent_message_header
*)(void *)buffer
)->message_error
= error
;
316 ((struct netagent_message_header
*)(void *)buffer
)->message_payload_length
= payload_length
;
317 return (buffer
+ sizeof(struct netagent_message_header
));
321 netagent_send_ctl_data(u_int32_t control_unit
, u_int8_t
*buffer
, size_t buffer_size
)
323 if (netagent_kctlref
== NULL
|| control_unit
== 0 || buffer
== NULL
|| buffer_size
== 0) {
327 return ctl_enqueuedata(netagent_kctlref
, control_unit
, buffer
, buffer_size
, CTL_DATA_EOR
);
331 netagent_send_trigger(struct netagent_wrapper
*wrapper
, struct proc
*p
, u_int32_t flags
, u_int32_t trigger_type
)
334 struct netagent_trigger_message
*trigger_message
= NULL
;
335 u_int8_t
*trigger
= NULL
;
336 size_t trigger_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_trigger_message
);
338 MALLOC(trigger
, u_int8_t
*, trigger_size
, M_NETAGENT
, M_WAITOK
);
339 if (trigger
== NULL
) {
343 (void)netagent_buffer_write_message_header(trigger
, trigger_type
, 0, 0, 0, sizeof(struct netagent_trigger_message
));
345 trigger_message
= (struct netagent_trigger_message
*)(void *)(trigger
+ sizeof(struct netagent_message_header
));
346 trigger_message
->trigger_flags
= flags
;
348 trigger_message
->trigger_pid
= proc_pid(p
);
349 proc_getexecutableuuid(p
, trigger_message
->trigger_proc_uuid
, sizeof(trigger_message
->trigger_proc_uuid
));
351 trigger_message
->trigger_pid
= 0;
352 uuid_clear(trigger_message
->trigger_proc_uuid
);
355 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)trigger
, trigger_size
))) {
356 NETAGENTLOG(LOG_ERR
, "Failed to send trigger message on control unit %d", wrapper
->control_unit
);
359 FREE(trigger
, M_NETAGENT
);
364 netagent_send_client_message(struct netagent_wrapper
*wrapper
, uuid_t client_id
, u_int8_t message_type
)
367 struct netagent_client_message
*client_message
= NULL
;
368 u_int8_t
*message
= NULL
;
369 size_t message_size
= sizeof(struct netagent_message_header
) + sizeof(struct netagent_client_message
);
371 MALLOC(message
, u_int8_t
*, message_size
, M_NETAGENT
, M_WAITOK
);
372 if (message
== NULL
) {
376 (void)netagent_buffer_write_message_header(message
, message_type
, 0, 0, 0, sizeof(struct netagent_client_message
));
378 client_message
= (struct netagent_client_message
*)(void *)(message
+ sizeof(struct netagent_message_header
));
379 uuid_copy(client_message
->client_id
, client_id
);
381 if ((error
= netagent_send_ctl_data(wrapper
->control_unit
, (u_int8_t
*)message
, message_size
))) {
382 NETAGENTLOG(LOG_ERR
, "Failed to send client message %d on control unit %d", message_type
, wrapper
->control_unit
);
385 FREE(message
, M_NETAGENT
);
390 netagent_send_success_response(struct netagent_session
*session
, u_int8_t message_type
, u_int32_t message_id
)
393 u_int8_t
*response
= NULL
;
394 size_t response_size
= sizeof(struct netagent_message_header
);
395 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
396 if (response
== NULL
) {
399 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0, 0);
401 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
402 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
405 FREE(response
, M_NETAGENT
);
410 netagent_send_error_response(struct netagent_session
*session
, u_int8_t message_type
,
411 u_int32_t message_id
, u_int32_t error_code
)
414 u_int8_t
*response
= NULL
;
415 size_t response_size
= sizeof(struct netagent_message_header
);
416 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
417 if (response
== NULL
) {
420 (void)netagent_buffer_write_message_header(response
, message_type
, NETAGENT_MESSAGE_FLAGS_RESPONSE
,
421 message_id
, error_code
, 0);
423 if ((error
= netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
))) {
424 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
427 FREE(response
, M_NETAGENT
);
432 netagent_ctl_send(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, mbuf_t packet
, int flags
)
434 #pragma unused(kctlref, unit, flags)
435 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
436 struct netagent_message_header header
;
439 if (session
== NULL
) {
440 NETAGENTLOG0(LOG_ERR
, "Got a NULL session");
445 if (mbuf_pkthdr_len(packet
) < sizeof(header
)) {
446 NETAGENTLOG(LOG_ERR
, "Got a bad packet, length (%lu) < sizeof header (%lu)",
447 mbuf_pkthdr_len(packet
), sizeof(header
));
452 error
= mbuf_copydata(packet
, 0, sizeof(header
), &header
);
454 NETAGENTLOG(LOG_ERR
, "mbuf_copydata failed for the header: %d", error
);
459 switch (header
.message_type
) {
460 case NETAGENT_MESSAGE_TYPE_REGISTER
: {
461 netagent_handle_register_message(session
, header
.message_id
, header
.message_payload_length
,
462 packet
, sizeof(header
));
465 case NETAGENT_MESSAGE_TYPE_UNREGISTER
: {
466 netagent_handle_unregister_message(session
, header
.message_id
, header
.message_payload_length
,
467 packet
, sizeof(header
));
470 case NETAGENT_MESSAGE_TYPE_UPDATE
: {
471 netagent_handle_update_message(session
, header
.message_id
, header
.message_payload_length
,
472 packet
, sizeof(header
));
475 case NETAGENT_MESSAGE_TYPE_GET
: {
476 netagent_handle_get(session
, header
.message_id
, header
.message_payload_length
,
477 packet
, sizeof(header
));
480 case NETAGENT_MESSAGE_TYPE_ASSERT
: {
481 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
484 case NETAGENT_MESSAGE_TYPE_UNASSERT
: {
485 NETAGENTLOG0(LOG_ERR
, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
488 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
: {
489 netagent_handle_assign_nexus_message(session
, header
.message_id
, header
.message_payload_length
,
490 packet
, sizeof(header
));
494 NETAGENTLOG(LOG_ERR
, "Received unknown message type %d", header
.message_type
);
495 netagent_send_error_response(session
, header
.message_type
, header
.message_id
,
496 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE
);
507 netagent_ctl_rcvd(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int flags
)
509 #pragma unused(kctlref, unit, unitinfo, flags)
514 netagent_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
515 void *data
, size_t *len
)
517 #pragma unused(kctlref, unit)
518 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
521 if (session
== NULL
) {
522 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
528 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
529 NETAGENTLOG0(LOG_DEBUG
, "Request to get use count");
530 error
= netagent_handle_use_count_getopt(session
, data
, len
);
534 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
544 netagent_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t unit
, void *unitinfo
, int opt
,
545 void *data
, size_t len
)
547 #pragma unused(kctlref, unit)
548 struct netagent_session
*session
= (struct netagent_session
*)unitinfo
;
551 if (session
== NULL
) {
552 NETAGENTLOG0(LOG_ERR
, "Received a NULL session");
558 case NETAGENT_OPTION_TYPE_REGISTER
: {
559 NETAGENTLOG0(LOG_DEBUG
, "Request for registration");
560 error
= netagent_handle_register_setopt(session
, data
, len
);
563 case NETAGENT_OPTION_TYPE_UPDATE
: {
564 NETAGENTLOG0(LOG_DEBUG
, "Request for update");
565 error
= netagent_handle_update_setopt(session
, data
, len
);
568 case NETAGENT_OPTION_TYPE_UNREGISTER
: {
569 NETAGENTLOG0(LOG_DEBUG
, "Request for unregistration");
570 error
= netagent_handle_unregister_setopt(session
, data
, len
);
573 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS
: {
574 NETAGENTLOG0(LOG_DEBUG
, "Request for assigning nexus");
575 error
= netagent_handle_assign_nexus_setopt(session
, data
, len
);
578 case NETAGENT_OPTION_TYPE_USE_COUNT
: {
579 NETAGENTLOG0(LOG_DEBUG
, "Request to set use count");
580 error
= netagent_handle_use_count_setopt(session
, data
, len
);
584 NETAGENTLOG0(LOG_ERR
, "Received unknown option");
593 // Session Management
594 static struct netagent_session
*
595 netagent_create_session(u_int32_t control_unit
)
597 struct netagent_session
*new_session
= NULL
;
599 MALLOC(new_session
, struct netagent_session
*, sizeof(*new_session
), M_NETAGENT
, M_WAITOK
);
600 if (new_session
== NULL
) {
603 NETAGENTLOG(LOG_DEBUG
, "Create agent session, control unit %d", control_unit
);
604 memset(new_session
, 0, sizeof(*new_session
));
605 new_session
->control_unit
= control_unit
;
606 new_session
->wrapper
= NULL
;
608 return (new_session
);
612 netagent_free_wrapper(struct netagent_wrapper
*wrapper
)
614 // Free any pending client triggers
615 struct netagent_client
*search_client
= NULL
;
616 struct netagent_client
*temp_client
= NULL
;
617 LIST_FOREACH_SAFE(search_client
, &wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
618 LIST_REMOVE(search_client
, client_chain
);
619 FREE(search_client
, M_NETAGENT
);
622 // Free wrapper itself
623 FREE(wrapper
, M_NETAGENT
);
627 netagent_unregister_session_wrapper(struct netagent_session
*session
)
629 bool unregistered
= FALSE
;
630 uuid_t unregistered_uuid
;
631 struct netagent_wrapper
*wrapper
= NULL
;
632 lck_rw_lock_exclusive(&netagent_lock
);
633 if (session
!= NULL
) {
634 wrapper
= session
->wrapper
;
635 if (wrapper
!= NULL
) {
636 if (netagent_registered_count
> 0) {
637 netagent_registered_count
--;
639 if ((session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
640 netagent_active_count
> 0) {
641 netagent_active_count
--;
644 LIST_REMOVE(wrapper
, master_chain
);
647 uuid_copy(unregistered_uuid
, session
->wrapper
->netagent
.netagent_uuid
);
649 netagent_free_wrapper(session
->wrapper
);
650 session
->wrapper
= NULL
;
651 NETAGENTLOG0(LOG_DEBUG
, "Unregistered agent");
654 lck_rw_done(&netagent_lock
);
657 ifnet_clear_netagent(unregistered_uuid
);
658 netagent_post_event(unregistered_uuid
, KEV_NETAGENT_UNREGISTERED
, TRUE
);
663 netagent_delete_session(struct netagent_session
*session
)
665 if (session
!= NULL
) {
666 netagent_unregister_session_wrapper(session
);
667 FREE(session
, M_NETAGENT
);
672 netagent_packet_get_netagent_data_size(mbuf_t packet
, int offset
, int *err
)
676 struct netagent netagent_peek
;
677 memset(&netagent_peek
, 0, sizeof(netagent_peek
));
681 error
= mbuf_copydata(packet
, offset
, sizeof(netagent_peek
), &netagent_peek
);
687 return (netagent_peek
.netagent_data_size
);
691 netagent_handle_register_inner(struct netagent_session
*session
, struct netagent_wrapper
*new_wrapper
)
693 lck_rw_lock_exclusive(&netagent_lock
);
695 new_wrapper
->control_unit
= session
->control_unit
;
696 new_wrapper
->generation
= g_next_generation
++;
698 session
->wrapper
= new_wrapper
;
699 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
700 LIST_INIT(&new_wrapper
->pending_triggers_list
);
702 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
703 netagent_registered_count
++;
704 if (new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) {
705 netagent_active_count
++;
708 lck_rw_done(&netagent_lock
);
714 netagent_handle_register_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
715 u_int32_t payload_length
)
718 struct netagent_wrapper
*new_wrapper
= NULL
;
719 u_int32_t response_error
= 0;
720 struct netagent
*register_netagent
= (struct netagent
*)(void *)payload
;
722 if (session
== NULL
) {
723 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
724 response_error
= EINVAL
;
728 if (payload
== NULL
) {
729 NETAGENTLOG0(LOG_ERR
, "No payload received");
730 response_error
= EINVAL
;
734 if (session
->wrapper
!= NULL
) {
735 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
736 response_error
= EINVAL
;
740 if (payload_length
< sizeof(struct netagent
)) {
741 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%d < %d)",
742 payload_length
, sizeof(struct netagent
));
743 response_error
= EINVAL
;
747 data_size
= register_netagent
->netagent_data_size
;
748 if (data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
749 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, data_size %d", data_size
);
750 response_error
= EINVAL
;
754 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
755 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
756 response_error
= EINVAL
;
760 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
761 if (new_wrapper
== NULL
) {
762 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
763 response_error
= ENOMEM
;
767 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
768 memcpy(&new_wrapper
->netagent
, register_netagent
, sizeof(struct netagent
) + data_size
);
770 response_error
= netagent_handle_register_inner(session
, new_wrapper
);
771 if (response_error
!= 0) {
772 FREE(new_wrapper
, M_NETAGENT
);
776 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
777 netagent_post_event(new_wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
);
780 return response_error
;
784 netagent_handle_register_message(struct netagent_session
*session
, u_int32_t message_id
,
785 u_int32_t payload_length
, mbuf_t packet
, int offset
)
789 struct netagent_wrapper
*new_wrapper
= NULL
;
790 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
791 uuid_t netagent_uuid
;
792 uuid_clear(netagent_uuid
);
794 if (session
== NULL
) {
795 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
796 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
800 if (session
->wrapper
!= NULL
) {
801 NETAGENTLOG0(LOG_ERR
, "Session already has a registered agent");
802 response_error
= NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED
;
806 if (payload_length
< sizeof(struct netagent
)) {
807 NETAGENTLOG(LOG_ERR
, "Register message size too small for agent: (%d < %d)",
808 payload_length
, sizeof(struct netagent
));
809 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
813 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
814 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
815 NETAGENTLOG(LOG_ERR
, "Register message size could not be read, error %d data_size %d",
817 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
821 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
822 if (new_wrapper
== NULL
) {
823 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
824 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
828 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
830 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
,
831 &new_wrapper
->netagent
);
833 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
834 FREE(new_wrapper
, M_NETAGENT
);
835 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
839 (void)netagent_handle_register_inner(session
, new_wrapper
);
841 NETAGENTLOG0(LOG_DEBUG
, "Registered new agent");
842 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
);
843 netagent_post_event(new_wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_REGISTERED
, TRUE
);
846 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_REGISTER
, message_id
, response_error
);
850 netagent_handle_unregister_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
851 u_int32_t payload_length
)
853 #pragma unused(payload, payload_length)
854 u_int32_t response_error
= 0;
856 if (session
== NULL
) {
857 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
858 response_error
= EINVAL
;
862 netagent_unregister_session_wrapper(session
);
865 return response_error
;
869 netagent_handle_unregister_message(struct netagent_session
*session
, u_int32_t message_id
,
870 u_int32_t payload_length
, mbuf_t packet
, int offset
)
872 #pragma unused(payload_length, packet, offset)
873 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
875 if (session
== NULL
) {
876 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
877 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
881 netagent_unregister_session_wrapper(session
);
883 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
);
886 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UNREGISTER
, message_id
, response_error
);
890 netagent_send_cellular_failed_event(struct netagent_wrapper
*wrapper
,
891 pid_t pid
, uuid_t proc_uuid
)
893 if (strncmp(wrapper
->netagent
.netagent_domain
, "Cellular", NETAGENT_DOMAINSIZE
) != 0) {
897 struct kev_netpolicy_ifdenied ev_ifdenied
;
899 bzero(&ev_ifdenied
, sizeof(ev_ifdenied
));
901 ev_ifdenied
.ev_data
.epid
= pid
;
902 uuid_copy(ev_ifdenied
.ev_data
.euuid
, proc_uuid
);
903 ev_ifdenied
.ev_if_functional_type
= IFRTYPE_FUNCTIONAL_CELLULAR
;
905 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED
, &ev_ifdenied
.ev_data
, sizeof(ev_ifdenied
));
909 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
)
911 u_int32_t response_error
= 0;
913 if (agent_changed
== NULL
) {
914 NETAGENTLOG0(LOG_ERR
, "Invalid argument: agent_changed");
918 lck_rw_lock_exclusive(&netagent_lock
);
920 if (uuid_compare(session
->wrapper
->netagent
.netagent_uuid
, new_wrapper
->netagent
.netagent_uuid
) != 0 ||
921 memcmp(&session
->wrapper
->netagent
.netagent_domain
, &new_wrapper
->netagent
.netagent_domain
,
922 sizeof(new_wrapper
->netagent
.netagent_domain
)) != 0 ||
923 memcmp(&session
->wrapper
->netagent
.netagent_type
, &new_wrapper
->netagent
.netagent_type
,
924 sizeof(new_wrapper
->netagent
.netagent_type
)) != 0) {
925 lck_rw_done(&netagent_lock
);
926 NETAGENTLOG0(LOG_ERR
, "Basic agent parameters do not match, cannot update");
927 if (error_domain
== kNetagentErrorDomainPOSIX
) {
928 response_error
= EINVAL
;
929 } else if (error_domain
== kNetagentErrorDomainUserDefined
) {
930 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE
;
932 return response_error
;
935 new_wrapper
->netagent
.netagent_flags
|= NETAGENT_FLAG_REGISTERED
;
936 if (session
->wrapper
->netagent
.netagent_data_size
== new_wrapper
->netagent
.netagent_data_size
&&
937 memcmp(&session
->wrapper
->netagent
, &new_wrapper
->netagent
, sizeof(struct netagent
) + data_size
) == 0) {
938 // Agent is exactly identical, don't increment the generation count
940 // Make a copy of the list of pending clients, and clear the current list
941 struct netagent_client_list_s pending_triggers_list_copy
;
942 LIST_INIT(&pending_triggers_list_copy
);
943 struct netagent_client
*search_client
= NULL
;
944 struct netagent_client
*temp_client
= NULL
;
945 LIST_FOREACH_SAFE(search_client
, &session
->wrapper
->pending_triggers_list
, client_chain
, temp_client
) {
946 LIST_REMOVE(search_client
, client_chain
);
947 LIST_INSERT_HEAD(&pending_triggers_list_copy
, search_client
, client_chain
);
949 lck_rw_done(&netagent_lock
);
951 // Update pending client triggers without holding a lock
952 search_client
= NULL
;
954 LIST_FOREACH_SAFE(search_client
, &pending_triggers_list_copy
, client_chain
, temp_client
) {
955 necp_force_update_client(search_client
->client_id
, session
->wrapper
->netagent
.netagent_uuid
);
956 netagent_send_cellular_failed_event(new_wrapper
, search_client
->client_pid
, search_client
->client_proc_uuid
);
957 LIST_REMOVE(search_client
, client_chain
);
958 FREE(search_client
, M_NETAGENT
);
960 NETAGENTLOG0(LOG_DEBUG
, "Updated agent (no changes)");
961 *agent_changed
= FALSE
;
962 return response_error
;
965 new_wrapper
->generation
= g_next_generation
++;
966 new_wrapper
->use_count
= session
->wrapper
->use_count
;
968 if ((new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
969 !(session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
970 netagent_active_count
++;
971 } else if (!(new_wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
972 (session
->wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) &&
973 netagent_active_count
> 0) {
974 netagent_active_count
--;
977 LIST_REMOVE(session
->wrapper
, master_chain
);
978 netagent_free_wrapper(session
->wrapper
);
979 session
->wrapper
= new_wrapper
;
980 new_wrapper
->control_unit
= session
->control_unit
;
981 LIST_INSERT_HEAD(&master_netagent_list
, new_wrapper
, master_chain
);
982 LIST_INIT(&new_wrapper
->pending_triggers_list
);
984 NETAGENTLOG0(LOG_DEBUG
, "Updated agent");
985 *agent_changed
= TRUE
;
987 lck_rw_done(&netagent_lock
);
989 return response_error
;
993 netagent_handle_update_setopt(struct netagent_session
*session
, u_int8_t
*payload
, u_int32_t payload_length
)
995 u_int32_t data_size
= 0;
996 struct netagent_wrapper
*new_wrapper
= NULL
;
997 errno_t response_error
= 0;
998 struct netagent
*update_netagent
= (struct netagent
*)(void *)payload
;
999 u_int8_t agent_changed
;
1001 if (session
== NULL
) {
1002 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1003 response_error
= EINVAL
;
1007 if (payload
== NULL
) {
1008 NETAGENTLOG0(LOG_ERR
, "No payload received");
1009 response_error
= EINVAL
;
1013 if (session
->wrapper
== NULL
) {
1014 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1015 response_error
= ENOENT
;
1019 if (payload_length
< sizeof(struct netagent
)) {
1020 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%d < %d)",
1021 payload_length
, sizeof(struct netagent
));
1022 response_error
= EINVAL
;
1026 data_size
= update_netagent
->netagent_data_size
;
1027 if (data_size
> NETAGENT_MAX_DATA_SIZE
) {
1028 NETAGENTLOG(LOG_ERR
, "Update message size (%u > %u) too large", data_size
, NETAGENT_MAX_DATA_SIZE
);
1029 response_error
= EINVAL
;
1033 if (payload_length
!= (sizeof(struct netagent
) + data_size
)) {
1034 NETAGENTLOG(LOG_ERR
, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent
) + data_size
), payload_length
);
1035 response_error
= EINVAL
;
1039 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1040 if (new_wrapper
== NULL
) {
1041 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1042 response_error
= ENOMEM
;
1046 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1047 memcpy(&new_wrapper
->netagent
, update_netagent
, sizeof(struct netagent
) + data_size
);
1049 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainPOSIX
);
1050 if (response_error
== 0) {
1051 netagent_post_event(session
->wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
);
1052 if (agent_changed
== FALSE
) {
1053 // The session wrapper does not need the "new_wrapper" as nothing changed
1054 FREE(new_wrapper
, M_NETAGENT
);
1057 FREE(new_wrapper
, M_NETAGENT
);
1061 return response_error
;
1065 netagent_handle_update_message(struct netagent_session
*session
, u_int32_t message_id
,
1066 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1070 struct netagent_wrapper
*new_wrapper
= NULL
;
1071 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1072 u_int8_t agent_changed
;
1074 if (session
== NULL
) {
1075 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1076 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1080 if (session
->wrapper
== NULL
) {
1081 NETAGENTLOG0(LOG_ERR
, "Session has no agent to update");
1082 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1086 if (payload_length
< sizeof(struct netagent
)) {
1087 NETAGENTLOG(LOG_ERR
, "Update message size too small for agent: (%d < %d)",
1088 payload_length
, sizeof(struct netagent
));
1089 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1093 data_size
= netagent_packet_get_netagent_data_size(packet
, offset
, &error
);
1094 if (error
|| data_size
< 0 || data_size
> NETAGENT_MAX_DATA_SIZE
) {
1095 NETAGENTLOG(LOG_ERR
, "Update message size could not be read, error %d data_size %d",
1097 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1101 MALLOC(new_wrapper
, struct netagent_wrapper
*, sizeof(*new_wrapper
) + data_size
, M_NETAGENT
, M_WAITOK
);
1102 if (new_wrapper
== NULL
) {
1103 NETAGENTLOG0(LOG_ERR
, "Failed to allocate agent");
1104 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1108 memset(new_wrapper
, 0, sizeof(*new_wrapper
) + data_size
);
1110 error
= mbuf_copydata(packet
, offset
, sizeof(struct netagent
) + data_size
, &new_wrapper
->netagent
);
1112 NETAGENTLOG(LOG_ERR
, "Failed to read data into agent structure: %d", error
);
1113 FREE(new_wrapper
, M_NETAGENT
);
1114 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1118 response_error
= netagent_handle_update_inner(session
, new_wrapper
, data_size
, &agent_changed
, kNetagentErrorDomainUserDefined
);
1119 if (response_error
!= 0) {
1120 FREE(new_wrapper
, M_NETAGENT
);
1124 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
);
1125 netagent_post_event(session
->wrapper
->netagent
.netagent_uuid
, KEV_NETAGENT_UPDATED
, agent_changed
);
1127 if (agent_changed
== FALSE
) {
1128 // The session wrapper does not need the "new_wrapper" as nothing changed
1129 FREE(new_wrapper
, M_NETAGENT
);
1134 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_UPDATE
, message_id
, response_error
);
1138 netagent_handle_get(struct netagent_session
*session
, u_int32_t message_id
,
1139 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1141 #pragma unused(payload_length, packet, offset)
1142 u_int8_t
*response
= NULL
;
1143 u_int8_t
*cursor
= NULL
;
1144 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1146 if (session
== NULL
) {
1147 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1148 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1152 if (session
->wrapper
== NULL
) {
1153 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1154 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1158 lck_rw_lock_shared(&netagent_lock
);
1160 size_t response_size
= sizeof(struct netagent_message_header
) + sizeof(session
->wrapper
->netagent
)
1161 + session
->wrapper
->netagent
.netagent_data_size
;
1162 MALLOC(response
, u_int8_t
*, response_size
, M_NETAGENT
, M_WAITOK
);
1163 if (response
== NULL
) {
1168 cursor
= netagent_buffer_write_message_header(cursor
, NETAGENT_MESSAGE_TYPE_GET
,
1169 NETAGENT_MESSAGE_FLAGS_RESPONSE
, message_id
, 0,
1170 response_size
- sizeof(struct netagent_message_header
));
1171 memcpy(cursor
, &session
->wrapper
->netagent
, sizeof(session
->wrapper
->netagent
) +
1172 session
->wrapper
->netagent
.netagent_data_size
);
1174 lck_rw_done(&netagent_lock
);
1176 if (!netagent_send_ctl_data(session
->control_unit
, (u_int8_t
*)response
, response_size
)) {
1177 NETAGENTLOG0(LOG_ERR
, "Failed to send response");
1179 FREE(response
, M_NETAGENT
);
1182 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_GET
, message_id
, response_error
);
1186 netagent_handle_assign_nexus_setopt(struct netagent_session
*session
, u_int8_t
*payload
,
1187 u_int32_t payload_length
)
1189 errno_t response_error
= 0;
1190 struct netagent_assign_nexus_message
*assign_nexus_netagent
= (struct netagent_assign_nexus_message
*)(void *)payload
;
1192 u_int8_t
*assigned_results
= NULL
;
1194 if (session
== NULL
) {
1195 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1196 response_error
= ENOENT
;
1200 if (payload
== NULL
) {
1201 NETAGENTLOG0(LOG_ERR
, "No payload received");
1202 response_error
= EINVAL
;
1206 if (session
->wrapper
== NULL
) {
1207 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1208 response_error
= ENOENT
;
1212 if (payload_length
< sizeof(uuid_t
)) {
1213 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1214 response_error
= EINVAL
;
1218 memcpy(client_id
, assign_nexus_netagent
->assign_client_id
, sizeof(client_id
));
1219 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1221 if (assigned_results_length
> 0) {
1222 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1223 if (assigned_results
== NULL
) {
1224 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1225 response_error
= ENOMEM
;
1228 memcpy(assigned_results
, assign_nexus_netagent
->assign_necp_results
, assigned_results_length
);
1231 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1232 response_error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1233 if (response_error
) {
1234 // necp_assign_client_result returns POSIX errors
1235 if (assigned_results
) {
1236 FREE(assigned_results
, M_NETAGENT
);
1238 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", response_error
);
1242 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1244 return response_error
;
1249 netagent_handle_assign_nexus_message(struct netagent_session
*session
, u_int32_t message_id
,
1250 u_int32_t payload_length
, mbuf_t packet
, int offset
)
1253 u_int32_t response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1255 u_int8_t
*assigned_results
= NULL
;
1257 if (session
== NULL
) {
1258 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1259 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1263 if (session
->wrapper
== NULL
) {
1264 NETAGENTLOG0(LOG_ERR
, "Session has no agent to get");
1265 response_error
= NETAGENT_MESSAGE_ERROR_NOT_REGISTERED
;
1269 if (payload_length
< sizeof(uuid_t
)) {
1270 NETAGENTLOG0(LOG_ERR
, "Assign message is too short");
1271 response_error
= NETAGENT_MESSAGE_ERROR_INVALID_DATA
;
1275 error
= mbuf_copydata(packet
, offset
, sizeof(client_id
), &client_id
);
1277 NETAGENTLOG(LOG_ERR
, "Failed to read uuid for assign message: %d", error
);
1278 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1282 size_t assigned_results_length
= (payload_length
- sizeof(client_id
));
1283 if (assigned_results_length
> 0) {
1284 MALLOC(assigned_results
, u_int8_t
*, assigned_results_length
, M_NETAGENT
, M_WAITOK
);
1285 if (assigned_results
== NULL
) {
1286 NETAGENTLOG(LOG_ERR
, "Failed to allocate assign message (%lu bytes)", assigned_results_length
);
1287 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1291 error
= mbuf_copydata(packet
, offset
+ sizeof(client_id
), assigned_results_length
, assigned_results
);
1293 FREE(assigned_results
, M_NETAGENT
);
1294 NETAGENTLOG(LOG_ERR
, "Failed to read assign message: %d", error
);
1295 response_error
= NETAGENT_MESSAGE_ERROR_INTERNAL
;
1300 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1301 error
= necp_assign_client_result(session
->wrapper
->netagent
.netagent_uuid
, client_id
, assigned_results
, assigned_results_length
);
1303 if (assigned_results
) {
1304 FREE(assigned_results
, M_NETAGENT
);
1306 NETAGENTLOG(LOG_ERR
, "Client assignment failed: %d", error
);
1307 response_error
= NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN
;
1311 NETAGENTLOG0(LOG_DEBUG
, "Agent assigned nexus properties to client");
1312 netagent_send_success_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
);
1315 netagent_send_error_response(session
, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS
, message_id
, response_error
);
1319 netagent_handle_use_count_setopt(struct netagent_session
*session
, u_int8_t
*payload
, size_t payload_length
)
1321 errno_t response_error
= 0;
1322 uint64_t use_count
= 0;
1324 if (session
== NULL
) {
1325 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1326 response_error
= ENOENT
;
1330 if (payload
== NULL
) {
1331 NETAGENTLOG0(LOG_ERR
, "No payload received");
1332 response_error
= EINVAL
;
1336 if (payload_length
!= sizeof(use_count
)) {
1337 NETAGENTLOG(LOG_ERR
, "Payload length is invalid (%u)", payload_length
);
1338 response_error
= EINVAL
;
1342 memcpy(&use_count
, payload
, sizeof(use_count
));
1344 lck_rw_lock_shared(&netagent_lock
);
1346 if (session
->wrapper
== NULL
) {
1347 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1348 response_error
= ENOENT
;
1349 lck_rw_done(&netagent_lock
);
1353 session
->wrapper
->use_count
= use_count
;
1355 lck_rw_done(&netagent_lock
);
1358 return response_error
;
1362 netagent_handle_use_count_getopt(struct netagent_session
*session
, u_int8_t
*buffer
, size_t *buffer_length
)
1364 errno_t response_error
= 0;
1365 uint64_t use_count
= 0;
1367 if (session
== NULL
) {
1368 NETAGENTLOG0(LOG_ERR
, "Failed to find session");
1369 response_error
= ENOENT
;
1373 if (buffer
== NULL
) {
1374 NETAGENTLOG0(LOG_ERR
, "No payload received");
1375 response_error
= EINVAL
;
1379 if (*buffer_length
!= sizeof(use_count
)) {
1380 NETAGENTLOG(LOG_ERR
, "Buffer length is invalid (%u)", buffer_length
);
1381 response_error
= EINVAL
;
1385 lck_rw_lock_shared(&netagent_lock
);
1387 if (session
->wrapper
== NULL
) {
1388 NETAGENTLOG0(LOG_ERR
, "Session has no agent registered");
1389 response_error
= ENOENT
;
1390 lck_rw_done(&netagent_lock
);
1394 use_count
= session
->wrapper
->use_count
;
1395 lck_rw_done(&netagent_lock
);
1397 memcpy(buffer
, &use_count
, sizeof(use_count
));
1398 *buffer_length
= sizeof(use_count
);
1401 return response_error
;
1404 static struct netagent_wrapper
*
1405 netagent_find_agent_with_uuid(uuid_t uuid
)
1407 struct netagent_wrapper
*search_netagent
= NULL
;
1409 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1410 if (uuid_compare(search_netagent
->netagent
.netagent_uuid
, uuid
) == 0) {
1411 return (search_netagent
);
1419 netagent_post_updated_interfaces(uuid_t uuid
)
1421 struct netagent_wrapper
*wrapper
= NULL
;
1422 lck_rw_lock_shared(&netagent_lock
);
1423 wrapper
= netagent_find_agent_with_uuid(uuid
);
1424 lck_rw_done(&netagent_lock
);
1426 if (wrapper
!= NULL
) {
1427 netagent_post_event(uuid
, KEV_NETAGENT_UPDATED_INTERFACES
, TRUE
);
1429 NETAGENTLOG0(LOG_DEBUG
, "Interface event with no associated agent");
1436 netagent_dump_get_data_size_locked()
1438 struct netagent_wrapper
*search_netagent
= NULL
;
1439 u_int32_t total_netagent_data_size
= 0;
1440 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1441 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1442 total_netagent_data_size
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1444 return total_netagent_data_size
;
1448 netagent_dump_copy_data_locked(u_int8_t
*buffer
, u_int32_t buffer_length
)
1450 size_t response_size
= 0;
1451 u_int8_t
*cursor
= NULL
;
1452 struct netagent_wrapper
*search_netagent
= NULL
;
1454 response_size
= buffer_length
; // We already know that buffer_length is the same as total_netagent_data_size.
1456 LIST_FOREACH(search_netagent
, &master_netagent_list
, master_chain
) {
1457 memcpy(cursor
, search_netagent
->netagent
.netagent_uuid
, sizeof(search_netagent
->netagent
.netagent_uuid
));
1458 cursor
+= sizeof(search_netagent
->netagent
.netagent_uuid
);
1463 netagent_ioctl(u_long cmd
, caddr_t data
)
1468 case SIOCGIFAGENTLIST32
:
1469 case SIOCGIFAGENTLIST64
: {
1470 /* Check entitlement if the client requests agent dump */
1471 errno_t cred_result
= priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES
, 0);
1472 if (cred_result
!= 0) {
1473 NETAGENTLOG0(LOG_ERR
, "Client does not hold the necessary entitlement to get netagent information");
1482 lck_rw_lock_shared(&netagent_lock
);
1484 case SIOCGIFAGENTDATA32
: {
1485 struct netagent_req32
*ifsir32
= (struct netagent_req32
*)(void *)data
;
1486 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir32
->netagent_uuid
);
1487 if (wrapper
== NULL
) {
1491 uuid_copy(ifsir32
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1492 memcpy(ifsir32
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir32
->netagent_domain
));
1493 memcpy(ifsir32
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir32
->netagent_type
));
1494 memcpy(ifsir32
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir32
->netagent_desc
));
1495 ifsir32
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1496 if (ifsir32
->netagent_data_size
== 0) {
1497 // First pass, client wants data size
1498 ifsir32
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1499 } else if (ifsir32
->netagent_data
!= USER_ADDR_NULL
&&
1500 ifsir32
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1501 // Second pass, client wants data buffer filled out
1502 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir32
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1508 case SIOCGIFAGENTDATA64
: {
1509 struct netagent_req64
*ifsir64
= (struct netagent_req64
*)(void *)data
;
1510 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(ifsir64
->netagent_uuid
);
1511 if (wrapper
== NULL
) {
1515 uuid_copy(ifsir64
->netagent_uuid
, wrapper
->netagent
.netagent_uuid
);
1516 memcpy(ifsir64
->netagent_domain
, wrapper
->netagent
.netagent_domain
, sizeof(ifsir64
->netagent_domain
));
1517 memcpy(ifsir64
->netagent_type
, wrapper
->netagent
.netagent_type
, sizeof(ifsir64
->netagent_type
));
1518 memcpy(ifsir64
->netagent_desc
, wrapper
->netagent
.netagent_desc
, sizeof(ifsir64
->netagent_desc
));
1519 ifsir64
->netagent_flags
= wrapper
->netagent
.netagent_flags
;
1520 if (ifsir64
->netagent_data_size
== 0) {
1521 // First pass, client wants data size
1522 ifsir64
->netagent_data_size
= wrapper
->netagent
.netagent_data_size
;
1523 } else if (ifsir64
->netagent_data
!= USER_ADDR_NULL
&&
1524 ifsir64
->netagent_data_size
== wrapper
->netagent
.netagent_data_size
) {
1525 // Second pass, client wants data buffer filled out
1526 error
= copyout(wrapper
->netagent
.netagent_data
, ifsir64
->netagent_data
, wrapper
->netagent
.netagent_data_size
);
1532 case SIOCGIFAGENTLIST32
: {
1533 struct netagentlist_req32
*ifsir32
= (struct netagentlist_req32
*)(void *)data
;
1534 if (ifsir32
->data_size
== 0) {
1535 // First pass, client wants data size
1536 ifsir32
->data_size
= netagent_dump_get_data_size_locked();
1537 } else if (ifsir32
->data
!= USER_ADDR_NULL
&&
1538 ifsir32
->data_size
> 0 &&
1539 ifsir32
->data_size
== netagent_dump_get_data_size_locked()) {
1540 // Second pass, client wants data buffer filled out
1541 u_int8_t
*response
= NULL
;
1542 MALLOC(response
, u_int8_t
*, ifsir32
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1543 if (response
== NULL
) {
1548 netagent_dump_copy_data_locked(response
, ifsir32
->data_size
);
1549 error
= copyout(response
, ifsir32
->data
, ifsir32
->data_size
);
1550 FREE(response
, M_NETAGENT
);
1556 case SIOCGIFAGENTLIST64
: {
1557 struct netagentlist_req64
*ifsir64
= (struct netagentlist_req64
*)(void *)data
;
1558 if (ifsir64
->data_size
== 0) {
1559 // First pass, client wants data size
1560 ifsir64
->data_size
= netagent_dump_get_data_size_locked();
1561 } else if (ifsir64
->data
!= USER_ADDR_NULL
&&
1562 ifsir64
->data_size
> 0 &&
1563 ifsir64
->data_size
== netagent_dump_get_data_size_locked()) {
1564 // Second pass, client wants data buffer filled out
1565 u_int8_t
*response
= NULL
;
1566 MALLOC(response
, u_int8_t
*, ifsir64
->data_size
, M_NETAGENT
, M_NOWAIT
| M_ZERO
);
1567 if (response
== NULL
) {
1572 netagent_dump_copy_data_locked(response
, ifsir64
->data_size
);
1573 error
= copyout(response
, ifsir64
->data
, ifsir64
->data_size
);
1574 FREE(response
, M_NETAGENT
);
1585 lck_rw_done(&netagent_lock
);
1590 netagent_get_flags(uuid_t uuid
)
1592 u_int32_t flags
= 0;
1593 lck_rw_lock_shared(&netagent_lock
);
1594 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1595 if (wrapper
!= NULL
) {
1596 flags
= wrapper
->netagent
.netagent_flags
;
1598 NETAGENTLOG0(LOG_DEBUG
, "Flags requested for invalid netagent");
1600 lck_rw_done(&netagent_lock
);
1606 netagent_get_generation(uuid_t uuid
)
1608 u_int32_t generation
= 0;
1609 lck_rw_lock_shared(&netagent_lock
);
1610 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1611 if (wrapper
!= NULL
) {
1612 generation
= wrapper
->generation
;
1614 NETAGENTLOG0(LOG_DEBUG
, "Generation requested for invalid netagent");
1616 lck_rw_done(&netagent_lock
);
1618 return (generation
);
1622 netagent_get_agent_domain_and_type(uuid_t uuid
, char *domain
, char *type
)
1625 if (domain
== NULL
|| type
== NULL
) {
1626 NETAGENTLOG(LOG_ERR
, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain
, type
);
1630 lck_rw_lock_shared(&netagent_lock
);
1631 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1632 if (wrapper
!= NULL
) {
1634 memcpy(domain
, wrapper
->netagent
.netagent_domain
, NETAGENT_DOMAINSIZE
);
1635 memcpy(type
, wrapper
->netagent
.netagent_type
, NETAGENT_TYPESIZE
);
1637 NETAGENTLOG0(LOG_DEBUG
, "Type requested for invalid netagent");
1639 lck_rw_done(&netagent_lock
);
1645 netagent_kernel_trigger(uuid_t uuid
)
1649 lck_rw_lock_shared(&netagent_lock
);
1650 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(uuid
);
1651 if (wrapper
== NULL
) {
1652 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger could not be found");
1657 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_KERNEL_ACTIVATED
) == 0) {
1658 NETAGENTLOG0(LOG_ERR
, "Requested netagent for kernel trigger is not kernel activated");
1659 // Agent does not accept kernel triggers
1664 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1665 // Agent already active
1666 NETAGENTLOG0(LOG_INFO
, "Requested netagent for kernel trigger is already active");
1671 error
= netagent_send_trigger(wrapper
, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
1672 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent from kernel (error %d)", error
);
1674 lck_rw_done(&netagent_lock
);
1679 netagent_client_message(uuid_t agent_uuid
, uuid_t necp_client_uuid
, u_int8_t message_type
)
1683 if (message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
&&
1684 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT
&&
1685 message_type
!= NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT
&&
1686 message_type
!= NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
&&
1687 message_type
!= NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
) {
1688 NETAGENTLOG(LOG_ERR
, "Client netagent message type (%d) is invalid", message_type
);
1692 lck_rw_lock_shared(&netagent_lock
);
1693 bool should_unlock
= TRUE
;
1694 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1695 if (wrapper
== NULL
) {
1696 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance could not be found");
1701 if (message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1702 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
1703 // Agent does not accept user triggers
1704 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1707 struct proc
*p
= current_proc();
1708 pid_t current_pid
= 0;
1709 uuid_t current_proc_uuid
;
1710 uuid_clear(current_proc_uuid
);
1712 current_pid
= proc_pid(p
);
1713 proc_getexecutableuuid(p
, current_proc_uuid
, sizeof(current_proc_uuid
));
1715 netagent_send_cellular_failed_event(wrapper
, current_pid
, current_proc_uuid
);
1718 } else if (message_type
== NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS
||
1719 message_type
== NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS
) {
1720 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_NEXUS_PROVIDER
) == 0) {
1721 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance is not a nexus provider");
1722 // Agent is not a nexus provider
1727 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
) == 0) {
1729 NETAGENTLOG0(LOG_INFO
, "Requested netagent for nexus instance is not active");
1735 error
= netagent_send_client_message(wrapper
, necp_client_uuid
, message_type
);
1736 if (error
== 0 && message_type
== NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER
) {
1737 if (lck_rw_lock_shared_to_exclusive(&netagent_lock
)) {
1738 // Grab the lock exclusively to add a pending client to the list
1739 struct netagent_client
*new_pending_client
= NULL
;
1740 MALLOC(new_pending_client
, struct netagent_client
*, sizeof(*new_pending_client
), M_NETAGENT
, M_WAITOK
);
1741 if (new_pending_client
== NULL
) {
1742 NETAGENTLOG0(LOG_ERR
, "Failed to allocate client for trigger");
1744 uuid_copy(new_pending_client
->client_id
, necp_client_uuid
);
1745 struct proc
*p
= current_proc();
1747 new_pending_client
->client_pid
= proc_pid(p
);
1748 proc_getexecutableuuid(p
, new_pending_client
->client_proc_uuid
, sizeof(new_pending_client
->client_proc_uuid
));
1750 LIST_INSERT_HEAD(&wrapper
->pending_triggers_list
, new_pending_client
, client_chain
);
1753 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
1754 should_unlock
= FALSE
;
1757 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Send message %d for client (error %d)", message_type
, error
);
1759 if (should_unlock
) {
1760 lck_rw_done(&netagent_lock
);
1766 netagent_use(uuid_t agent_uuid
, uint64_t *out_use_count
)
1770 lck_rw_lock_exclusive(&netagent_lock
);
1771 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1772 if (wrapper
== NULL
) {
1773 NETAGENTLOG0(LOG_ERR
, "netagent_assert: Requested netagent UUID is not registered");
1778 uint64_t current_count
= wrapper
->use_count
;
1779 wrapper
->use_count
++;
1781 if (out_use_count
!= NULL
) {
1782 *out_use_count
= current_count
;
1786 lck_rw_done(&netagent_lock
);
1791 netagent_copyout(uuid_t agent_uuid
, user_addr_t user_addr
, u_int32_t user_size
)
1795 lck_rw_lock_shared(&netagent_lock
);
1796 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1797 if (wrapper
== NULL
) {
1798 NETAGENTLOG0(LOG_ERR
, "Requested netagent for nexus instance could not be found");
1803 u_int32_t total_size
= (sizeof(struct netagent
) + wrapper
->netagent
.netagent_data_size
);
1804 if (user_size
< total_size
) {
1805 NETAGENTLOG(LOG_ERR
, "Provided user buffer is too small (%u < %u)", user_size
, total_size
);
1810 error
= copyout(&wrapper
->netagent
, user_addr
, total_size
);
1812 NETAGENTLOG((error
? LOG_ERR
: LOG_DEBUG
), "Copied agent content (error %d)", error
);
1814 lck_rw_done(&netagent_lock
);
1819 netagent_trigger(struct proc
*p
, struct netagent_trigger_args
*uap
, int32_t *retval
)
1821 #pragma unused(p, retval)
1826 NETAGENTLOG0(LOG_ERR
, "uap == NULL");
1830 if (uap
->agent_uuid
) {
1831 if (uap
->agent_uuidlen
!= sizeof(uuid_t
)) {
1832 NETAGENTLOG(LOG_ERR
, "Incorrect length (got %d, expected %d)",
1833 uap
->agent_uuidlen
, sizeof(uuid_t
));
1837 error
= copyin(uap
->agent_uuid
, agent_uuid
, sizeof(uuid_t
));
1839 NETAGENTLOG(LOG_ERR
, "copyin error (%d)", error
);
1844 if (uuid_is_null(agent_uuid
)) {
1845 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is empty");
1849 lck_rw_lock_shared(&netagent_lock
);
1850 struct netagent_wrapper
*wrapper
= netagent_find_agent_with_uuid(agent_uuid
);
1851 if (wrapper
== NULL
) {
1852 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not registered");
1857 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_USER_ACTIVATED
) == 0) {
1858 // Agent does not accept triggers
1859 NETAGENTLOG0(LOG_ERR
, "Requested netagent UUID is not eligible for triggering");
1864 if ((wrapper
->netagent
.netagent_flags
& NETAGENT_FLAG_ACTIVE
)) {
1865 // Agent already active
1866 NETAGENTLOG0(LOG_INFO
, "Requested netagent UUID is already active");
1871 error
= netagent_send_trigger(wrapper
, p
, NETAGENT_TRIGGER_FLAG_USER
, NETAGENT_MESSAGE_TYPE_TRIGGER
);
1872 NETAGENTLOG((error
? LOG_ERR
: LOG_INFO
), "Triggered netagent (error %d)", error
);
1874 lck_rw_done(&netagent_lock
);