1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions * Copyright (c) 2014-2021 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions *
4*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions *
6*aca3beaaSApple OSS Distributions * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions * compliance with the License. The rights granted to you under the License
10*aca3beaaSApple OSS Distributions * may not be used to create, or enable the creation or redistribution of,
11*aca3beaaSApple OSS Distributions * unlawful or unlicensed copies of an Apple operating system, or to
12*aca3beaaSApple OSS Distributions * circumvent, violate, or enable the circumvention or violation of, any
13*aca3beaaSApple OSS Distributions * terms of an Apple operating system software license agreement.
14*aca3beaaSApple OSS Distributions *
15*aca3beaaSApple OSS Distributions * Please obtain a copy of the License at
16*aca3beaaSApple OSS Distributions * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*aca3beaaSApple OSS Distributions *
18*aca3beaaSApple OSS Distributions * The Original Code and all software distributed under the License are
19*aca3beaaSApple OSS Distributions * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*aca3beaaSApple OSS Distributions * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*aca3beaaSApple OSS Distributions * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*aca3beaaSApple OSS Distributions * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*aca3beaaSApple OSS Distributions * Please see the License for the specific language governing rights and
24*aca3beaaSApple OSS Distributions * limitations under the License.
25*aca3beaaSApple OSS Distributions *
26*aca3beaaSApple OSS Distributions * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*aca3beaaSApple OSS Distributions */
28*aca3beaaSApple OSS Distributions
29*aca3beaaSApple OSS Distributions #include <string.h>
30*aca3beaaSApple OSS Distributions #include <sys/systm.h>
31*aca3beaaSApple OSS Distributions #include <sys/types.h>
32*aca3beaaSApple OSS Distributions #include <sys/syslog.h>
33*aca3beaaSApple OSS Distributions #include <sys/queue.h>
34*aca3beaaSApple OSS Distributions #include <sys/malloc.h>
35*aca3beaaSApple OSS Distributions #include <sys/kernel.h>
36*aca3beaaSApple OSS Distributions #include <sys/kern_control.h>
37*aca3beaaSApple OSS Distributions #include <sys/mbuf.h>
38*aca3beaaSApple OSS Distributions #include <sys/kpi_mbuf.h>
39*aca3beaaSApple OSS Distributions #include <sys/sysctl.h>
40*aca3beaaSApple OSS Distributions #include <sys/priv.h>
41*aca3beaaSApple OSS Distributions #include <sys/kern_event.h>
42*aca3beaaSApple OSS Distributions #include <sys/sysproto.h>
43*aca3beaaSApple OSS Distributions #include <net/network_agent.h>
44*aca3beaaSApple OSS Distributions #include <net/if_var.h>
45*aca3beaaSApple OSS Distributions #include <net/necp.h>
46*aca3beaaSApple OSS Distributions #include <os/log.h>
47*aca3beaaSApple OSS Distributions
48*aca3beaaSApple OSS Distributions u_int32_t netagent_debug = LOG_NOTICE; // 0=None, 1=Basic
49*aca3beaaSApple OSS Distributions
50*aca3beaaSApple OSS Distributions SYSCTL_NODE(_net, OID_AUTO, netagent, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "NetworkAgent");
51*aca3beaaSApple OSS Distributions SYSCTL_INT(_net_netagent, OID_AUTO, debug, CTLFLAG_LOCKED | CTLFLAG_RW, &netagent_debug, 0, "");
52*aca3beaaSApple OSS Distributions
53*aca3beaaSApple OSS Distributions static int netagent_registered_count = 0;
54*aca3beaaSApple OSS Distributions SYSCTL_INT(_net_netagent, OID_AUTO, registered_count, CTLFLAG_RD | CTLFLAG_LOCKED,
55*aca3beaaSApple OSS Distributions &netagent_registered_count, 0, "");
56*aca3beaaSApple OSS Distributions
57*aca3beaaSApple OSS Distributions static int netagent_active_count = 0;
58*aca3beaaSApple OSS Distributions SYSCTL_INT(_net_netagent, OID_AUTO, active_count, CTLFLAG_RD | CTLFLAG_LOCKED,
59*aca3beaaSApple OSS Distributions &netagent_active_count, 0, "");
60*aca3beaaSApple OSS Distributions
61*aca3beaaSApple OSS Distributions #define NETAGENTLOG(level, format, ...) do { \
62*aca3beaaSApple OSS Distributions if (level <= netagent_debug) { \
63*aca3beaaSApple OSS Distributions if (level == LOG_ERR) { \
64*aca3beaaSApple OSS Distributions os_log_error(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
65*aca3beaaSApple OSS Distributions } else { \
66*aca3beaaSApple OSS Distributions os_log(OS_LOG_DEFAULT, "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
67*aca3beaaSApple OSS Distributions } \
68*aca3beaaSApple OSS Distributions } \
69*aca3beaaSApple OSS Distributions } while (0)
70*aca3beaaSApple OSS Distributions
71*aca3beaaSApple OSS Distributions #define NETAGENTLOG0(level, msg) do { \
72*aca3beaaSApple OSS Distributions if (level <= netagent_debug) { \
73*aca3beaaSApple OSS Distributions if (level == LOG_ERR) { \
74*aca3beaaSApple OSS Distributions os_log_error(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
75*aca3beaaSApple OSS Distributions } else { \
76*aca3beaaSApple OSS Distributions os_log(OS_LOG_DEFAULT, "%s: %s\n", __FUNCTION__, msg); \
77*aca3beaaSApple OSS Distributions } \
78*aca3beaaSApple OSS Distributions } \
79*aca3beaaSApple OSS Distributions } while (0)
80*aca3beaaSApple OSS Distributions
81*aca3beaaSApple OSS Distributions struct netagent_client {
82*aca3beaaSApple OSS Distributions LIST_ENTRY(netagent_client) client_chain;
83*aca3beaaSApple OSS Distributions uuid_t client_id;
84*aca3beaaSApple OSS Distributions uuid_t client_proc_uuid;
85*aca3beaaSApple OSS Distributions pid_t client_pid;
86*aca3beaaSApple OSS Distributions };
87*aca3beaaSApple OSS Distributions
88*aca3beaaSApple OSS Distributions LIST_HEAD(netagent_client_list_s, netagent_client);
89*aca3beaaSApple OSS Distributions
90*aca3beaaSApple OSS Distributions struct netagent_token {
91*aca3beaaSApple OSS Distributions TAILQ_ENTRY(netagent_token) token_chain;
92*aca3beaaSApple OSS Distributions u_int32_t token_length;
93*aca3beaaSApple OSS Distributions u_int8_t *token_bytes;
94*aca3beaaSApple OSS Distributions };
95*aca3beaaSApple OSS Distributions
96*aca3beaaSApple OSS Distributions TAILQ_HEAD(netagent_token_list_s, netagent_token);
97*aca3beaaSApple OSS Distributions
98*aca3beaaSApple OSS Distributions #define NETAGENT_MAX_CLIENT_ERROR_COUNT 32
99*aca3beaaSApple OSS Distributions
100*aca3beaaSApple OSS Distributions struct netagent_wrapper {
101*aca3beaaSApple OSS Distributions LIST_ENTRY(netagent_wrapper) list_chain;
102*aca3beaaSApple OSS Distributions lck_rw_t agent_lock;
103*aca3beaaSApple OSS Distributions u_int32_t control_unit;
104*aca3beaaSApple OSS Distributions netagent_event_f event_handler;
105*aca3beaaSApple OSS Distributions void *event_context;
106*aca3beaaSApple OSS Distributions u_int32_t generation;
107*aca3beaaSApple OSS Distributions u_int64_t use_count;
108*aca3beaaSApple OSS Distributions u_int64_t need_tokens_event_deadline;
109*aca3beaaSApple OSS Distributions u_int32_t token_count;
110*aca3beaaSApple OSS Distributions u_int32_t token_low_water;
111*aca3beaaSApple OSS Distributions int32_t last_client_error;
112*aca3beaaSApple OSS Distributions u_int32_t client_error_count;
113*aca3beaaSApple OSS Distributions u_int8_t __pad_bytes[3];
114*aca3beaaSApple OSS Distributions struct netagent_token_list_s token_list;
115*aca3beaaSApple OSS Distributions struct netagent_client_list_s pending_triggers_list;
116*aca3beaaSApple OSS Distributions struct netagent *netagent;
117*aca3beaaSApple OSS Distributions };
118*aca3beaaSApple OSS Distributions
119*aca3beaaSApple OSS Distributions struct netagent_session {
120*aca3beaaSApple OSS Distributions u_int32_t control_unit; // A control unit of 0 indicates an agent owned by the kernel
121*aca3beaaSApple OSS Distributions lck_mtx_t session_lock;
122*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper;
123*aca3beaaSApple OSS Distributions netagent_event_f event_handler;
124*aca3beaaSApple OSS Distributions void *event_context;
125*aca3beaaSApple OSS Distributions };
126*aca3beaaSApple OSS Distributions
127*aca3beaaSApple OSS Distributions typedef enum {
128*aca3beaaSApple OSS Distributions kNetagentErrorDomainPOSIX = 0,
129*aca3beaaSApple OSS Distributions kNetagentErrorDomainUserDefined = 1,
130*aca3beaaSApple OSS Distributions } netagent_error_domain_t;
131*aca3beaaSApple OSS Distributions
132*aca3beaaSApple OSS Distributions static LIST_HEAD(_netagent_list, netagent_wrapper) shared_netagent_list =
133*aca3beaaSApple OSS Distributions LIST_HEAD_INITIALIZER(master_netagent_list);
134*aca3beaaSApple OSS Distributions
135*aca3beaaSApple OSS Distributions // Protected by netagent_list_lock
136*aca3beaaSApple OSS Distributions static u_int32_t g_next_generation = 1;
137*aca3beaaSApple OSS Distributions
138*aca3beaaSApple OSS Distributions static kern_ctl_ref netagent_kctlref;
139*aca3beaaSApple OSS Distributions static u_int32_t netagent_family;
140*aca3beaaSApple OSS Distributions static LCK_GRP_DECLARE(netagent_mtx_grp, NETAGENT_CONTROL_NAME);
141*aca3beaaSApple OSS Distributions static LCK_RW_DECLARE(netagent_list_lock, &netagent_mtx_grp);
142*aca3beaaSApple OSS Distributions
143*aca3beaaSApple OSS Distributions #define NETAGENT_LIST_LOCK_EXCLUSIVE() lck_rw_lock_exclusive(&netagent_list_lock)
144*aca3beaaSApple OSS Distributions #define NETAGENT_LIST_LOCK_SHARED() lck_rw_lock_shared(&netagent_list_lock)
145*aca3beaaSApple OSS Distributions #define NETAGENT_LIST_UNLOCK() lck_rw_done(&netagent_list_lock)
146*aca3beaaSApple OSS Distributions #define NETAGENT_LIST_ASSERT_LOCKED() LCK_RW_ASSERT(&netagent_list_lock, LCK_RW_ASSERT_HELD)
147*aca3beaaSApple OSS Distributions
148*aca3beaaSApple OSS Distributions #define NETAGENT_SESSION_LOCK(session) lck_mtx_lock(&session->session_lock)
149*aca3beaaSApple OSS Distributions #define NETAGENT_SESSION_UNLOCK(session) lck_mtx_unlock(&session->session_lock)
150*aca3beaaSApple OSS Distributions
151*aca3beaaSApple OSS Distributions #define NETAGENT_LOCK_EXCLUSIVE(wrapper) lck_rw_lock_exclusive(&wrapper->agent_lock)
152*aca3beaaSApple OSS Distributions #define NETAGENT_LOCK_SHARED(wrapper) lck_rw_lock_shared(&wrapper->agent_lock)
153*aca3beaaSApple OSS Distributions #define NETAGENT_LOCK_SHARED_TO_EXCLUSIVE(wrapper) lck_rw_lock_shared_to_exclusive(&wrapper->agent_lock)
154*aca3beaaSApple OSS Distributions #define NETAGENT_UNLOCK(wrapper) lck_rw_done(&wrapper->agent_lock)
155*aca3beaaSApple OSS Distributions #define NETAGENT_ASSERT_LOCKED(wrapper) LCK_RW_ASSERT(&wrapper->agent_lock, LCK_RW_ASSERT_HELD)
156*aca3beaaSApple OSS Distributions
157*aca3beaaSApple OSS Distributions // Locking Notes
158*aca3beaaSApple OSS Distributions
159*aca3beaaSApple OSS Distributions // Precedence, where 1 is the first lock that must be taken
160*aca3beaaSApple OSS Distributions // 1. NETAGENT_LIST_LOCK - protects shared_netagent_list
161*aca3beaaSApple OSS Distributions // 2. NETAGENT_SESSION_LOCK - protects the session->wrapper pointer
162*aca3beaaSApple OSS Distributions // 3. NETAGENT_LOCK -> protects values in a wrapper
163*aca3beaaSApple OSS Distributions
164*aca3beaaSApple OSS Distributions static errno_t netagent_register_control(void);
165*aca3beaaSApple OSS Distributions static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
166*aca3beaaSApple OSS Distributions void **unitinfo);
167*aca3beaaSApple OSS Distributions static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
168*aca3beaaSApple OSS Distributions static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
169*aca3beaaSApple OSS Distributions mbuf_t m, int flags);
170*aca3beaaSApple OSS Distributions static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
171*aca3beaaSApple OSS Distributions static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
172*aca3beaaSApple OSS Distributions int opt, void *data, size_t *len);
173*aca3beaaSApple OSS Distributions static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
174*aca3beaaSApple OSS Distributions int opt, void *data, size_t len);
175*aca3beaaSApple OSS Distributions
176*aca3beaaSApple OSS Distributions static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
177*aca3beaaSApple OSS Distributions
178*aca3beaaSApple OSS Distributions static struct netagent_session *netagent_create_session(u_int32_t control_unit);
179*aca3beaaSApple OSS Distributions static void netagent_delete_session(struct netagent_session *session);
180*aca3beaaSApple OSS Distributions
181*aca3beaaSApple OSS Distributions // Register
182*aca3beaaSApple OSS Distributions static void netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
183*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset);
184*aca3beaaSApple OSS Distributions static errno_t netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
185*aca3beaaSApple OSS Distributions size_t payload_length);
186*aca3beaaSApple OSS Distributions
187*aca3beaaSApple OSS Distributions // Unregister
188*aca3beaaSApple OSS Distributions static void netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
189*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset);
190*aca3beaaSApple OSS Distributions static errno_t netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
191*aca3beaaSApple OSS Distributions size_t payload_length);
192*aca3beaaSApple OSS Distributions
193*aca3beaaSApple OSS Distributions // Update
194*aca3beaaSApple OSS Distributions static void netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
195*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset);
196*aca3beaaSApple OSS Distributions static errno_t netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload,
197*aca3beaaSApple OSS Distributions size_t payload_length);
198*aca3beaaSApple OSS Distributions
199*aca3beaaSApple OSS Distributions // Assign nexus
200*aca3beaaSApple OSS Distributions static void netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
201*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset);
202*aca3beaaSApple OSS Distributions static errno_t netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
203*aca3beaaSApple OSS Distributions size_t payload_length);
204*aca3beaaSApple OSS Distributions
205*aca3beaaSApple OSS Distributions // Assign group
206*aca3beaaSApple OSS Distributions static errno_t netagent_handle_assign_group_setopt(struct netagent_session *session, u_int8_t *payload,
207*aca3beaaSApple OSS Distributions size_t payload_length);
208*aca3beaaSApple OSS Distributions
209*aca3beaaSApple OSS Distributions // Set/get assert count
210*aca3beaaSApple OSS Distributions static errno_t netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
211*aca3beaaSApple OSS Distributions static errno_t netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
212*aca3beaaSApple OSS Distributions
213*aca3beaaSApple OSS Distributions // Manage tokens
214*aca3beaaSApple OSS Distributions static errno_t netagent_handle_add_token_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
215*aca3beaaSApple OSS Distributions static errno_t netagent_handle_flush_tokens_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
216*aca3beaaSApple OSS Distributions static errno_t netagent_handle_token_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
217*aca3beaaSApple OSS Distributions static errno_t netagent_handle_token_low_water_setopt(struct netagent_session *session, u_int8_t *buffer, size_t buffer_length);
218*aca3beaaSApple OSS Distributions static errno_t netagent_handle_token_low_water_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
219*aca3beaaSApple OSS Distributions
220*aca3beaaSApple OSS Distributions // Client error
221*aca3beaaSApple OSS Distributions static errno_t netagent_handle_reset_client_error_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
222*aca3beaaSApple OSS Distributions
223*aca3beaaSApple OSS Distributions static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
224*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset);
225*aca3beaaSApple OSS Distributions
226*aca3beaaSApple OSS Distributions // Requires list lock being held
227*aca3beaaSApple OSS Distributions static struct netagent_wrapper *netagent_find_agent_with_uuid_and_lock(uuid_t uuid, bool exclusively, bool ignore_lock);
228*aca3beaaSApple OSS Distributions
229*aca3beaaSApple OSS Distributions errno_t
netagent_init(void)230*aca3beaaSApple OSS Distributions netagent_init(void)
231*aca3beaaSApple OSS Distributions {
232*aca3beaaSApple OSS Distributions return netagent_register_control();
233*aca3beaaSApple OSS Distributions }
234*aca3beaaSApple OSS Distributions
235*aca3beaaSApple OSS Distributions static errno_t
netagent_register_control(void)236*aca3beaaSApple OSS Distributions netagent_register_control(void)
237*aca3beaaSApple OSS Distributions {
238*aca3beaaSApple OSS Distributions struct kern_ctl_reg kern_ctl;
239*aca3beaaSApple OSS Distributions errno_t result = 0;
240*aca3beaaSApple OSS Distributions
241*aca3beaaSApple OSS Distributions // Find a unique value for our interface family
242*aca3beaaSApple OSS Distributions result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
243*aca3beaaSApple OSS Distributions if (result != 0) {
244*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
245*aca3beaaSApple OSS Distributions return result;
246*aca3beaaSApple OSS Distributions }
247*aca3beaaSApple OSS Distributions
248*aca3beaaSApple OSS Distributions bzero(&kern_ctl, sizeof(kern_ctl));
249*aca3beaaSApple OSS Distributions strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
250*aca3beaaSApple OSS Distributions kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
251*aca3beaaSApple OSS Distributions kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
252*aca3beaaSApple OSS Distributions kern_ctl.ctl_sendsize = 64 * 1024;
253*aca3beaaSApple OSS Distributions kern_ctl.ctl_recvsize = 64 * 1024;
254*aca3beaaSApple OSS Distributions kern_ctl.ctl_connect = netagent_ctl_connect;
255*aca3beaaSApple OSS Distributions kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
256*aca3beaaSApple OSS Distributions kern_ctl.ctl_send = netagent_ctl_send;
257*aca3beaaSApple OSS Distributions kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
258*aca3beaaSApple OSS Distributions kern_ctl.ctl_setopt = netagent_ctl_setopt;
259*aca3beaaSApple OSS Distributions kern_ctl.ctl_getopt = netagent_ctl_getopt;
260*aca3beaaSApple OSS Distributions
261*aca3beaaSApple OSS Distributions result = ctl_register(&kern_ctl, &netagent_kctlref);
262*aca3beaaSApple OSS Distributions if (result != 0) {
263*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
264*aca3beaaSApple OSS Distributions return result;
265*aca3beaaSApple OSS Distributions }
266*aca3beaaSApple OSS Distributions
267*aca3beaaSApple OSS Distributions return 0;
268*aca3beaaSApple OSS Distributions }
269*aca3beaaSApple OSS Distributions
270*aca3beaaSApple OSS Distributions static errno_t
netagent_ctl_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)271*aca3beaaSApple OSS Distributions netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
272*aca3beaaSApple OSS Distributions {
273*aca3beaaSApple OSS Distributions #pragma unused(kctlref)
274*aca3beaaSApple OSS Distributions *unitinfo = netagent_create_session(sac->sc_unit);
275*aca3beaaSApple OSS Distributions if (*unitinfo == NULL) {
276*aca3beaaSApple OSS Distributions // Could not allocate session
277*aca3beaaSApple OSS Distributions return ENOBUFS;
278*aca3beaaSApple OSS Distributions }
279*aca3beaaSApple OSS Distributions
280*aca3beaaSApple OSS Distributions return 0;
281*aca3beaaSApple OSS Distributions }
282*aca3beaaSApple OSS Distributions
283*aca3beaaSApple OSS Distributions static errno_t
netagent_ctl_disconnect(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo)284*aca3beaaSApple OSS Distributions netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
285*aca3beaaSApple OSS Distributions {
286*aca3beaaSApple OSS Distributions #pragma unused(kctlref, unit)
287*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)unitinfo;
288*aca3beaaSApple OSS Distributions if (session != NULL) {
289*aca3beaaSApple OSS Distributions netagent_delete_session(session);
290*aca3beaaSApple OSS Distributions }
291*aca3beaaSApple OSS Distributions
292*aca3beaaSApple OSS Distributions return 0;
293*aca3beaaSApple OSS Distributions }
294*aca3beaaSApple OSS Distributions
295*aca3beaaSApple OSS Distributions // Kernel events
296*aca3beaaSApple OSS Distributions static void
netagent_post_event(uuid_t agent_uuid,u_int32_t event_code,bool update_necp,bool should_update_immediately)297*aca3beaaSApple OSS Distributions netagent_post_event(uuid_t agent_uuid, u_int32_t event_code, bool update_necp, bool should_update_immediately)
298*aca3beaaSApple OSS Distributions {
299*aca3beaaSApple OSS Distributions if (update_necp) {
300*aca3beaaSApple OSS Distributions necp_update_all_clients_immediately_if_needed(should_update_immediately);
301*aca3beaaSApple OSS Distributions }
302*aca3beaaSApple OSS Distributions
303*aca3beaaSApple OSS Distributions struct kev_msg ev_msg;
304*aca3beaaSApple OSS Distributions memset(&ev_msg, 0, sizeof(ev_msg));
305*aca3beaaSApple OSS Distributions
306*aca3beaaSApple OSS Distributions struct kev_netagent_data event_data;
307*aca3beaaSApple OSS Distributions
308*aca3beaaSApple OSS Distributions ev_msg.vendor_code = KEV_VENDOR_APPLE;
309*aca3beaaSApple OSS Distributions ev_msg.kev_class = KEV_NETWORK_CLASS;
310*aca3beaaSApple OSS Distributions ev_msg.kev_subclass = KEV_NETAGENT_SUBCLASS;
311*aca3beaaSApple OSS Distributions ev_msg.event_code = event_code;
312*aca3beaaSApple OSS Distributions
313*aca3beaaSApple OSS Distributions uuid_copy(event_data.netagent_uuid, agent_uuid);
314*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_ptr = &event_data;
315*aca3beaaSApple OSS Distributions ev_msg.dv[0].data_length = sizeof(event_data);
316*aca3beaaSApple OSS Distributions
317*aca3beaaSApple OSS Distributions kev_post_msg(&ev_msg);
318*aca3beaaSApple OSS Distributions }
319*aca3beaaSApple OSS Distributions
320*aca3beaaSApple OSS Distributions // Message handling
321*aca3beaaSApple OSS Distributions static u_int8_t *
netagent_buffer_write_message_header(u_int8_t * buffer,u_int8_t message_type,u_int8_t flags,u_int32_t message_id,u_int32_t error,size_t payload_length)322*aca3beaaSApple OSS Distributions netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
323*aca3beaaSApple OSS Distributions u_int32_t message_id, u_int32_t error, size_t payload_length)
324*aca3beaaSApple OSS Distributions {
325*aca3beaaSApple OSS Distributions memset(buffer, 0, sizeof(struct netagent_message_header));
326*aca3beaaSApple OSS Distributions ((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
327*aca3beaaSApple OSS Distributions ((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
328*aca3beaaSApple OSS Distributions ((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
329*aca3beaaSApple OSS Distributions ((struct netagent_message_header *)(void *)buffer)->message_error = error;
330*aca3beaaSApple OSS Distributions ((struct netagent_message_header *)(void *)buffer)->message_payload_length = (u_int32_t)payload_length;
331*aca3beaaSApple OSS Distributions return buffer + sizeof(struct netagent_message_header);
332*aca3beaaSApple OSS Distributions }
333*aca3beaaSApple OSS Distributions
334*aca3beaaSApple OSS Distributions static int
netagent_send_ctl_data(u_int32_t control_unit,u_int8_t * buffer,size_t buffer_size)335*aca3beaaSApple OSS Distributions netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
336*aca3beaaSApple OSS Distributions {
337*aca3beaaSApple OSS Distributions if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
338*aca3beaaSApple OSS Distributions return EINVAL;
339*aca3beaaSApple OSS Distributions }
340*aca3beaaSApple OSS Distributions
341*aca3beaaSApple OSS Distributions return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
342*aca3beaaSApple OSS Distributions }
343*aca3beaaSApple OSS Distributions
344*aca3beaaSApple OSS Distributions static int
netagent_send_trigger(struct netagent_wrapper * wrapper,struct proc * p,u_int32_t flags,u_int8_t trigger_type)345*aca3beaaSApple OSS Distributions netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int8_t trigger_type)
346*aca3beaaSApple OSS Distributions {
347*aca3beaaSApple OSS Distributions int error = 0;
348*aca3beaaSApple OSS Distributions struct netagent_trigger_message *trigger_message = NULL;
349*aca3beaaSApple OSS Distributions u_int8_t *trigger = NULL;
350*aca3beaaSApple OSS Distributions size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
351*aca3beaaSApple OSS Distributions
352*aca3beaaSApple OSS Distributions trigger = (u_int8_t *)kalloc_data(trigger_size, Z_WAITOK);
353*aca3beaaSApple OSS Distributions if (trigger == NULL) {
354*aca3beaaSApple OSS Distributions return ENOMEM;
355*aca3beaaSApple OSS Distributions }
356*aca3beaaSApple OSS Distributions
357*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
358*aca3beaaSApple OSS Distributions
359*aca3beaaSApple OSS Distributions trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
360*aca3beaaSApple OSS Distributions trigger_message->trigger_flags = flags;
361*aca3beaaSApple OSS Distributions if (p != NULL) {
362*aca3beaaSApple OSS Distributions trigger_message->trigger_pid = proc_pid(p);
363*aca3beaaSApple OSS Distributions proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
364*aca3beaaSApple OSS Distributions } else {
365*aca3beaaSApple OSS Distributions trigger_message->trigger_pid = 0;
366*aca3beaaSApple OSS Distributions uuid_clear(trigger_message->trigger_proc_uuid);
367*aca3beaaSApple OSS Distributions }
368*aca3beaaSApple OSS Distributions
369*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(wrapper->control_unit, trigger, trigger_size))) {
370*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
371*aca3beaaSApple OSS Distributions }
372*aca3beaaSApple OSS Distributions
373*aca3beaaSApple OSS Distributions kfree_data(trigger, trigger_size);
374*aca3beaaSApple OSS Distributions return error;
375*aca3beaaSApple OSS Distributions }
376*aca3beaaSApple OSS Distributions
377*aca3beaaSApple OSS Distributions static int
netagent_send_client_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type)378*aca3beaaSApple OSS Distributions netagent_send_client_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type)
379*aca3beaaSApple OSS Distributions {
380*aca3beaaSApple OSS Distributions int error = 0;
381*aca3beaaSApple OSS Distributions struct netagent_client_message *client_message = NULL;
382*aca3beaaSApple OSS Distributions u_int8_t *message = NULL;
383*aca3beaaSApple OSS Distributions size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_message);
384*aca3beaaSApple OSS Distributions
385*aca3beaaSApple OSS Distributions message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
386*aca3beaaSApple OSS Distributions if (message == NULL) {
387*aca3beaaSApple OSS Distributions return ENOMEM;
388*aca3beaaSApple OSS Distributions }
389*aca3beaaSApple OSS Distributions
390*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_message));
391*aca3beaaSApple OSS Distributions
392*aca3beaaSApple OSS Distributions client_message = (struct netagent_client_message *)(void *)(message + sizeof(struct netagent_message_header));
393*aca3beaaSApple OSS Distributions uuid_copy(client_message->client_id, client_id);
394*aca3beaaSApple OSS Distributions
395*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
396*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
397*aca3beaaSApple OSS Distributions }
398*aca3beaaSApple OSS Distributions
399*aca3beaaSApple OSS Distributions kfree_data(message, message_size);
400*aca3beaaSApple OSS Distributions return error;
401*aca3beaaSApple OSS Distributions }
402*aca3beaaSApple OSS Distributions
403*aca3beaaSApple OSS Distributions static int
netagent_send_error_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type,int32_t error_code)404*aca3beaaSApple OSS Distributions netagent_send_error_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type, int32_t error_code)
405*aca3beaaSApple OSS Distributions {
406*aca3beaaSApple OSS Distributions int error = 0;
407*aca3beaaSApple OSS Distributions struct netagent_client_error_message *client_message = NULL;
408*aca3beaaSApple OSS Distributions u_int8_t *message = NULL;
409*aca3beaaSApple OSS Distributions size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_error_message);
410*aca3beaaSApple OSS Distributions
411*aca3beaaSApple OSS Distributions message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
412*aca3beaaSApple OSS Distributions if (message == NULL) {
413*aca3beaaSApple OSS Distributions return ENOMEM;
414*aca3beaaSApple OSS Distributions }
415*aca3beaaSApple OSS Distributions
416*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_error_message));
417*aca3beaaSApple OSS Distributions
418*aca3beaaSApple OSS Distributions client_message = (struct netagent_client_error_message *)(void *)(message + sizeof(struct netagent_message_header));
419*aca3beaaSApple OSS Distributions uuid_copy(client_message->client_id, client_id);
420*aca3beaaSApple OSS Distributions client_message->error_code = error_code;
421*aca3beaaSApple OSS Distributions
422*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
423*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
424*aca3beaaSApple OSS Distributions }
425*aca3beaaSApple OSS Distributions
426*aca3beaaSApple OSS Distributions kfree_data(message, message_size);
427*aca3beaaSApple OSS Distributions return error;
428*aca3beaaSApple OSS Distributions }
429*aca3beaaSApple OSS Distributions
430*aca3beaaSApple OSS Distributions static int
netagent_send_group_message(struct netagent_wrapper * wrapper,uuid_t client_id,u_int8_t message_type,struct necp_client_group_members * group_members)431*aca3beaaSApple OSS Distributions netagent_send_group_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type, struct necp_client_group_members *group_members)
432*aca3beaaSApple OSS Distributions {
433*aca3beaaSApple OSS Distributions int error = 0;
434*aca3beaaSApple OSS Distributions struct netagent_client_group_message *client_message = NULL;
435*aca3beaaSApple OSS Distributions u_int8_t *message = NULL;
436*aca3beaaSApple OSS Distributions size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_group_message) + group_members->group_members_length;
437*aca3beaaSApple OSS Distributions
438*aca3beaaSApple OSS Distributions message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
439*aca3beaaSApple OSS Distributions if (message == NULL) {
440*aca3beaaSApple OSS Distributions return ENOMEM;
441*aca3beaaSApple OSS Distributions }
442*aca3beaaSApple OSS Distributions
443*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_group_message) + group_members->group_members_length);
444*aca3beaaSApple OSS Distributions
445*aca3beaaSApple OSS Distributions client_message = (struct netagent_client_group_message *)(void *)(message + sizeof(struct netagent_message_header));
446*aca3beaaSApple OSS Distributions uuid_copy(client_message->client_id, client_id);
447*aca3beaaSApple OSS Distributions memcpy(client_message->group_members, group_members->group_members, group_members->group_members_length);
448*aca3beaaSApple OSS Distributions
449*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
450*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to send client group message %d on control unit %d", message_type, wrapper->control_unit);
451*aca3beaaSApple OSS Distributions }
452*aca3beaaSApple OSS Distributions
453*aca3beaaSApple OSS Distributions kfree_data(message, message_size);
454*aca3beaaSApple OSS Distributions return error;
455*aca3beaaSApple OSS Distributions }
456*aca3beaaSApple OSS Distributions
457*aca3beaaSApple OSS Distributions static int
netagent_send_tokens_needed(struct netagent_wrapper * wrapper)458*aca3beaaSApple OSS Distributions netagent_send_tokens_needed(struct netagent_wrapper *wrapper)
459*aca3beaaSApple OSS Distributions {
460*aca3beaaSApple OSS Distributions const u_int8_t message_type = NETAGENT_MESSAGE_TYPE_TOKENS_NEEDED;
461*aca3beaaSApple OSS Distributions int error = 0;
462*aca3beaaSApple OSS Distributions u_int8_t *message = NULL;
463*aca3beaaSApple OSS Distributions size_t message_size = sizeof(struct netagent_message_header);
464*aca3beaaSApple OSS Distributions
465*aca3beaaSApple OSS Distributions message = (u_int8_t *)kalloc_data(message_size, Z_WAITOK);
466*aca3beaaSApple OSS Distributions if (message == NULL) {
467*aca3beaaSApple OSS Distributions return ENOMEM;
468*aca3beaaSApple OSS Distributions }
469*aca3beaaSApple OSS Distributions
470*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, 0);
471*aca3beaaSApple OSS Distributions
472*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(wrapper->control_unit, message, message_size))) {
473*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to send client tokens needed message on control unit %d", wrapper->control_unit);
474*aca3beaaSApple OSS Distributions }
475*aca3beaaSApple OSS Distributions
476*aca3beaaSApple OSS Distributions kfree_data(message, message_size);
477*aca3beaaSApple OSS Distributions return error;
478*aca3beaaSApple OSS Distributions }
479*aca3beaaSApple OSS Distributions
480*aca3beaaSApple OSS Distributions static int
netagent_send_success_response(struct netagent_session * session,u_int8_t message_type,u_int32_t message_id)481*aca3beaaSApple OSS Distributions netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
482*aca3beaaSApple OSS Distributions {
483*aca3beaaSApple OSS Distributions int error = 0;
484*aca3beaaSApple OSS Distributions u_int8_t *response = NULL;
485*aca3beaaSApple OSS Distributions size_t response_size = sizeof(struct netagent_message_header);
486*aca3beaaSApple OSS Distributions response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
487*aca3beaaSApple OSS Distributions if (response == NULL) {
488*aca3beaaSApple OSS Distributions return ENOMEM;
489*aca3beaaSApple OSS Distributions }
490*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
491*aca3beaaSApple OSS Distributions
492*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(session->control_unit, response, response_size))) {
493*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to send response");
494*aca3beaaSApple OSS Distributions }
495*aca3beaaSApple OSS Distributions
496*aca3beaaSApple OSS Distributions kfree_data(response, response_size);
497*aca3beaaSApple OSS Distributions return error;
498*aca3beaaSApple OSS Distributions }
499*aca3beaaSApple OSS Distributions
500*aca3beaaSApple OSS Distributions static errno_t
netagent_send_error_response(struct netagent_session * session,u_int8_t message_type,u_int32_t message_id,u_int32_t error_code)501*aca3beaaSApple OSS Distributions netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
502*aca3beaaSApple OSS Distributions u_int32_t message_id, u_int32_t error_code)
503*aca3beaaSApple OSS Distributions {
504*aca3beaaSApple OSS Distributions int error = 0;
505*aca3beaaSApple OSS Distributions u_int8_t *response = NULL;
506*aca3beaaSApple OSS Distributions size_t response_size = sizeof(struct netagent_message_header);
507*aca3beaaSApple OSS Distributions
508*aca3beaaSApple OSS Distributions if (session == NULL) {
509*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Got a NULL session");
510*aca3beaaSApple OSS Distributions return EINVAL;
511*aca3beaaSApple OSS Distributions }
512*aca3beaaSApple OSS Distributions
513*aca3beaaSApple OSS Distributions response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
514*aca3beaaSApple OSS Distributions if (response == NULL) {
515*aca3beaaSApple OSS Distributions return ENOMEM;
516*aca3beaaSApple OSS Distributions }
517*aca3beaaSApple OSS Distributions (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
518*aca3beaaSApple OSS Distributions message_id, error_code, 0);
519*aca3beaaSApple OSS Distributions
520*aca3beaaSApple OSS Distributions if ((error = netagent_send_ctl_data(session->control_unit, response, response_size))) {
521*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to send response");
522*aca3beaaSApple OSS Distributions }
523*aca3beaaSApple OSS Distributions
524*aca3beaaSApple OSS Distributions kfree_data(response, response_size);
525*aca3beaaSApple OSS Distributions return error;
526*aca3beaaSApple OSS Distributions }
527*aca3beaaSApple OSS Distributions
528*aca3beaaSApple OSS Distributions static errno_t
netagent_ctl_send(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,mbuf_t packet,int flags)529*aca3beaaSApple OSS Distributions netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
530*aca3beaaSApple OSS Distributions {
531*aca3beaaSApple OSS Distributions #pragma unused(kctlref, unit, flags)
532*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)unitinfo;
533*aca3beaaSApple OSS Distributions struct netagent_message_header header;
534*aca3beaaSApple OSS Distributions int error = 0;
535*aca3beaaSApple OSS Distributions
536*aca3beaaSApple OSS Distributions if (session == NULL) {
537*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Got a NULL session");
538*aca3beaaSApple OSS Distributions error = EINVAL;
539*aca3beaaSApple OSS Distributions goto done;
540*aca3beaaSApple OSS Distributions }
541*aca3beaaSApple OSS Distributions
542*aca3beaaSApple OSS Distributions if (mbuf_pkthdr_len(packet) < sizeof(header)) {
543*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
544*aca3beaaSApple OSS Distributions mbuf_pkthdr_len(packet), sizeof(header));
545*aca3beaaSApple OSS Distributions error = EINVAL;
546*aca3beaaSApple OSS Distributions goto done;
547*aca3beaaSApple OSS Distributions }
548*aca3beaaSApple OSS Distributions
549*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, 0, sizeof(header), &header);
550*aca3beaaSApple OSS Distributions if (error) {
551*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
552*aca3beaaSApple OSS Distributions error = ENOBUFS;
553*aca3beaaSApple OSS Distributions goto done;
554*aca3beaaSApple OSS Distributions }
555*aca3beaaSApple OSS Distributions
556*aca3beaaSApple OSS Distributions switch (header.message_type) {
557*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_REGISTER: {
558*aca3beaaSApple OSS Distributions netagent_handle_register_message(session, header.message_id, header.message_payload_length,
559*aca3beaaSApple OSS Distributions packet, sizeof(header));
560*aca3beaaSApple OSS Distributions break;
561*aca3beaaSApple OSS Distributions }
562*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
563*aca3beaaSApple OSS Distributions netagent_handle_unregister_message(session, header.message_id, header.message_payload_length,
564*aca3beaaSApple OSS Distributions packet, sizeof(header));
565*aca3beaaSApple OSS Distributions break;
566*aca3beaaSApple OSS Distributions }
567*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_UPDATE: {
568*aca3beaaSApple OSS Distributions netagent_handle_update_message(session, header.message_id, header.message_payload_length,
569*aca3beaaSApple OSS Distributions packet, sizeof(header));
570*aca3beaaSApple OSS Distributions break;
571*aca3beaaSApple OSS Distributions }
572*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_GET: {
573*aca3beaaSApple OSS Distributions netagent_handle_get(session, header.message_id, header.message_payload_length,
574*aca3beaaSApple OSS Distributions packet, sizeof(header));
575*aca3beaaSApple OSS Distributions break;
576*aca3beaaSApple OSS Distributions }
577*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_ASSERT: {
578*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
579*aca3beaaSApple OSS Distributions break;
580*aca3beaaSApple OSS Distributions }
581*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_UNASSERT: {
582*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
583*aca3beaaSApple OSS Distributions break;
584*aca3beaaSApple OSS Distributions }
585*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS: {
586*aca3beaaSApple OSS Distributions netagent_handle_assign_nexus_message(session, header.message_id, header.message_payload_length,
587*aca3beaaSApple OSS Distributions packet, sizeof(header));
588*aca3beaaSApple OSS Distributions break;
589*aca3beaaSApple OSS Distributions }
590*aca3beaaSApple OSS Distributions default: {
591*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
592*aca3beaaSApple OSS Distributions netagent_send_error_response(session, header.message_type, header.message_id,
593*aca3beaaSApple OSS Distributions NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
594*aca3beaaSApple OSS Distributions break;
595*aca3beaaSApple OSS Distributions }
596*aca3beaaSApple OSS Distributions }
597*aca3beaaSApple OSS Distributions
598*aca3beaaSApple OSS Distributions done:
599*aca3beaaSApple OSS Distributions mbuf_freem(packet);
600*aca3beaaSApple OSS Distributions return error;
601*aca3beaaSApple OSS Distributions }
602*aca3beaaSApple OSS Distributions
603*aca3beaaSApple OSS Distributions static void
netagent_ctl_rcvd(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int flags)604*aca3beaaSApple OSS Distributions netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
605*aca3beaaSApple OSS Distributions {
606*aca3beaaSApple OSS Distributions #pragma unused(kctlref, unit, unitinfo, flags)
607*aca3beaaSApple OSS Distributions return;
608*aca3beaaSApple OSS Distributions }
609*aca3beaaSApple OSS Distributions
610*aca3beaaSApple OSS Distributions static errno_t
netagent_ctl_getopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t * len)611*aca3beaaSApple OSS Distributions netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
612*aca3beaaSApple OSS Distributions void *data, size_t *len)
613*aca3beaaSApple OSS Distributions {
614*aca3beaaSApple OSS Distributions #pragma unused(kctlref, unit)
615*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)unitinfo;
616*aca3beaaSApple OSS Distributions errno_t error;
617*aca3beaaSApple OSS Distributions
618*aca3beaaSApple OSS Distributions if (session == NULL) {
619*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Received a NULL session");
620*aca3beaaSApple OSS Distributions error = EINVAL;
621*aca3beaaSApple OSS Distributions goto done;
622*aca3beaaSApple OSS Distributions }
623*aca3beaaSApple OSS Distributions
624*aca3beaaSApple OSS Distributions switch (opt) {
625*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_USE_COUNT: {
626*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to get use count");
627*aca3beaaSApple OSS Distributions error = netagent_handle_use_count_getopt(session, data, len);
628*aca3beaaSApple OSS Distributions break;
629*aca3beaaSApple OSS Distributions }
630*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_TOKEN_COUNT: {
631*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to get token count");
632*aca3beaaSApple OSS Distributions error = netagent_handle_token_count_getopt(session, data, len);
633*aca3beaaSApple OSS Distributions break;
634*aca3beaaSApple OSS Distributions }
635*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_TOKEN_LOW_WATER: {
636*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to get token low water mark");
637*aca3beaaSApple OSS Distributions error = netagent_handle_token_low_water_getopt(session, data, len);
638*aca3beaaSApple OSS Distributions break;
639*aca3beaaSApple OSS Distributions }
640*aca3beaaSApple OSS Distributions default:
641*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Received unknown option");
642*aca3beaaSApple OSS Distributions error = ENOPROTOOPT;
643*aca3beaaSApple OSS Distributions break;
644*aca3beaaSApple OSS Distributions }
645*aca3beaaSApple OSS Distributions
646*aca3beaaSApple OSS Distributions done:
647*aca3beaaSApple OSS Distributions return error;
648*aca3beaaSApple OSS Distributions }
649*aca3beaaSApple OSS Distributions
650*aca3beaaSApple OSS Distributions static errno_t
netagent_ctl_setopt(kern_ctl_ref kctlref,u_int32_t unit,void * unitinfo,int opt,void * data,size_t len)651*aca3beaaSApple OSS Distributions netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
652*aca3beaaSApple OSS Distributions void *data, size_t len)
653*aca3beaaSApple OSS Distributions {
654*aca3beaaSApple OSS Distributions #pragma unused(kctlref, unit)
655*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)unitinfo;
656*aca3beaaSApple OSS Distributions errno_t error;
657*aca3beaaSApple OSS Distributions
658*aca3beaaSApple OSS Distributions if (session == NULL) {
659*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Received a NULL session");
660*aca3beaaSApple OSS Distributions error = EINVAL;
661*aca3beaaSApple OSS Distributions goto done;
662*aca3beaaSApple OSS Distributions }
663*aca3beaaSApple OSS Distributions
664*aca3beaaSApple OSS Distributions switch (opt) {
665*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_REGISTER: {
666*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request for registration");
667*aca3beaaSApple OSS Distributions error = netagent_handle_register_setopt(session, data, len);
668*aca3beaaSApple OSS Distributions break;
669*aca3beaaSApple OSS Distributions }
670*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_UPDATE: {
671*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request for update");
672*aca3beaaSApple OSS Distributions error = netagent_handle_update_setopt(session, data, len);
673*aca3beaaSApple OSS Distributions break;
674*aca3beaaSApple OSS Distributions }
675*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_UNREGISTER: {
676*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request for unregistration");
677*aca3beaaSApple OSS Distributions error = netagent_handle_unregister_setopt(session, data, len);
678*aca3beaaSApple OSS Distributions break;
679*aca3beaaSApple OSS Distributions }
680*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS: {
681*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request for assigning nexus");
682*aca3beaaSApple OSS Distributions error = netagent_handle_assign_nexus_setopt(session, data, len);
683*aca3beaaSApple OSS Distributions break;
684*aca3beaaSApple OSS Distributions }
685*aca3beaaSApple OSS Distributions case NETAGENT_MESSAGE_TYPE_ASSIGN_GROUP_MEMBERS: {
686*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request for assigning group members");
687*aca3beaaSApple OSS Distributions error = netagent_handle_assign_group_setopt(session, data, len);
688*aca3beaaSApple OSS Distributions break;
689*aca3beaaSApple OSS Distributions }
690*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_USE_COUNT: {
691*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to set use count");
692*aca3beaaSApple OSS Distributions error = netagent_handle_use_count_setopt(session, data, len);
693*aca3beaaSApple OSS Distributions break;
694*aca3beaaSApple OSS Distributions }
695*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_ADD_TOKEN: {
696*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to add a token");
697*aca3beaaSApple OSS Distributions error = netagent_handle_add_token_setopt(session, data, len);
698*aca3beaaSApple OSS Distributions break;
699*aca3beaaSApple OSS Distributions }
700*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_FLUSH_TOKENS: {
701*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to flush tokens");
702*aca3beaaSApple OSS Distributions error = netagent_handle_flush_tokens_setopt(session, data, len);
703*aca3beaaSApple OSS Distributions break;
704*aca3beaaSApple OSS Distributions }
705*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_TOKEN_LOW_WATER: {
706*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to set token low water mark");
707*aca3beaaSApple OSS Distributions error = netagent_handle_token_low_water_setopt(session, data, len);
708*aca3beaaSApple OSS Distributions break;
709*aca3beaaSApple OSS Distributions }
710*aca3beaaSApple OSS Distributions case NETAGENT_OPTION_TYPE_RESET_CLIENT_ERROR: {
711*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Request to reset client error");
712*aca3beaaSApple OSS Distributions error = netagent_handle_reset_client_error_setopt(session, data, len);
713*aca3beaaSApple OSS Distributions break;
714*aca3beaaSApple OSS Distributions }
715*aca3beaaSApple OSS Distributions default:
716*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Received unknown option");
717*aca3beaaSApple OSS Distributions error = ENOPROTOOPT;
718*aca3beaaSApple OSS Distributions break;
719*aca3beaaSApple OSS Distributions }
720*aca3beaaSApple OSS Distributions
721*aca3beaaSApple OSS Distributions done:
722*aca3beaaSApple OSS Distributions return error;
723*aca3beaaSApple OSS Distributions }
724*aca3beaaSApple OSS Distributions
725*aca3beaaSApple OSS Distributions // Session Management
726*aca3beaaSApple OSS Distributions static struct netagent_session *
netagent_create_session(u_int32_t control_unit)727*aca3beaaSApple OSS Distributions netagent_create_session(u_int32_t control_unit)
728*aca3beaaSApple OSS Distributions {
729*aca3beaaSApple OSS Distributions struct netagent_session *new_session = NULL;
730*aca3beaaSApple OSS Distributions
731*aca3beaaSApple OSS Distributions new_session = kalloc_type(struct netagent_session,
732*aca3beaaSApple OSS Distributions Z_WAITOK | Z_ZERO | Z_NOFAIL);
733*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
734*aca3beaaSApple OSS Distributions new_session->control_unit = control_unit;
735*aca3beaaSApple OSS Distributions lck_mtx_init(&new_session->session_lock, &netagent_mtx_grp, LCK_ATTR_NULL);
736*aca3beaaSApple OSS Distributions
737*aca3beaaSApple OSS Distributions return new_session;
738*aca3beaaSApple OSS Distributions }
739*aca3beaaSApple OSS Distributions
740*aca3beaaSApple OSS Distributions netagent_session_t
netagent_create(netagent_event_f event_handler,void * context)741*aca3beaaSApple OSS Distributions netagent_create(netagent_event_f event_handler, void *context)
742*aca3beaaSApple OSS Distributions {
743*aca3beaaSApple OSS Distributions struct netagent_session *session = netagent_create_session(0);
744*aca3beaaSApple OSS Distributions if (session == NULL) {
745*aca3beaaSApple OSS Distributions return NULL;
746*aca3beaaSApple OSS Distributions }
747*aca3beaaSApple OSS Distributions
748*aca3beaaSApple OSS Distributions session->event_handler = event_handler;
749*aca3beaaSApple OSS Distributions session->event_context = context;
750*aca3beaaSApple OSS Distributions return session;
751*aca3beaaSApple OSS Distributions }
752*aca3beaaSApple OSS Distributions
753*aca3beaaSApple OSS Distributions static void
netagent_token_free(struct netagent_token * token)754*aca3beaaSApple OSS Distributions netagent_token_free(struct netagent_token *token)
755*aca3beaaSApple OSS Distributions {
756*aca3beaaSApple OSS Distributions kfree_data(token->token_bytes, token->token_length);
757*aca3beaaSApple OSS Distributions kfree_type(struct netagent_token, token);
758*aca3beaaSApple OSS Distributions }
759*aca3beaaSApple OSS Distributions
760*aca3beaaSApple OSS Distributions static struct netagent_wrapper *
netagent_alloc_wrapper_memory(uint32_t data_size)761*aca3beaaSApple OSS Distributions netagent_alloc_wrapper_memory(uint32_t data_size)
762*aca3beaaSApple OSS Distributions {
763*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper;
764*aca3beaaSApple OSS Distributions
765*aca3beaaSApple OSS Distributions new_wrapper = kalloc_type(struct netagent_wrapper,
766*aca3beaaSApple OSS Distributions Z_WAITOK | Z_ZERO | Z_NOFAIL);
767*aca3beaaSApple OSS Distributions new_wrapper->netagent = kalloc_data(sizeof(struct netagent) + data_size,
768*aca3beaaSApple OSS Distributions Z_WAITOK | Z_NOFAIL);
769*aca3beaaSApple OSS Distributions
770*aca3beaaSApple OSS Distributions lck_rw_init(&new_wrapper->agent_lock, &netagent_mtx_grp, LCK_ATTR_NULL);
771*aca3beaaSApple OSS Distributions
772*aca3beaaSApple OSS Distributions return new_wrapper;
773*aca3beaaSApple OSS Distributions }
774*aca3beaaSApple OSS Distributions
775*aca3beaaSApple OSS Distributions static void
netagent_free_wrapper_memory(struct netagent_wrapper * wrapper)776*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(struct netagent_wrapper *wrapper)
777*aca3beaaSApple OSS Distributions {
778*aca3beaaSApple OSS Distributions // Before destroying the lock, take the lock exclusively and then
779*aca3beaaSApple OSS Distributions // drop it again. This ensures that no other thread was holding
780*aca3beaaSApple OSS Distributions // onto the lock at the time of destroying it.
781*aca3beaaSApple OSS Distributions // This can happen in netagent_client_message_with_params due
782*aca3beaaSApple OSS Distributions // to the fact that the wrapper lock needs to be held during the
783*aca3beaaSApple OSS Distributions // event callout, while the list lock has been released. Taking
784*aca3beaaSApple OSS Distributions // this lock here ensures that any such remaining thread completes
785*aca3beaaSApple OSS Distributions // before this object is released. Since the wrapper object has
786*aca3beaaSApple OSS Distributions // already been removed from any and all lists by this point,
787*aca3beaaSApple OSS Distributions // there isn't any way for a new thread to start referencing it.
788*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(wrapper);
789*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
790*aca3beaaSApple OSS Distributions lck_rw_destroy(&wrapper->agent_lock, &netagent_mtx_grp);
791*aca3beaaSApple OSS Distributions
792*aca3beaaSApple OSS Distributions kfree_data(wrapper->netagent, sizeof(struct netagent) +
793*aca3beaaSApple OSS Distributions wrapper->netagent->netagent_data_size);
794*aca3beaaSApple OSS Distributions kfree_type(struct netagent_wrapper, wrapper);
795*aca3beaaSApple OSS Distributions }
796*aca3beaaSApple OSS Distributions
797*aca3beaaSApple OSS Distributions static void
netagent_free_wrapper(struct netagent_wrapper * wrapper)798*aca3beaaSApple OSS Distributions netagent_free_wrapper(struct netagent_wrapper *wrapper)
799*aca3beaaSApple OSS Distributions {
800*aca3beaaSApple OSS Distributions // Free any leftover tokens
801*aca3beaaSApple OSS Distributions struct netagent_token *search_token = NULL;
802*aca3beaaSApple OSS Distributions struct netagent_token *temp_token = NULL;
803*aca3beaaSApple OSS Distributions TAILQ_FOREACH_SAFE(search_token, &wrapper->token_list, token_chain, temp_token) {
804*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&wrapper->token_list, search_token, token_chain);
805*aca3beaaSApple OSS Distributions netagent_token_free(search_token);
806*aca3beaaSApple OSS Distributions }
807*aca3beaaSApple OSS Distributions
808*aca3beaaSApple OSS Distributions // Free any pending client triggers
809*aca3beaaSApple OSS Distributions struct netagent_client *search_client = NULL;
810*aca3beaaSApple OSS Distributions struct netagent_client *temp_client = NULL;
811*aca3beaaSApple OSS Distributions LIST_FOREACH_SAFE(search_client, &wrapper->pending_triggers_list, client_chain, temp_client) {
812*aca3beaaSApple OSS Distributions LIST_REMOVE(search_client, client_chain);
813*aca3beaaSApple OSS Distributions kfree_type(struct netagent_client, search_client);
814*aca3beaaSApple OSS Distributions }
815*aca3beaaSApple OSS Distributions
816*aca3beaaSApple OSS Distributions // Free wrapper itself
817*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(wrapper);
818*aca3beaaSApple OSS Distributions }
819*aca3beaaSApple OSS Distributions
820*aca3beaaSApple OSS Distributions static void
netagent_unregister_session_wrapper(struct netagent_session * session)821*aca3beaaSApple OSS Distributions netagent_unregister_session_wrapper(struct netagent_session *session)
822*aca3beaaSApple OSS Distributions {
823*aca3beaaSApple OSS Distributions bool unregistered = FALSE;
824*aca3beaaSApple OSS Distributions uuid_t unregistered_uuid;
825*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = NULL;
826*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_EXCLUSIVE();
827*aca3beaaSApple OSS Distributions if (session != NULL) {
828*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
829*aca3beaaSApple OSS Distributions wrapper = session->wrapper;
830*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
831*aca3beaaSApple OSS Distributions if (netagent_registered_count > 0) {
832*aca3beaaSApple OSS Distributions netagent_registered_count--;
833*aca3beaaSApple OSS Distributions }
834*aca3beaaSApple OSS Distributions if ((session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
835*aca3beaaSApple OSS Distributions netagent_active_count > 0) {
836*aca3beaaSApple OSS Distributions netagent_active_count--;
837*aca3beaaSApple OSS Distributions }
838*aca3beaaSApple OSS Distributions
839*aca3beaaSApple OSS Distributions LIST_REMOVE(wrapper, list_chain);
840*aca3beaaSApple OSS Distributions
841*aca3beaaSApple OSS Distributions unregistered = TRUE;
842*aca3beaaSApple OSS Distributions uuid_copy(unregistered_uuid, session->wrapper->netagent->netagent_uuid);
843*aca3beaaSApple OSS Distributions
844*aca3beaaSApple OSS Distributions netagent_free_wrapper(session->wrapper);
845*aca3beaaSApple OSS Distributions session->wrapper = NULL;
846*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
847*aca3beaaSApple OSS Distributions }
848*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
849*aca3beaaSApple OSS Distributions }
850*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
851*aca3beaaSApple OSS Distributions
852*aca3beaaSApple OSS Distributions if (unregistered) {
853*aca3beaaSApple OSS Distributions ifnet_clear_netagent(unregistered_uuid);
854*aca3beaaSApple OSS Distributions netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED, TRUE, false);
855*aca3beaaSApple OSS Distributions }
856*aca3beaaSApple OSS Distributions }
857*aca3beaaSApple OSS Distributions
858*aca3beaaSApple OSS Distributions static void
netagent_delete_session(struct netagent_session * session)859*aca3beaaSApple OSS Distributions netagent_delete_session(struct netagent_session *session)
860*aca3beaaSApple OSS Distributions {
861*aca3beaaSApple OSS Distributions if (session != NULL) {
862*aca3beaaSApple OSS Distributions netagent_unregister_session_wrapper(session);
863*aca3beaaSApple OSS Distributions lck_mtx_destroy(&session->session_lock, &netagent_mtx_grp);
864*aca3beaaSApple OSS Distributions kfree_type(struct netagent_session, session);
865*aca3beaaSApple OSS Distributions }
866*aca3beaaSApple OSS Distributions }
867*aca3beaaSApple OSS Distributions
868*aca3beaaSApple OSS Distributions void
netagent_destroy(netagent_session_t session)869*aca3beaaSApple OSS Distributions netagent_destroy(netagent_session_t session)
870*aca3beaaSApple OSS Distributions {
871*aca3beaaSApple OSS Distributions return netagent_delete_session((struct netagent_session *)session);
872*aca3beaaSApple OSS Distributions }
873*aca3beaaSApple OSS Distributions
874*aca3beaaSApple OSS Distributions static size_t
netagent_packet_get_netagent_data_size(mbuf_t packet,size_t offset,int * err)875*aca3beaaSApple OSS Distributions netagent_packet_get_netagent_data_size(mbuf_t packet, size_t offset, int *err)
876*aca3beaaSApple OSS Distributions {
877*aca3beaaSApple OSS Distributions int error = 0;
878*aca3beaaSApple OSS Distributions
879*aca3beaaSApple OSS Distributions struct netagent netagent_peek;
880*aca3beaaSApple OSS Distributions memset(&netagent_peek, 0, sizeof(netagent_peek));
881*aca3beaaSApple OSS Distributions
882*aca3beaaSApple OSS Distributions *err = 0;
883*aca3beaaSApple OSS Distributions
884*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
885*aca3beaaSApple OSS Distributions if (error) {
886*aca3beaaSApple OSS Distributions *err = ENOENT;
887*aca3beaaSApple OSS Distributions return 0;
888*aca3beaaSApple OSS Distributions }
889*aca3beaaSApple OSS Distributions
890*aca3beaaSApple OSS Distributions return netagent_peek.netagent_data_size;
891*aca3beaaSApple OSS Distributions }
892*aca3beaaSApple OSS Distributions
893*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_register_inner(struct netagent_session * session,struct netagent_wrapper * new_wrapper)894*aca3beaaSApple OSS Distributions netagent_handle_register_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper)
895*aca3beaaSApple OSS Distributions {
896*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_EXCLUSIVE();
897*aca3beaaSApple OSS Distributions
898*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
899*aca3beaaSApple OSS Distributions if (session->wrapper != NULL) {
900*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
901*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
902*aca3beaaSApple OSS Distributions return EINVAL;
903*aca3beaaSApple OSS Distributions }
904*aca3beaaSApple OSS Distributions
905*aca3beaaSApple OSS Distributions new_wrapper->control_unit = session->control_unit;
906*aca3beaaSApple OSS Distributions new_wrapper->event_handler = session->event_handler;
907*aca3beaaSApple OSS Distributions new_wrapper->event_context = session->event_context;
908*aca3beaaSApple OSS Distributions new_wrapper->generation = g_next_generation++;
909*aca3beaaSApple OSS Distributions
910*aca3beaaSApple OSS Distributions session->wrapper = new_wrapper;
911*aca3beaaSApple OSS Distributions LIST_INSERT_HEAD(&shared_netagent_list, new_wrapper, list_chain);
912*aca3beaaSApple OSS Distributions TAILQ_INIT(&new_wrapper->token_list);
913*aca3beaaSApple OSS Distributions LIST_INIT(&new_wrapper->pending_triggers_list);
914*aca3beaaSApple OSS Distributions
915*aca3beaaSApple OSS Distributions new_wrapper->netagent->netagent_flags |= NETAGENT_FLAG_REGISTERED;
916*aca3beaaSApple OSS Distributions netagent_registered_count++;
917*aca3beaaSApple OSS Distributions if (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) {
918*aca3beaaSApple OSS Distributions netagent_active_count++;
919*aca3beaaSApple OSS Distributions }
920*aca3beaaSApple OSS Distributions
921*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
922*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
923*aca3beaaSApple OSS Distributions return 0;
924*aca3beaaSApple OSS Distributions }
925*aca3beaaSApple OSS Distributions
926*aca3beaaSApple OSS Distributions errno_t
netagent_register(netagent_session_t _session,struct netagent * agent)927*aca3beaaSApple OSS Distributions netagent_register(netagent_session_t _session, struct netagent *agent)
928*aca3beaaSApple OSS Distributions {
929*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
930*aca3beaaSApple OSS Distributions uuid_t registered_uuid;
931*aca3beaaSApple OSS Distributions
932*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)_session;
933*aca3beaaSApple OSS Distributions if (session == NULL) {
934*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot register agent on NULL session");
935*aca3beaaSApple OSS Distributions return EINVAL;
936*aca3beaaSApple OSS Distributions }
937*aca3beaaSApple OSS Distributions
938*aca3beaaSApple OSS Distributions if (agent == NULL) {
939*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
940*aca3beaaSApple OSS Distributions return EINVAL;
941*aca3beaaSApple OSS Distributions }
942*aca3beaaSApple OSS Distributions
943*aca3beaaSApple OSS Distributions size_t data_size = agent->netagent_data_size;
944*aca3beaaSApple OSS Distributions if (data_size > NETAGENT_MAX_DATA_SIZE) {
945*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu",
946*aca3beaaSApple OSS Distributions data_size);
947*aca3beaaSApple OSS Distributions return EINVAL;
948*aca3beaaSApple OSS Distributions }
949*aca3beaaSApple OSS Distributions
950*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
951*aca3beaaSApple OSS Distributions
952*aca3beaaSApple OSS Distributions __nochk_memcpy(new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
953*aca3beaaSApple OSS Distributions
954*aca3beaaSApple OSS Distributions uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
955*aca3beaaSApple OSS Distributions
956*aca3beaaSApple OSS Distributions errno_t error = netagent_handle_register_inner(session, new_wrapper);
957*aca3beaaSApple OSS Distributions if (error != 0) {
958*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
959*aca3beaaSApple OSS Distributions return error;
960*aca3beaaSApple OSS Distributions }
961*aca3beaaSApple OSS Distributions
962*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
963*aca3beaaSApple OSS Distributions netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
964*aca3beaaSApple OSS Distributions
965*aca3beaaSApple OSS Distributions return 0;
966*aca3beaaSApple OSS Distributions }
967*aca3beaaSApple OSS Distributions
968*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_register_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)969*aca3beaaSApple OSS Distributions netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
970*aca3beaaSApple OSS Distributions size_t payload_length)
971*aca3beaaSApple OSS Distributions {
972*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
973*aca3beaaSApple OSS Distributions errno_t response_error = 0;
974*aca3beaaSApple OSS Distributions struct netagent *register_netagent = (struct netagent *)(void *)payload;
975*aca3beaaSApple OSS Distributions uuid_t registered_uuid;
976*aca3beaaSApple OSS Distributions
977*aca3beaaSApple OSS Distributions if (session == NULL) {
978*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
979*aca3beaaSApple OSS Distributions response_error = EINVAL;
980*aca3beaaSApple OSS Distributions goto done;
981*aca3beaaSApple OSS Distributions }
982*aca3beaaSApple OSS Distributions
983*aca3beaaSApple OSS Distributions if (payload == NULL) {
984*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
985*aca3beaaSApple OSS Distributions response_error = EINVAL;
986*aca3beaaSApple OSS Distributions goto done;
987*aca3beaaSApple OSS Distributions }
988*aca3beaaSApple OSS Distributions
989*aca3beaaSApple OSS Distributions if (payload_length < sizeof(struct netagent)) {
990*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
991*aca3beaaSApple OSS Distributions payload_length, sizeof(struct netagent));
992*aca3beaaSApple OSS Distributions response_error = EINVAL;
993*aca3beaaSApple OSS Distributions goto done;
994*aca3beaaSApple OSS Distributions }
995*aca3beaaSApple OSS Distributions
996*aca3beaaSApple OSS Distributions size_t data_size = register_netagent->netagent_data_size;
997*aca3beaaSApple OSS Distributions if (data_size > NETAGENT_MAX_DATA_SIZE) {
998*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu", data_size);
999*aca3beaaSApple OSS Distributions response_error = EINVAL;
1000*aca3beaaSApple OSS Distributions goto done;
1001*aca3beaaSApple OSS Distributions }
1002*aca3beaaSApple OSS Distributions
1003*aca3beaaSApple OSS Distributions if (payload_length != (sizeof(struct netagent) + data_size)) {
1004*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
1005*aca3beaaSApple OSS Distributions response_error = EINVAL;
1006*aca3beaaSApple OSS Distributions goto done;
1007*aca3beaaSApple OSS Distributions }
1008*aca3beaaSApple OSS Distributions
1009*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
1010*aca3beaaSApple OSS Distributions
1011*aca3beaaSApple OSS Distributions __nochk_memcpy(new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
1012*aca3beaaSApple OSS Distributions
1013*aca3beaaSApple OSS Distributions uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
1014*aca3beaaSApple OSS Distributions
1015*aca3beaaSApple OSS Distributions response_error = netagent_handle_register_inner(session, new_wrapper);
1016*aca3beaaSApple OSS Distributions if (response_error != 0) {
1017*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1018*aca3beaaSApple OSS Distributions goto done;
1019*aca3beaaSApple OSS Distributions }
1020*aca3beaaSApple OSS Distributions
1021*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
1022*aca3beaaSApple OSS Distributions netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
1023*aca3beaaSApple OSS Distributions
1024*aca3beaaSApple OSS Distributions done:
1025*aca3beaaSApple OSS Distributions return response_error;
1026*aca3beaaSApple OSS Distributions }
1027*aca3beaaSApple OSS Distributions
1028*aca3beaaSApple OSS Distributions static void
netagent_handle_register_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1029*aca3beaaSApple OSS Distributions netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
1030*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset)
1031*aca3beaaSApple OSS Distributions {
1032*aca3beaaSApple OSS Distributions errno_t error;
1033*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
1034*aca3beaaSApple OSS Distributions u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1035*aca3beaaSApple OSS Distributions uuid_t registered_uuid;
1036*aca3beaaSApple OSS Distributions
1037*aca3beaaSApple OSS Distributions if (session == NULL) {
1038*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1039*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1040*aca3beaaSApple OSS Distributions goto fail;
1041*aca3beaaSApple OSS Distributions }
1042*aca3beaaSApple OSS Distributions
1043*aca3beaaSApple OSS Distributions if (payload_length < sizeof(struct netagent)) {
1044*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
1045*aca3beaaSApple OSS Distributions payload_length, sizeof(struct netagent));
1046*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1047*aca3beaaSApple OSS Distributions goto fail;
1048*aca3beaaSApple OSS Distributions }
1049*aca3beaaSApple OSS Distributions
1050*aca3beaaSApple OSS Distributions size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1051*aca3beaaSApple OSS Distributions if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
1052*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %zu",
1053*aca3beaaSApple OSS Distributions error, data_size);
1054*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1055*aca3beaaSApple OSS Distributions goto fail;
1056*aca3beaaSApple OSS Distributions }
1057*aca3beaaSApple OSS Distributions
1058*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
1059*aca3beaaSApple OSS Distributions
1060*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
1061*aca3beaaSApple OSS Distributions new_wrapper->netagent);
1062*aca3beaaSApple OSS Distributions if (error) {
1063*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1064*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1065*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1066*aca3beaaSApple OSS Distributions goto fail;
1067*aca3beaaSApple OSS Distributions }
1068*aca3beaaSApple OSS Distributions
1069*aca3beaaSApple OSS Distributions uuid_copy(registered_uuid, new_wrapper->netagent->netagent_uuid);
1070*aca3beaaSApple OSS Distributions
1071*aca3beaaSApple OSS Distributions error = netagent_handle_register_inner(session, new_wrapper);
1072*aca3beaaSApple OSS Distributions if (error) {
1073*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to register agent: %d", error);
1074*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1075*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1076*aca3beaaSApple OSS Distributions goto fail;
1077*aca3beaaSApple OSS Distributions }
1078*aca3beaaSApple OSS Distributions
1079*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
1080*aca3beaaSApple OSS Distributions netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
1081*aca3beaaSApple OSS Distributions netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
1082*aca3beaaSApple OSS Distributions return;
1083*aca3beaaSApple OSS Distributions fail:
1084*aca3beaaSApple OSS Distributions netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
1085*aca3beaaSApple OSS Distributions }
1086*aca3beaaSApple OSS Distributions
1087*aca3beaaSApple OSS Distributions errno_t
netagent_unregister(netagent_session_t _session)1088*aca3beaaSApple OSS Distributions netagent_unregister(netagent_session_t _session)
1089*aca3beaaSApple OSS Distributions {
1090*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)_session;
1091*aca3beaaSApple OSS Distributions if (session == NULL) {
1092*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot unregister NULL session");
1093*aca3beaaSApple OSS Distributions return EINVAL;
1094*aca3beaaSApple OSS Distributions }
1095*aca3beaaSApple OSS Distributions
1096*aca3beaaSApple OSS Distributions netagent_unregister_session_wrapper(session);
1097*aca3beaaSApple OSS Distributions return 0;
1098*aca3beaaSApple OSS Distributions }
1099*aca3beaaSApple OSS Distributions
1100*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_unregister_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1101*aca3beaaSApple OSS Distributions netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
1102*aca3beaaSApple OSS Distributions size_t payload_length)
1103*aca3beaaSApple OSS Distributions {
1104*aca3beaaSApple OSS Distributions #pragma unused(payload, payload_length)
1105*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1106*aca3beaaSApple OSS Distributions
1107*aca3beaaSApple OSS Distributions if (session == NULL) {
1108*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1109*aca3beaaSApple OSS Distributions response_error = EINVAL;
1110*aca3beaaSApple OSS Distributions goto done;
1111*aca3beaaSApple OSS Distributions }
1112*aca3beaaSApple OSS Distributions
1113*aca3beaaSApple OSS Distributions netagent_unregister_session_wrapper(session);
1114*aca3beaaSApple OSS Distributions
1115*aca3beaaSApple OSS Distributions done:
1116*aca3beaaSApple OSS Distributions return response_error;
1117*aca3beaaSApple OSS Distributions }
1118*aca3beaaSApple OSS Distributions
1119*aca3beaaSApple OSS Distributions static void
netagent_handle_unregister_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1120*aca3beaaSApple OSS Distributions netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
1121*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset)
1122*aca3beaaSApple OSS Distributions {
1123*aca3beaaSApple OSS Distributions #pragma unused(payload_length, packet, offset)
1124*aca3beaaSApple OSS Distributions u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1125*aca3beaaSApple OSS Distributions
1126*aca3beaaSApple OSS Distributions if (session == NULL) {
1127*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1128*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1129*aca3beaaSApple OSS Distributions goto fail;
1130*aca3beaaSApple OSS Distributions }
1131*aca3beaaSApple OSS Distributions
1132*aca3beaaSApple OSS Distributions netagent_unregister_session_wrapper(session);
1133*aca3beaaSApple OSS Distributions
1134*aca3beaaSApple OSS Distributions netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
1135*aca3beaaSApple OSS Distributions return;
1136*aca3beaaSApple OSS Distributions fail:
1137*aca3beaaSApple OSS Distributions netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
1138*aca3beaaSApple OSS Distributions }
1139*aca3beaaSApple OSS Distributions
1140*aca3beaaSApple OSS Distributions static void
netagent_send_cellular_failed_event(struct netagent_wrapper * wrapper,pid_t pid,uuid_t proc_uuid)1141*aca3beaaSApple OSS Distributions netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
1142*aca3beaaSApple OSS Distributions pid_t pid, uuid_t proc_uuid)
1143*aca3beaaSApple OSS Distributions {
1144*aca3beaaSApple OSS Distributions if (strncmp(wrapper->netagent->netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
1145*aca3beaaSApple OSS Distributions return;
1146*aca3beaaSApple OSS Distributions }
1147*aca3beaaSApple OSS Distributions
1148*aca3beaaSApple OSS Distributions struct kev_netpolicy_ifdenied ev_ifdenied;
1149*aca3beaaSApple OSS Distributions
1150*aca3beaaSApple OSS Distributions bzero(&ev_ifdenied, sizeof(ev_ifdenied));
1151*aca3beaaSApple OSS Distributions
1152*aca3beaaSApple OSS Distributions ev_ifdenied.ev_data.epid = (u_int64_t)pid;
1153*aca3beaaSApple OSS Distributions uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
1154*aca3beaaSApple OSS Distributions ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
1155*aca3beaaSApple OSS Distributions
1156*aca3beaaSApple OSS Distributions netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
1157*aca3beaaSApple OSS Distributions }
1158*aca3beaaSApple OSS Distributions
1159*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_update_inner(struct netagent_session * session,struct netagent_wrapper * new_wrapper,size_t data_size,u_int8_t * agent_changed,netagent_error_domain_t error_domain)1160*aca3beaaSApple OSS Distributions netagent_handle_update_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper,
1161*aca3beaaSApple OSS Distributions size_t data_size, u_int8_t *agent_changed, netagent_error_domain_t error_domain)
1162*aca3beaaSApple OSS Distributions {
1163*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1164*aca3beaaSApple OSS Distributions
1165*aca3beaaSApple OSS Distributions if (agent_changed == NULL) {
1166*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
1167*aca3beaaSApple OSS Distributions return EINVAL;
1168*aca3beaaSApple OSS Distributions }
1169*aca3beaaSApple OSS Distributions
1170*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_EXCLUSIVE();
1171*aca3beaaSApple OSS Distributions
1172*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1173*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1174*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1175*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
1176*aca3beaaSApple OSS Distributions response_error = ENOENT;
1177*aca3beaaSApple OSS Distributions return response_error;
1178*aca3beaaSApple OSS Distributions }
1179*aca3beaaSApple OSS Distributions
1180*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
1181*aca3beaaSApple OSS Distributions
1182*aca3beaaSApple OSS Distributions if (uuid_compare(session->wrapper->netagent->netagent_uuid, new_wrapper->netagent->netagent_uuid) != 0 ||
1183*aca3beaaSApple OSS Distributions memcmp(&session->wrapper->netagent->netagent_domain, &new_wrapper->netagent->netagent_domain,
1184*aca3beaaSApple OSS Distributions sizeof(new_wrapper->netagent->netagent_domain)) != 0 ||
1185*aca3beaaSApple OSS Distributions memcmp(&session->wrapper->netagent->netagent_type, &new_wrapper->netagent->netagent_type,
1186*aca3beaaSApple OSS Distributions sizeof(new_wrapper->netagent->netagent_type)) != 0) {
1187*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1188*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1189*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
1190*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
1191*aca3beaaSApple OSS Distributions if (error_domain == kNetagentErrorDomainPOSIX) {
1192*aca3beaaSApple OSS Distributions response_error = EINVAL;
1193*aca3beaaSApple OSS Distributions } else if (error_domain == kNetagentErrorDomainUserDefined) {
1194*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
1195*aca3beaaSApple OSS Distributions }
1196*aca3beaaSApple OSS Distributions return response_error;
1197*aca3beaaSApple OSS Distributions }
1198*aca3beaaSApple OSS Distributions
1199*aca3beaaSApple OSS Distributions new_wrapper->netagent->netagent_flags |= NETAGENT_FLAG_REGISTERED;
1200*aca3beaaSApple OSS Distributions if (session->wrapper->netagent->netagent_data_size == new_wrapper->netagent->netagent_data_size &&
1201*aca3beaaSApple OSS Distributions memcmp(session->wrapper->netagent, new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
1202*aca3beaaSApple OSS Distributions // Agent is exactly identical, don't increment the generation count
1203*aca3beaaSApple OSS Distributions
1204*aca3beaaSApple OSS Distributions // Make a copy of the list of pending clients, and clear the current list
1205*aca3beaaSApple OSS Distributions struct netagent_client_list_s pending_triggers_list_copy;
1206*aca3beaaSApple OSS Distributions LIST_INIT(&pending_triggers_list_copy);
1207*aca3beaaSApple OSS Distributions struct netagent_client *search_client = NULL;
1208*aca3beaaSApple OSS Distributions struct netagent_client *temp_client = NULL;
1209*aca3beaaSApple OSS Distributions LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
1210*aca3beaaSApple OSS Distributions LIST_REMOVE(search_client, client_chain);
1211*aca3beaaSApple OSS Distributions LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
1212*aca3beaaSApple OSS Distributions }
1213*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1214*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1215*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
1216*aca3beaaSApple OSS Distributions
1217*aca3beaaSApple OSS Distributions // Update pending client triggers without holding a lock
1218*aca3beaaSApple OSS Distributions search_client = NULL;
1219*aca3beaaSApple OSS Distributions temp_client = NULL;
1220*aca3beaaSApple OSS Distributions LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
1221*aca3beaaSApple OSS Distributions necp_force_update_client(search_client->client_id, session->wrapper->netagent->netagent_uuid, session->wrapper->generation);
1222*aca3beaaSApple OSS Distributions netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
1223*aca3beaaSApple OSS Distributions LIST_REMOVE(search_client, client_chain);
1224*aca3beaaSApple OSS Distributions kfree_type(struct netagent_client, search_client);
1225*aca3beaaSApple OSS Distributions }
1226*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
1227*aca3beaaSApple OSS Distributions *agent_changed = FALSE;
1228*aca3beaaSApple OSS Distributions return response_error;
1229*aca3beaaSApple OSS Distributions }
1230*aca3beaaSApple OSS Distributions
1231*aca3beaaSApple OSS Distributions new_wrapper->generation = g_next_generation++;
1232*aca3beaaSApple OSS Distributions new_wrapper->use_count = session->wrapper->use_count;
1233*aca3beaaSApple OSS Distributions
1234*aca3beaaSApple OSS Distributions TAILQ_INIT(&new_wrapper->token_list);
1235*aca3beaaSApple OSS Distributions TAILQ_CONCAT(&new_wrapper->token_list, &session->wrapper->token_list, token_chain);
1236*aca3beaaSApple OSS Distributions new_wrapper->token_count = session->wrapper->token_count;
1237*aca3beaaSApple OSS Distributions new_wrapper->token_low_water = session->wrapper->token_low_water;
1238*aca3beaaSApple OSS Distributions new_wrapper->last_client_error = session->wrapper->last_client_error;
1239*aca3beaaSApple OSS Distributions new_wrapper->client_error_count = session->wrapper->client_error_count;
1240*aca3beaaSApple OSS Distributions
1241*aca3beaaSApple OSS Distributions if ((new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1242*aca3beaaSApple OSS Distributions !(session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1243*aca3beaaSApple OSS Distributions netagent_active_count++;
1244*aca3beaaSApple OSS Distributions } else if (!(new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1245*aca3beaaSApple OSS Distributions (session->wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1246*aca3beaaSApple OSS Distributions netagent_active_count > 0) {
1247*aca3beaaSApple OSS Distributions netagent_active_count--;
1248*aca3beaaSApple OSS Distributions }
1249*aca3beaaSApple OSS Distributions
1250*aca3beaaSApple OSS Distributions LIST_REMOVE(session->wrapper, list_chain);
1251*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1252*aca3beaaSApple OSS Distributions netagent_free_wrapper(session->wrapper);
1253*aca3beaaSApple OSS Distributions session->wrapper = new_wrapper;
1254*aca3beaaSApple OSS Distributions new_wrapper->control_unit = session->control_unit;
1255*aca3beaaSApple OSS Distributions new_wrapper->event_handler = session->event_handler;
1256*aca3beaaSApple OSS Distributions new_wrapper->event_context = session->event_context;
1257*aca3beaaSApple OSS Distributions LIST_INSERT_HEAD(&shared_netagent_list, new_wrapper, list_chain);
1258*aca3beaaSApple OSS Distributions LIST_INIT(&new_wrapper->pending_triggers_list);
1259*aca3beaaSApple OSS Distributions
1260*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1261*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
1262*aca3beaaSApple OSS Distributions
1263*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Updated agent");
1264*aca3beaaSApple OSS Distributions *agent_changed = TRUE;
1265*aca3beaaSApple OSS Distributions
1266*aca3beaaSApple OSS Distributions return response_error;
1267*aca3beaaSApple OSS Distributions }
1268*aca3beaaSApple OSS Distributions
1269*aca3beaaSApple OSS Distributions errno_t
netagent_update(netagent_session_t _session,struct netagent * agent)1270*aca3beaaSApple OSS Distributions netagent_update(netagent_session_t _session, struct netagent *agent)
1271*aca3beaaSApple OSS Distributions {
1272*aca3beaaSApple OSS Distributions u_int8_t agent_changed;
1273*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
1274*aca3beaaSApple OSS Distributions bool should_update_immediately;
1275*aca3beaaSApple OSS Distributions uuid_t updated_uuid;
1276*aca3beaaSApple OSS Distributions
1277*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)_session;
1278*aca3beaaSApple OSS Distributions if (session == NULL) {
1279*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot update agent on NULL session");
1280*aca3beaaSApple OSS Distributions return EINVAL;
1281*aca3beaaSApple OSS Distributions }
1282*aca3beaaSApple OSS Distributions
1283*aca3beaaSApple OSS Distributions if (agent == NULL) {
1284*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
1285*aca3beaaSApple OSS Distributions return EINVAL;
1286*aca3beaaSApple OSS Distributions }
1287*aca3beaaSApple OSS Distributions
1288*aca3beaaSApple OSS Distributions size_t data_size = agent->netagent_data_size;
1289*aca3beaaSApple OSS Distributions if (data_size > NETAGENT_MAX_DATA_SIZE) {
1290*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1291*aca3beaaSApple OSS Distributions return EINVAL;
1292*aca3beaaSApple OSS Distributions }
1293*aca3beaaSApple OSS Distributions
1294*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
1295*aca3beaaSApple OSS Distributions
1296*aca3beaaSApple OSS Distributions __nochk_memcpy(new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
1297*aca3beaaSApple OSS Distributions
1298*aca3beaaSApple OSS Distributions uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1299*aca3beaaSApple OSS Distributions should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1300*aca3beaaSApple OSS Distributions
1301*aca3beaaSApple OSS Distributions errno_t error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1302*aca3beaaSApple OSS Distributions if (error == 0) {
1303*aca3beaaSApple OSS Distributions netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1304*aca3beaaSApple OSS Distributions if (agent_changed == FALSE) {
1305*aca3beaaSApple OSS Distributions // The session wrapper does not need the "new_wrapper" as nothing changed
1306*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1307*aca3beaaSApple OSS Distributions }
1308*aca3beaaSApple OSS Distributions } else {
1309*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1310*aca3beaaSApple OSS Distributions return error;
1311*aca3beaaSApple OSS Distributions }
1312*aca3beaaSApple OSS Distributions
1313*aca3beaaSApple OSS Distributions return 0;
1314*aca3beaaSApple OSS Distributions }
1315*aca3beaaSApple OSS Distributions
1316*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_update_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1317*aca3beaaSApple OSS Distributions netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1318*aca3beaaSApple OSS Distributions {
1319*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
1320*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1321*aca3beaaSApple OSS Distributions struct netagent *update_netagent = (struct netagent *)(void *)payload;
1322*aca3beaaSApple OSS Distributions u_int8_t agent_changed;
1323*aca3beaaSApple OSS Distributions bool should_update_immediately;
1324*aca3beaaSApple OSS Distributions uuid_t updated_uuid;
1325*aca3beaaSApple OSS Distributions
1326*aca3beaaSApple OSS Distributions if (session == NULL) {
1327*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1328*aca3beaaSApple OSS Distributions response_error = EINVAL;
1329*aca3beaaSApple OSS Distributions goto done;
1330*aca3beaaSApple OSS Distributions }
1331*aca3beaaSApple OSS Distributions
1332*aca3beaaSApple OSS Distributions if (payload == NULL) {
1333*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1334*aca3beaaSApple OSS Distributions response_error = EINVAL;
1335*aca3beaaSApple OSS Distributions goto done;
1336*aca3beaaSApple OSS Distributions }
1337*aca3beaaSApple OSS Distributions
1338*aca3beaaSApple OSS Distributions if (payload_length < sizeof(struct netagent)) {
1339*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1340*aca3beaaSApple OSS Distributions payload_length, sizeof(struct netagent));
1341*aca3beaaSApple OSS Distributions response_error = EINVAL;
1342*aca3beaaSApple OSS Distributions goto done;
1343*aca3beaaSApple OSS Distributions }
1344*aca3beaaSApple OSS Distributions
1345*aca3beaaSApple OSS Distributions size_t data_size = update_netagent->netagent_data_size;
1346*aca3beaaSApple OSS Distributions if (data_size > NETAGENT_MAX_DATA_SIZE) {
1347*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1348*aca3beaaSApple OSS Distributions response_error = EINVAL;
1349*aca3beaaSApple OSS Distributions goto done;
1350*aca3beaaSApple OSS Distributions }
1351*aca3beaaSApple OSS Distributions
1352*aca3beaaSApple OSS Distributions if (payload_length != (sizeof(struct netagent) + data_size)) {
1353*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
1354*aca3beaaSApple OSS Distributions response_error = EINVAL;
1355*aca3beaaSApple OSS Distributions goto done;
1356*aca3beaaSApple OSS Distributions }
1357*aca3beaaSApple OSS Distributions
1358*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
1359*aca3beaaSApple OSS Distributions
1360*aca3beaaSApple OSS Distributions __nochk_memcpy(new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1361*aca3beaaSApple OSS Distributions
1362*aca3beaaSApple OSS Distributions uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1363*aca3beaaSApple OSS Distributions should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1364*aca3beaaSApple OSS Distributions
1365*aca3beaaSApple OSS Distributions response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1366*aca3beaaSApple OSS Distributions if (response_error == 0) {
1367*aca3beaaSApple OSS Distributions netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1368*aca3beaaSApple OSS Distributions if (agent_changed == FALSE) {
1369*aca3beaaSApple OSS Distributions // The session wrapper does not need the "new_wrapper" as nothing changed
1370*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1371*aca3beaaSApple OSS Distributions }
1372*aca3beaaSApple OSS Distributions } else {
1373*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1374*aca3beaaSApple OSS Distributions }
1375*aca3beaaSApple OSS Distributions
1376*aca3beaaSApple OSS Distributions done:
1377*aca3beaaSApple OSS Distributions return response_error;
1378*aca3beaaSApple OSS Distributions }
1379*aca3beaaSApple OSS Distributions
1380*aca3beaaSApple OSS Distributions static void
netagent_handle_update_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1381*aca3beaaSApple OSS Distributions netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1382*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset)
1383*aca3beaaSApple OSS Distributions {
1384*aca3beaaSApple OSS Distributions int error;
1385*aca3beaaSApple OSS Distributions struct netagent_wrapper *new_wrapper = NULL;
1386*aca3beaaSApple OSS Distributions u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1387*aca3beaaSApple OSS Distributions u_int8_t agent_changed;
1388*aca3beaaSApple OSS Distributions uuid_t updated_uuid;
1389*aca3beaaSApple OSS Distributions bool should_update_immediately;
1390*aca3beaaSApple OSS Distributions
1391*aca3beaaSApple OSS Distributions if (session == NULL) {
1392*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1393*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1394*aca3beaaSApple OSS Distributions goto fail;
1395*aca3beaaSApple OSS Distributions }
1396*aca3beaaSApple OSS Distributions
1397*aca3beaaSApple OSS Distributions if (payload_length < sizeof(struct netagent)) {
1398*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1399*aca3beaaSApple OSS Distributions payload_length, sizeof(struct netagent));
1400*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1401*aca3beaaSApple OSS Distributions goto fail;
1402*aca3beaaSApple OSS Distributions }
1403*aca3beaaSApple OSS Distributions
1404*aca3beaaSApple OSS Distributions size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1405*aca3beaaSApple OSS Distributions if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
1406*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %zu",
1407*aca3beaaSApple OSS Distributions error, data_size);
1408*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1409*aca3beaaSApple OSS Distributions goto fail;
1410*aca3beaaSApple OSS Distributions }
1411*aca3beaaSApple OSS Distributions
1412*aca3beaaSApple OSS Distributions new_wrapper = netagent_alloc_wrapper_memory(data_size);
1413*aca3beaaSApple OSS Distributions
1414*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, new_wrapper->netagent);
1415*aca3beaaSApple OSS Distributions if (error) {
1416*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1417*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1418*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1419*aca3beaaSApple OSS Distributions goto fail;
1420*aca3beaaSApple OSS Distributions }
1421*aca3beaaSApple OSS Distributions
1422*aca3beaaSApple OSS Distributions uuid_copy(updated_uuid, new_wrapper->netagent->netagent_uuid);
1423*aca3beaaSApple OSS Distributions should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent->netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1424*aca3beaaSApple OSS Distributions
1425*aca3beaaSApple OSS Distributions response_error = (u_int32_t)netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainUserDefined);
1426*aca3beaaSApple OSS Distributions if (response_error != 0) {
1427*aca3beaaSApple OSS Distributions if (response_error == ENOENT) {
1428*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1429*aca3beaaSApple OSS Distributions }
1430*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1431*aca3beaaSApple OSS Distributions goto fail;
1432*aca3beaaSApple OSS Distributions }
1433*aca3beaaSApple OSS Distributions
1434*aca3beaaSApple OSS Distributions netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1435*aca3beaaSApple OSS Distributions
1436*aca3beaaSApple OSS Distributions netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1437*aca3beaaSApple OSS Distributions
1438*aca3beaaSApple OSS Distributions if (agent_changed == FALSE) {
1439*aca3beaaSApple OSS Distributions // The session wrapper does not need the "new_wrapper" as nothing changed
1440*aca3beaaSApple OSS Distributions netagent_free_wrapper_memory(new_wrapper);
1441*aca3beaaSApple OSS Distributions }
1442*aca3beaaSApple OSS Distributions
1443*aca3beaaSApple OSS Distributions return;
1444*aca3beaaSApple OSS Distributions fail:
1445*aca3beaaSApple OSS Distributions netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1446*aca3beaaSApple OSS Distributions }
1447*aca3beaaSApple OSS Distributions
1448*aca3beaaSApple OSS Distributions static void
netagent_handle_get(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1449*aca3beaaSApple OSS Distributions netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1450*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset)
1451*aca3beaaSApple OSS Distributions {
1452*aca3beaaSApple OSS Distributions #pragma unused(payload_length, packet, offset)
1453*aca3beaaSApple OSS Distributions u_int8_t *response = NULL;
1454*aca3beaaSApple OSS Distributions u_int8_t *cursor = NULL;
1455*aca3beaaSApple OSS Distributions u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1456*aca3beaaSApple OSS Distributions
1457*aca3beaaSApple OSS Distributions if (session == NULL) {
1458*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1459*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1460*aca3beaaSApple OSS Distributions goto fail;
1461*aca3beaaSApple OSS Distributions }
1462*aca3beaaSApple OSS Distributions
1463*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1464*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1465*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1466*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1467*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1468*aca3beaaSApple OSS Distributions goto fail;
1469*aca3beaaSApple OSS Distributions }
1470*aca3beaaSApple OSS Distributions
1471*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1472*aca3beaaSApple OSS Distributions
1473*aca3beaaSApple OSS Distributions size_t response_size = sizeof(struct netagent_message_header)
1474*aca3beaaSApple OSS Distributions + sizeof(struct netagent)
1475*aca3beaaSApple OSS Distributions + session->wrapper->netagent->netagent_data_size;
1476*aca3beaaSApple OSS Distributions response = (u_int8_t *)kalloc_data(response_size, Z_WAITOK);
1477*aca3beaaSApple OSS Distributions if (response == NULL) {
1478*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1479*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1480*aca3beaaSApple OSS Distributions goto fail;
1481*aca3beaaSApple OSS Distributions }
1482*aca3beaaSApple OSS Distributions
1483*aca3beaaSApple OSS Distributions cursor = response;
1484*aca3beaaSApple OSS Distributions cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1485*aca3beaaSApple OSS Distributions NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1486*aca3beaaSApple OSS Distributions response_size - sizeof(struct netagent_message_header));
1487*aca3beaaSApple OSS Distributions memcpy(cursor, session->wrapper->netagent, sizeof(struct netagent) +
1488*aca3beaaSApple OSS Distributions session->wrapper->netagent->netagent_data_size);
1489*aca3beaaSApple OSS Distributions
1490*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1491*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1492*aca3beaaSApple OSS Distributions
1493*aca3beaaSApple OSS Distributions if (!netagent_send_ctl_data(session->control_unit, response, response_size)) {
1494*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to send response");
1495*aca3beaaSApple OSS Distributions }
1496*aca3beaaSApple OSS Distributions kfree_data(response, response_size);
1497*aca3beaaSApple OSS Distributions return;
1498*aca3beaaSApple OSS Distributions fail:
1499*aca3beaaSApple OSS Distributions netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1500*aca3beaaSApple OSS Distributions }
1501*aca3beaaSApple OSS Distributions
1502*aca3beaaSApple OSS Distributions errno_t
netagent_assign_nexus(netagent_session_t _session,uuid_t necp_client_uuid,void * assign_message,size_t assigned_results_length)1503*aca3beaaSApple OSS Distributions netagent_assign_nexus(netagent_session_t _session, uuid_t necp_client_uuid,
1504*aca3beaaSApple OSS Distributions void *assign_message, size_t assigned_results_length)
1505*aca3beaaSApple OSS Distributions {
1506*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)_session;
1507*aca3beaaSApple OSS Distributions uuid_t netagent_uuid;
1508*aca3beaaSApple OSS Distributions if (session == NULL) {
1509*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1510*aca3beaaSApple OSS Distributions return EINVAL;
1511*aca3beaaSApple OSS Distributions }
1512*aca3beaaSApple OSS Distributions
1513*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1514*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1515*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1516*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent");
1517*aca3beaaSApple OSS Distributions return ENOENT;
1518*aca3beaaSApple OSS Distributions }
1519*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1520*aca3beaaSApple OSS Distributions uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1521*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1522*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1523*aca3beaaSApple OSS Distributions
1524*aca3beaaSApple OSS Distributions // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1525*aca3beaaSApple OSS Distributions int error = necp_assign_client_result(netagent_uuid, necp_client_uuid, assign_message, assigned_results_length);
1526*aca3beaaSApple OSS Distributions if (error) {
1527*aca3beaaSApple OSS Distributions // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1528*aca3beaaSApple OSS Distributions NETAGENTLOG((error == ENOENT ? LOG_DEBUG : LOG_ERR), "Client assignment failed: %d", error);
1529*aca3beaaSApple OSS Distributions return error;
1530*aca3beaaSApple OSS Distributions }
1531*aca3beaaSApple OSS Distributions
1532*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1533*aca3beaaSApple OSS Distributions return 0;
1534*aca3beaaSApple OSS Distributions }
1535*aca3beaaSApple OSS Distributions
1536*aca3beaaSApple OSS Distributions errno_t
netagent_update_flow_protoctl_event(netagent_session_t _session,uuid_t client_id,uint32_t protoctl_event_code,uint32_t protoctl_event_val,uint32_t protoctl_event_tcp_seq_number)1537*aca3beaaSApple OSS Distributions netagent_update_flow_protoctl_event(netagent_session_t _session,
1538*aca3beaaSApple OSS Distributions uuid_t client_id, uint32_t protoctl_event_code,
1539*aca3beaaSApple OSS Distributions uint32_t protoctl_event_val, uint32_t protoctl_event_tcp_seq_number)
1540*aca3beaaSApple OSS Distributions {
1541*aca3beaaSApple OSS Distributions struct netagent_session *session = (struct netagent_session *)_session;
1542*aca3beaaSApple OSS Distributions uuid_t netagent_uuid;
1543*aca3beaaSApple OSS Distributions int error = 0;
1544*aca3beaaSApple OSS Distributions
1545*aca3beaaSApple OSS Distributions if (session == NULL) {
1546*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1547*aca3beaaSApple OSS Distributions return EINVAL;
1548*aca3beaaSApple OSS Distributions }
1549*aca3beaaSApple OSS Distributions
1550*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1551*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1552*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1553*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent");
1554*aca3beaaSApple OSS Distributions return ENOENT;
1555*aca3beaaSApple OSS Distributions }
1556*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1557*aca3beaaSApple OSS Distributions uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1558*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1559*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1560*aca3beaaSApple OSS Distributions
1561*aca3beaaSApple OSS Distributions error = necp_update_flow_protoctl_event(netagent_uuid,
1562*aca3beaaSApple OSS Distributions client_id, protoctl_event_code, protoctl_event_val, protoctl_event_tcp_seq_number);
1563*aca3beaaSApple OSS Distributions
1564*aca3beaaSApple OSS Distributions return error;
1565*aca3beaaSApple OSS Distributions }
1566*aca3beaaSApple OSS Distributions
1567*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_assign_nexus_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1568*aca3beaaSApple OSS Distributions netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1569*aca3beaaSApple OSS Distributions size_t payload_length)
1570*aca3beaaSApple OSS Distributions {
1571*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1572*aca3beaaSApple OSS Distributions struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1573*aca3beaaSApple OSS Distributions uuid_t client_id;
1574*aca3beaaSApple OSS Distributions uuid_t netagent_uuid;
1575*aca3beaaSApple OSS Distributions u_int8_t *assigned_results = NULL;
1576*aca3beaaSApple OSS Distributions
1577*aca3beaaSApple OSS Distributions if (session == NULL) {
1578*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1579*aca3beaaSApple OSS Distributions response_error = ENOENT;
1580*aca3beaaSApple OSS Distributions goto done;
1581*aca3beaaSApple OSS Distributions }
1582*aca3beaaSApple OSS Distributions
1583*aca3beaaSApple OSS Distributions if (payload == NULL) {
1584*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1585*aca3beaaSApple OSS Distributions response_error = EINVAL;
1586*aca3beaaSApple OSS Distributions goto done;
1587*aca3beaaSApple OSS Distributions }
1588*aca3beaaSApple OSS Distributions
1589*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1590*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1591*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1592*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1593*aca3beaaSApple OSS Distributions response_error = ENOENT;
1594*aca3beaaSApple OSS Distributions goto done;
1595*aca3beaaSApple OSS Distributions }
1596*aca3beaaSApple OSS Distributions
1597*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1598*aca3beaaSApple OSS Distributions uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1599*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1600*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1601*aca3beaaSApple OSS Distributions
1602*aca3beaaSApple OSS Distributions if (payload_length < sizeof(uuid_t)) {
1603*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1604*aca3beaaSApple OSS Distributions response_error = EINVAL;
1605*aca3beaaSApple OSS Distributions goto done;
1606*aca3beaaSApple OSS Distributions }
1607*aca3beaaSApple OSS Distributions
1608*aca3beaaSApple OSS Distributions memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1609*aca3beaaSApple OSS Distributions size_t assigned_results_length = (payload_length - sizeof(client_id));
1610*aca3beaaSApple OSS Distributions
1611*aca3beaaSApple OSS Distributions if (assigned_results_length > 0) {
1612*aca3beaaSApple OSS Distributions assigned_results = kalloc_data(assigned_results_length, Z_WAITOK);
1613*aca3beaaSApple OSS Distributions if (assigned_results == NULL) {
1614*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1615*aca3beaaSApple OSS Distributions response_error = ENOMEM;
1616*aca3beaaSApple OSS Distributions goto done;
1617*aca3beaaSApple OSS Distributions }
1618*aca3beaaSApple OSS Distributions memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1619*aca3beaaSApple OSS Distributions }
1620*aca3beaaSApple OSS Distributions
1621*aca3beaaSApple OSS Distributions // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1622*aca3beaaSApple OSS Distributions response_error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1623*aca3beaaSApple OSS Distributions if (response_error) {
1624*aca3beaaSApple OSS Distributions // necp_assign_client_result returns POSIX errors
1625*aca3beaaSApple OSS Distributions kfree_data(assigned_results, assigned_results_length);
1626*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1627*aca3beaaSApple OSS Distributions goto done;
1628*aca3beaaSApple OSS Distributions }
1629*aca3beaaSApple OSS Distributions
1630*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1631*aca3beaaSApple OSS Distributions done:
1632*aca3beaaSApple OSS Distributions return response_error;
1633*aca3beaaSApple OSS Distributions }
1634*aca3beaaSApple OSS Distributions
1635*aca3beaaSApple OSS Distributions
1636*aca3beaaSApple OSS Distributions static void
netagent_handle_assign_nexus_message(struct netagent_session * session,u_int32_t message_id,size_t payload_length,mbuf_t packet,size_t offset)1637*aca3beaaSApple OSS Distributions netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1638*aca3beaaSApple OSS Distributions size_t payload_length, mbuf_t packet, size_t offset)
1639*aca3beaaSApple OSS Distributions {
1640*aca3beaaSApple OSS Distributions int error = 0;
1641*aca3beaaSApple OSS Distributions u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1642*aca3beaaSApple OSS Distributions uuid_t client_id;
1643*aca3beaaSApple OSS Distributions uuid_t netagent_uuid;
1644*aca3beaaSApple OSS Distributions u_int8_t *assigned_results = NULL;
1645*aca3beaaSApple OSS Distributions
1646*aca3beaaSApple OSS Distributions if (session == NULL) {
1647*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1648*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1649*aca3beaaSApple OSS Distributions goto fail;
1650*aca3beaaSApple OSS Distributions }
1651*aca3beaaSApple OSS Distributions
1652*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1653*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1654*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1655*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1656*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1657*aca3beaaSApple OSS Distributions goto fail;
1658*aca3beaaSApple OSS Distributions }
1659*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1660*aca3beaaSApple OSS Distributions uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1661*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1662*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1663*aca3beaaSApple OSS Distributions
1664*aca3beaaSApple OSS Distributions if (payload_length < sizeof(uuid_t)) {
1665*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1666*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1667*aca3beaaSApple OSS Distributions goto fail;
1668*aca3beaaSApple OSS Distributions }
1669*aca3beaaSApple OSS Distributions
1670*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1671*aca3beaaSApple OSS Distributions if (error) {
1672*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1673*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1674*aca3beaaSApple OSS Distributions goto fail;
1675*aca3beaaSApple OSS Distributions }
1676*aca3beaaSApple OSS Distributions
1677*aca3beaaSApple OSS Distributions size_t assigned_results_length = (payload_length - sizeof(client_id));
1678*aca3beaaSApple OSS Distributions if (assigned_results_length > 0) {
1679*aca3beaaSApple OSS Distributions assigned_results = kalloc_data( assigned_results_length, Z_WAITOK);
1680*aca3beaaSApple OSS Distributions if (assigned_results == NULL) {
1681*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1682*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1683*aca3beaaSApple OSS Distributions goto fail;
1684*aca3beaaSApple OSS Distributions }
1685*aca3beaaSApple OSS Distributions
1686*aca3beaaSApple OSS Distributions error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1687*aca3beaaSApple OSS Distributions if (error) {
1688*aca3beaaSApple OSS Distributions kfree_data(assigned_results, assigned_results_length);
1689*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1690*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1691*aca3beaaSApple OSS Distributions goto fail;
1692*aca3beaaSApple OSS Distributions }
1693*aca3beaaSApple OSS Distributions }
1694*aca3beaaSApple OSS Distributions
1695*aca3beaaSApple OSS Distributions // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1696*aca3beaaSApple OSS Distributions error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1697*aca3beaaSApple OSS Distributions if (error) {
1698*aca3beaaSApple OSS Distributions kfree_data(assigned_results, assigned_results_length);
1699*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1700*aca3beaaSApple OSS Distributions response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1701*aca3beaaSApple OSS Distributions goto fail;
1702*aca3beaaSApple OSS Distributions }
1703*aca3beaaSApple OSS Distributions
1704*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1705*aca3beaaSApple OSS Distributions netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1706*aca3beaaSApple OSS Distributions return;
1707*aca3beaaSApple OSS Distributions fail:
1708*aca3beaaSApple OSS Distributions netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1709*aca3beaaSApple OSS Distributions }
1710*aca3beaaSApple OSS Distributions
1711*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_assign_group_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1712*aca3beaaSApple OSS Distributions netagent_handle_assign_group_setopt(struct netagent_session *session, u_int8_t *payload,
1713*aca3beaaSApple OSS Distributions size_t payload_length)
1714*aca3beaaSApple OSS Distributions {
1715*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1716*aca3beaaSApple OSS Distributions struct netagent_assign_nexus_message *assign_message = (struct netagent_assign_nexus_message *)(void *)payload;
1717*aca3beaaSApple OSS Distributions uuid_t client_id;
1718*aca3beaaSApple OSS Distributions uuid_t netagent_uuid;
1719*aca3beaaSApple OSS Distributions u_int8_t *assigned_group_members = NULL;
1720*aca3beaaSApple OSS Distributions
1721*aca3beaaSApple OSS Distributions if (session == NULL) {
1722*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1723*aca3beaaSApple OSS Distributions response_error = ENOENT;
1724*aca3beaaSApple OSS Distributions goto done;
1725*aca3beaaSApple OSS Distributions }
1726*aca3beaaSApple OSS Distributions
1727*aca3beaaSApple OSS Distributions if (payload == NULL) {
1728*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1729*aca3beaaSApple OSS Distributions response_error = EINVAL;
1730*aca3beaaSApple OSS Distributions goto done;
1731*aca3beaaSApple OSS Distributions }
1732*aca3beaaSApple OSS Distributions
1733*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1734*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1735*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1736*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1737*aca3beaaSApple OSS Distributions response_error = ENOENT;
1738*aca3beaaSApple OSS Distributions goto done;
1739*aca3beaaSApple OSS Distributions }
1740*aca3beaaSApple OSS Distributions
1741*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1742*aca3beaaSApple OSS Distributions uuid_copy(netagent_uuid, session->wrapper->netagent->netagent_uuid);
1743*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1744*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1745*aca3beaaSApple OSS Distributions
1746*aca3beaaSApple OSS Distributions if (payload_length < sizeof(uuid_t)) {
1747*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Group assign message is too short");
1748*aca3beaaSApple OSS Distributions response_error = EINVAL;
1749*aca3beaaSApple OSS Distributions goto done;
1750*aca3beaaSApple OSS Distributions }
1751*aca3beaaSApple OSS Distributions
1752*aca3beaaSApple OSS Distributions memcpy(client_id, assign_message->assign_client_id, sizeof(client_id));
1753*aca3beaaSApple OSS Distributions size_t assigned_group_members_length = (payload_length - sizeof(client_id));
1754*aca3beaaSApple OSS Distributions
1755*aca3beaaSApple OSS Distributions if (assigned_group_members_length > 0) {
1756*aca3beaaSApple OSS Distributions assigned_group_members = (u_int8_t *)kalloc_data(assigned_group_members_length, Z_WAITOK);
1757*aca3beaaSApple OSS Distributions if (assigned_group_members == NULL) {
1758*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Failed to allocate group assign message (%lu bytes)", assigned_group_members_length);
1759*aca3beaaSApple OSS Distributions response_error = ENOMEM;
1760*aca3beaaSApple OSS Distributions goto done;
1761*aca3beaaSApple OSS Distributions }
1762*aca3beaaSApple OSS Distributions memcpy(assigned_group_members, assign_message->assign_necp_results, assigned_group_members_length);
1763*aca3beaaSApple OSS Distributions }
1764*aca3beaaSApple OSS Distributions
1765*aca3beaaSApple OSS Distributions // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1766*aca3beaaSApple OSS Distributions response_error = necp_assign_client_group_members(netagent_uuid, client_id, assigned_group_members, assigned_group_members_length);
1767*aca3beaaSApple OSS Distributions if (response_error != 0) {
1768*aca3beaaSApple OSS Distributions // necp_assign_client_group_members returns POSIX errors
1769*aca3beaaSApple OSS Distributions if (assigned_group_members != NULL) {
1770*aca3beaaSApple OSS Distributions kfree_data(assigned_group_members, assigned_group_members_length);
1771*aca3beaaSApple OSS Distributions }
1772*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Client group assignment failed: %d", response_error);
1773*aca3beaaSApple OSS Distributions goto done;
1774*aca3beaaSApple OSS Distributions }
1775*aca3beaaSApple OSS Distributions
1776*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Agent assigned group members to client");
1777*aca3beaaSApple OSS Distributions done:
1778*aca3beaaSApple OSS Distributions return response_error;
1779*aca3beaaSApple OSS Distributions }
1780*aca3beaaSApple OSS Distributions
1781*aca3beaaSApple OSS Distributions
1782*aca3beaaSApple OSS Distributions errno_t
netagent_handle_use_count_setopt(struct netagent_session * session,u_int8_t * payload,size_t payload_length)1783*aca3beaaSApple OSS Distributions netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1784*aca3beaaSApple OSS Distributions {
1785*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1786*aca3beaaSApple OSS Distributions uint64_t use_count = 0;
1787*aca3beaaSApple OSS Distributions
1788*aca3beaaSApple OSS Distributions if (session == NULL) {
1789*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1790*aca3beaaSApple OSS Distributions response_error = ENOENT;
1791*aca3beaaSApple OSS Distributions goto done;
1792*aca3beaaSApple OSS Distributions }
1793*aca3beaaSApple OSS Distributions
1794*aca3beaaSApple OSS Distributions if (payload == NULL) {
1795*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1796*aca3beaaSApple OSS Distributions response_error = EINVAL;
1797*aca3beaaSApple OSS Distributions goto done;
1798*aca3beaaSApple OSS Distributions }
1799*aca3beaaSApple OSS Distributions
1800*aca3beaaSApple OSS Distributions if (payload_length != sizeof(use_count)) {
1801*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Payload length is invalid (%lu)", payload_length);
1802*aca3beaaSApple OSS Distributions response_error = EINVAL;
1803*aca3beaaSApple OSS Distributions goto done;
1804*aca3beaaSApple OSS Distributions }
1805*aca3beaaSApple OSS Distributions
1806*aca3beaaSApple OSS Distributions memcpy(&use_count, payload, sizeof(use_count));
1807*aca3beaaSApple OSS Distributions
1808*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1809*aca3beaaSApple OSS Distributions
1810*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1811*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1812*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1813*aca3beaaSApple OSS Distributions response_error = ENOENT;
1814*aca3beaaSApple OSS Distributions goto done;
1815*aca3beaaSApple OSS Distributions }
1816*aca3beaaSApple OSS Distributions
1817*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
1818*aca3beaaSApple OSS Distributions session->wrapper->use_count = use_count;
1819*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1820*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1821*aca3beaaSApple OSS Distributions
1822*aca3beaaSApple OSS Distributions done:
1823*aca3beaaSApple OSS Distributions return response_error;
1824*aca3beaaSApple OSS Distributions }
1825*aca3beaaSApple OSS Distributions
1826*aca3beaaSApple OSS Distributions errno_t
netagent_handle_use_count_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)1827*aca3beaaSApple OSS Distributions netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1828*aca3beaaSApple OSS Distributions {
1829*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1830*aca3beaaSApple OSS Distributions uint64_t use_count = 0;
1831*aca3beaaSApple OSS Distributions
1832*aca3beaaSApple OSS Distributions if (session == NULL) {
1833*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1834*aca3beaaSApple OSS Distributions response_error = ENOENT;
1835*aca3beaaSApple OSS Distributions goto done;
1836*aca3beaaSApple OSS Distributions }
1837*aca3beaaSApple OSS Distributions
1838*aca3beaaSApple OSS Distributions if (buffer == NULL) {
1839*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1840*aca3beaaSApple OSS Distributions response_error = EINVAL;
1841*aca3beaaSApple OSS Distributions goto done;
1842*aca3beaaSApple OSS Distributions }
1843*aca3beaaSApple OSS Distributions
1844*aca3beaaSApple OSS Distributions if (*buffer_length != sizeof(use_count)) {
1845*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1846*aca3beaaSApple OSS Distributions response_error = EINVAL;
1847*aca3beaaSApple OSS Distributions goto done;
1848*aca3beaaSApple OSS Distributions }
1849*aca3beaaSApple OSS Distributions
1850*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1851*aca3beaaSApple OSS Distributions
1852*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1853*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1854*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1855*aca3beaaSApple OSS Distributions response_error = ENOENT;
1856*aca3beaaSApple OSS Distributions goto done;
1857*aca3beaaSApple OSS Distributions }
1858*aca3beaaSApple OSS Distributions
1859*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1860*aca3beaaSApple OSS Distributions use_count = session->wrapper->use_count;
1861*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1862*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1863*aca3beaaSApple OSS Distributions
1864*aca3beaaSApple OSS Distributions memcpy(buffer, &use_count, sizeof(use_count));
1865*aca3beaaSApple OSS Distributions *buffer_length = sizeof(use_count);
1866*aca3beaaSApple OSS Distributions
1867*aca3beaaSApple OSS Distributions done:
1868*aca3beaaSApple OSS Distributions return response_error;
1869*aca3beaaSApple OSS Distributions }
1870*aca3beaaSApple OSS Distributions
1871*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_add_token_setopt(struct netagent_session * session,u_int8_t * token,size_t token_length)1872*aca3beaaSApple OSS Distributions netagent_handle_add_token_setopt(struct netagent_session *session, u_int8_t *token, size_t token_length)
1873*aca3beaaSApple OSS Distributions {
1874*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1875*aca3beaaSApple OSS Distributions
1876*aca3beaaSApple OSS Distributions if (session == NULL) {
1877*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1878*aca3beaaSApple OSS Distributions response_error = ENOENT;
1879*aca3beaaSApple OSS Distributions goto done;
1880*aca3beaaSApple OSS Distributions }
1881*aca3beaaSApple OSS Distributions
1882*aca3beaaSApple OSS Distributions if (token == NULL) {
1883*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No token received");
1884*aca3beaaSApple OSS Distributions response_error = EINVAL;
1885*aca3beaaSApple OSS Distributions goto done;
1886*aca3beaaSApple OSS Distributions }
1887*aca3beaaSApple OSS Distributions
1888*aca3beaaSApple OSS Distributions if (token_length > NETAGENT_MAX_DATA_SIZE) {
1889*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Token length is invalid (%lu)", token_length);
1890*aca3beaaSApple OSS Distributions response_error = EINVAL;
1891*aca3beaaSApple OSS Distributions goto done;
1892*aca3beaaSApple OSS Distributions }
1893*aca3beaaSApple OSS Distributions
1894*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1895*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1896*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1897*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1898*aca3beaaSApple OSS Distributions response_error = ENOENT;
1899*aca3beaaSApple OSS Distributions goto done;
1900*aca3beaaSApple OSS Distributions }
1901*aca3beaaSApple OSS Distributions
1902*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
1903*aca3beaaSApple OSS Distributions if (session->wrapper->token_count >= NETAGENT_MAX_TOKEN_COUNT) {
1904*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1905*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1906*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session cannot add more tokens");
1907*aca3beaaSApple OSS Distributions response_error = EINVAL;
1908*aca3beaaSApple OSS Distributions goto done;
1909*aca3beaaSApple OSS Distributions }
1910*aca3beaaSApple OSS Distributions
1911*aca3beaaSApple OSS Distributions struct netagent_token *token_struct = NULL;
1912*aca3beaaSApple OSS Distributions
1913*aca3beaaSApple OSS Distributions token_struct = kalloc_type(struct netagent_token, Z_WAITOK | Z_ZERO | Z_NOFAIL);
1914*aca3beaaSApple OSS Distributions token_struct->token_bytes = kalloc_data(token_length, Z_WAITOK | Z_NOFAIL);
1915*aca3beaaSApple OSS Distributions token_struct->token_length = (u_int32_t)token_length;
1916*aca3beaaSApple OSS Distributions memcpy(token_struct->token_bytes, token, token_length);
1917*aca3beaaSApple OSS Distributions
1918*aca3beaaSApple OSS Distributions TAILQ_INSERT_TAIL(&session->wrapper->token_list, token_struct, token_chain);
1919*aca3beaaSApple OSS Distributions
1920*aca3beaaSApple OSS Distributions session->wrapper->token_count++;
1921*aca3beaaSApple OSS Distributions
1922*aca3beaaSApple OSS Distributions // Reset deadline time, now that there are more than 0 tokens
1923*aca3beaaSApple OSS Distributions session->wrapper->need_tokens_event_deadline = 0;
1924*aca3beaaSApple OSS Distributions
1925*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1926*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1927*aca3beaaSApple OSS Distributions done:
1928*aca3beaaSApple OSS Distributions return response_error;
1929*aca3beaaSApple OSS Distributions }
1930*aca3beaaSApple OSS Distributions
1931*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_flush_tokens_setopt(struct netagent_session * session,__unused u_int8_t * buffer,__unused size_t buffer_length)1932*aca3beaaSApple OSS Distributions netagent_handle_flush_tokens_setopt(struct netagent_session *session, __unused u_int8_t *buffer, __unused size_t buffer_length)
1933*aca3beaaSApple OSS Distributions {
1934*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1935*aca3beaaSApple OSS Distributions
1936*aca3beaaSApple OSS Distributions if (session == NULL) {
1937*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1938*aca3beaaSApple OSS Distributions response_error = ENOENT;
1939*aca3beaaSApple OSS Distributions goto done;
1940*aca3beaaSApple OSS Distributions }
1941*aca3beaaSApple OSS Distributions
1942*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1943*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1944*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1945*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1946*aca3beaaSApple OSS Distributions response_error = ENOENT;
1947*aca3beaaSApple OSS Distributions goto done;
1948*aca3beaaSApple OSS Distributions }
1949*aca3beaaSApple OSS Distributions
1950*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
1951*aca3beaaSApple OSS Distributions struct netagent_token *search_token = NULL;
1952*aca3beaaSApple OSS Distributions struct netagent_token *temp_token = NULL;
1953*aca3beaaSApple OSS Distributions TAILQ_FOREACH_SAFE(search_token, &session->wrapper->token_list, token_chain, temp_token) {
1954*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&session->wrapper->token_list, search_token, token_chain);
1955*aca3beaaSApple OSS Distributions netagent_token_free(search_token);
1956*aca3beaaSApple OSS Distributions }
1957*aca3beaaSApple OSS Distributions session->wrapper->token_count = 0;
1958*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1959*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1960*aca3beaaSApple OSS Distributions done:
1961*aca3beaaSApple OSS Distributions return response_error;
1962*aca3beaaSApple OSS Distributions }
1963*aca3beaaSApple OSS Distributions
1964*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_token_count_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)1965*aca3beaaSApple OSS Distributions netagent_handle_token_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1966*aca3beaaSApple OSS Distributions {
1967*aca3beaaSApple OSS Distributions errno_t response_error = 0;
1968*aca3beaaSApple OSS Distributions uint32_t token_count = 0;
1969*aca3beaaSApple OSS Distributions
1970*aca3beaaSApple OSS Distributions if (session == NULL) {
1971*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
1972*aca3beaaSApple OSS Distributions response_error = ENOENT;
1973*aca3beaaSApple OSS Distributions goto done;
1974*aca3beaaSApple OSS Distributions }
1975*aca3beaaSApple OSS Distributions
1976*aca3beaaSApple OSS Distributions if (buffer == NULL) {
1977*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
1978*aca3beaaSApple OSS Distributions response_error = EINVAL;
1979*aca3beaaSApple OSS Distributions goto done;
1980*aca3beaaSApple OSS Distributions }
1981*aca3beaaSApple OSS Distributions
1982*aca3beaaSApple OSS Distributions if (*buffer_length != sizeof(token_count)) {
1983*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1984*aca3beaaSApple OSS Distributions response_error = EINVAL;
1985*aca3beaaSApple OSS Distributions goto done;
1986*aca3beaaSApple OSS Distributions }
1987*aca3beaaSApple OSS Distributions
1988*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
1989*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
1990*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
1991*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1992*aca3beaaSApple OSS Distributions response_error = ENOENT;
1993*aca3beaaSApple OSS Distributions goto done;
1994*aca3beaaSApple OSS Distributions }
1995*aca3beaaSApple OSS Distributions
1996*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
1997*aca3beaaSApple OSS Distributions token_count = session->wrapper->token_count;
1998*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
1999*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2000*aca3beaaSApple OSS Distributions
2001*aca3beaaSApple OSS Distributions memcpy(buffer, &token_count, sizeof(token_count));
2002*aca3beaaSApple OSS Distributions *buffer_length = sizeof(token_count);
2003*aca3beaaSApple OSS Distributions
2004*aca3beaaSApple OSS Distributions done:
2005*aca3beaaSApple OSS Distributions return response_error;
2006*aca3beaaSApple OSS Distributions }
2007*aca3beaaSApple OSS Distributions
2008*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_token_low_water_setopt(struct netagent_session * session,u_int8_t * buffer,size_t buffer_length)2009*aca3beaaSApple OSS Distributions netagent_handle_token_low_water_setopt(struct netagent_session *session, u_int8_t *buffer, size_t buffer_length)
2010*aca3beaaSApple OSS Distributions {
2011*aca3beaaSApple OSS Distributions errno_t response_error = 0;
2012*aca3beaaSApple OSS Distributions uint32_t token_low_water = 0;
2013*aca3beaaSApple OSS Distributions
2014*aca3beaaSApple OSS Distributions if (session == NULL) {
2015*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
2016*aca3beaaSApple OSS Distributions response_error = ENOENT;
2017*aca3beaaSApple OSS Distributions goto done;
2018*aca3beaaSApple OSS Distributions }
2019*aca3beaaSApple OSS Distributions
2020*aca3beaaSApple OSS Distributions if (buffer == NULL) {
2021*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
2022*aca3beaaSApple OSS Distributions response_error = EINVAL;
2023*aca3beaaSApple OSS Distributions goto done;
2024*aca3beaaSApple OSS Distributions }
2025*aca3beaaSApple OSS Distributions
2026*aca3beaaSApple OSS Distributions if (buffer_length != sizeof(token_low_water)) {
2027*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", buffer_length);
2028*aca3beaaSApple OSS Distributions response_error = EINVAL;
2029*aca3beaaSApple OSS Distributions goto done;
2030*aca3beaaSApple OSS Distributions }
2031*aca3beaaSApple OSS Distributions
2032*aca3beaaSApple OSS Distributions memcpy(&token_low_water, buffer, sizeof(token_low_water));
2033*aca3beaaSApple OSS Distributions
2034*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
2035*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
2036*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2037*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
2038*aca3beaaSApple OSS Distributions response_error = ENOENT;
2039*aca3beaaSApple OSS Distributions goto done;
2040*aca3beaaSApple OSS Distributions }
2041*aca3beaaSApple OSS Distributions
2042*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
2043*aca3beaaSApple OSS Distributions session->wrapper->token_low_water = token_low_water;
2044*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
2045*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2046*aca3beaaSApple OSS Distributions
2047*aca3beaaSApple OSS Distributions done:
2048*aca3beaaSApple OSS Distributions return response_error;
2049*aca3beaaSApple OSS Distributions }
2050*aca3beaaSApple OSS Distributions
2051*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_token_low_water_getopt(struct netagent_session * session,u_int8_t * buffer,size_t * buffer_length)2052*aca3beaaSApple OSS Distributions netagent_handle_token_low_water_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
2053*aca3beaaSApple OSS Distributions {
2054*aca3beaaSApple OSS Distributions errno_t response_error = 0;
2055*aca3beaaSApple OSS Distributions uint32_t token_low_water = 0;
2056*aca3beaaSApple OSS Distributions
2057*aca3beaaSApple OSS Distributions if (session == NULL) {
2058*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
2059*aca3beaaSApple OSS Distributions response_error = ENOENT;
2060*aca3beaaSApple OSS Distributions goto done;
2061*aca3beaaSApple OSS Distributions }
2062*aca3beaaSApple OSS Distributions
2063*aca3beaaSApple OSS Distributions if (buffer == NULL) {
2064*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "No payload received");
2065*aca3beaaSApple OSS Distributions response_error = EINVAL;
2066*aca3beaaSApple OSS Distributions goto done;
2067*aca3beaaSApple OSS Distributions }
2068*aca3beaaSApple OSS Distributions
2069*aca3beaaSApple OSS Distributions if (*buffer_length != sizeof(token_low_water)) {
2070*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
2071*aca3beaaSApple OSS Distributions response_error = EINVAL;
2072*aca3beaaSApple OSS Distributions goto done;
2073*aca3beaaSApple OSS Distributions }
2074*aca3beaaSApple OSS Distributions
2075*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
2076*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
2077*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2078*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
2079*aca3beaaSApple OSS Distributions response_error = ENOENT;
2080*aca3beaaSApple OSS Distributions goto done;
2081*aca3beaaSApple OSS Distributions }
2082*aca3beaaSApple OSS Distributions
2083*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(session->wrapper);
2084*aca3beaaSApple OSS Distributions token_low_water = session->wrapper->token_low_water;
2085*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
2086*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2087*aca3beaaSApple OSS Distributions
2088*aca3beaaSApple OSS Distributions memcpy(buffer, &token_low_water, sizeof(token_low_water));
2089*aca3beaaSApple OSS Distributions *buffer_length = sizeof(token_low_water);
2090*aca3beaaSApple OSS Distributions
2091*aca3beaaSApple OSS Distributions done:
2092*aca3beaaSApple OSS Distributions return response_error;
2093*aca3beaaSApple OSS Distributions }
2094*aca3beaaSApple OSS Distributions
2095*aca3beaaSApple OSS Distributions static errno_t
netagent_handle_reset_client_error_setopt(struct netagent_session * session,__unused u_int8_t * payload,__unused size_t payload_length)2096*aca3beaaSApple OSS Distributions netagent_handle_reset_client_error_setopt(struct netagent_session *session, __unused u_int8_t *payload, __unused size_t payload_length)
2097*aca3beaaSApple OSS Distributions {
2098*aca3beaaSApple OSS Distributions errno_t response_error = 0;
2099*aca3beaaSApple OSS Distributions
2100*aca3beaaSApple OSS Distributions if (session == NULL) {
2101*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to find session");
2102*aca3beaaSApple OSS Distributions response_error = ENOENT;
2103*aca3beaaSApple OSS Distributions goto done;
2104*aca3beaaSApple OSS Distributions }
2105*aca3beaaSApple OSS Distributions
2106*aca3beaaSApple OSS Distributions NETAGENT_SESSION_LOCK(session);
2107*aca3beaaSApple OSS Distributions if (session->wrapper == NULL) {
2108*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2109*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
2110*aca3beaaSApple OSS Distributions response_error = ENOENT;
2111*aca3beaaSApple OSS Distributions goto done;
2112*aca3beaaSApple OSS Distributions }
2113*aca3beaaSApple OSS Distributions
2114*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(session->wrapper);
2115*aca3beaaSApple OSS Distributions struct netagent_token *search_token = NULL;
2116*aca3beaaSApple OSS Distributions struct netagent_token *temp_token = NULL;
2117*aca3beaaSApple OSS Distributions TAILQ_FOREACH_SAFE(search_token, &session->wrapper->token_list, token_chain, temp_token) {
2118*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&session->wrapper->token_list, search_token, token_chain);
2119*aca3beaaSApple OSS Distributions netagent_token_free(search_token);
2120*aca3beaaSApple OSS Distributions }
2121*aca3beaaSApple OSS Distributions session->wrapper->last_client_error = 0;
2122*aca3beaaSApple OSS Distributions session->wrapper->client_error_count = 0;
2123*aca3beaaSApple OSS Distributions
2124*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(session->wrapper);
2125*aca3beaaSApple OSS Distributions NETAGENT_SESSION_UNLOCK(session);
2126*aca3beaaSApple OSS Distributions done:
2127*aca3beaaSApple OSS Distributions return response_error;
2128*aca3beaaSApple OSS Distributions }
2129*aca3beaaSApple OSS Distributions
2130*aca3beaaSApple OSS Distributions static struct netagent_wrapper *
netagent_find_agent_with_uuid_and_lock(uuid_t uuid,bool exclusively,bool ignore_lock)2131*aca3beaaSApple OSS Distributions netagent_find_agent_with_uuid_and_lock(uuid_t uuid, bool exclusively, bool ignore_lock)
2132*aca3beaaSApple OSS Distributions {
2133*aca3beaaSApple OSS Distributions NETAGENT_LIST_ASSERT_LOCKED();
2134*aca3beaaSApple OSS Distributions
2135*aca3beaaSApple OSS Distributions struct netagent_wrapper *search_netagent = NULL;
2136*aca3beaaSApple OSS Distributions
2137*aca3beaaSApple OSS Distributions LIST_FOREACH(search_netagent, &shared_netagent_list, list_chain) {
2138*aca3beaaSApple OSS Distributions if (uuid_compare(search_netagent->netagent->netagent_uuid, uuid) == 0) {
2139*aca3beaaSApple OSS Distributions if (!ignore_lock) {
2140*aca3beaaSApple OSS Distributions if (exclusively) {
2141*aca3beaaSApple OSS Distributions NETAGENT_LOCK_EXCLUSIVE(search_netagent);
2142*aca3beaaSApple OSS Distributions } else {
2143*aca3beaaSApple OSS Distributions NETAGENT_LOCK_SHARED(search_netagent);
2144*aca3beaaSApple OSS Distributions }
2145*aca3beaaSApple OSS Distributions }
2146*aca3beaaSApple OSS Distributions return search_netagent;
2147*aca3beaaSApple OSS Distributions }
2148*aca3beaaSApple OSS Distributions }
2149*aca3beaaSApple OSS Distributions
2150*aca3beaaSApple OSS Distributions return NULL;
2151*aca3beaaSApple OSS Distributions }
2152*aca3beaaSApple OSS Distributions
2153*aca3beaaSApple OSS Distributions void
netagent_post_updated_interfaces(uuid_t uuid)2154*aca3beaaSApple OSS Distributions netagent_post_updated_interfaces(uuid_t uuid)
2155*aca3beaaSApple OSS Distributions {
2156*aca3beaaSApple OSS Distributions if (!uuid_is_null(uuid)) {
2157*aca3beaaSApple OSS Distributions netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, true, false);
2158*aca3beaaSApple OSS Distributions } else {
2159*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
2160*aca3beaaSApple OSS Distributions }
2161*aca3beaaSApple OSS Distributions }
2162*aca3beaaSApple OSS Distributions
2163*aca3beaaSApple OSS Distributions static u_int32_t
netagent_dump_get_data_size_locked()2164*aca3beaaSApple OSS Distributions netagent_dump_get_data_size_locked()
2165*aca3beaaSApple OSS Distributions {
2166*aca3beaaSApple OSS Distributions NETAGENT_LIST_ASSERT_LOCKED();
2167*aca3beaaSApple OSS Distributions
2168*aca3beaaSApple OSS Distributions struct netagent_wrapper *search_netagent = NULL;
2169*aca3beaaSApple OSS Distributions u_int32_t total_netagent_data_size = 0;
2170*aca3beaaSApple OSS Distributions // Traverse the shared list to know how much data the client needs to allocate to get the list of agent UUIDs
2171*aca3beaaSApple OSS Distributions LIST_FOREACH(search_netagent, &shared_netagent_list, list_chain) {
2172*aca3beaaSApple OSS Distributions total_netagent_data_size += sizeof(search_netagent->netagent->netagent_uuid);
2173*aca3beaaSApple OSS Distributions }
2174*aca3beaaSApple OSS Distributions return total_netagent_data_size;
2175*aca3beaaSApple OSS Distributions }
2176*aca3beaaSApple OSS Distributions
2177*aca3beaaSApple OSS Distributions static void
netagent_dump_copy_data_locked(u_int8_t * buffer,u_int32_t buffer_length)2178*aca3beaaSApple OSS Distributions netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
2179*aca3beaaSApple OSS Distributions {
2180*aca3beaaSApple OSS Distributions NETAGENT_LIST_ASSERT_LOCKED();
2181*aca3beaaSApple OSS Distributions
2182*aca3beaaSApple OSS Distributions size_t response_size = 0;
2183*aca3beaaSApple OSS Distributions u_int8_t *cursor = NULL;
2184*aca3beaaSApple OSS Distributions struct netagent_wrapper *search_netagent = NULL;
2185*aca3beaaSApple OSS Distributions
2186*aca3beaaSApple OSS Distributions response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
2187*aca3beaaSApple OSS Distributions cursor = buffer;
2188*aca3beaaSApple OSS Distributions LIST_FOREACH(search_netagent, &shared_netagent_list, list_chain) {
2189*aca3beaaSApple OSS Distributions memcpy(cursor, search_netagent->netagent->netagent_uuid, sizeof(search_netagent->netagent->netagent_uuid));
2190*aca3beaaSApple OSS Distributions cursor += sizeof(search_netagent->netagent->netagent_uuid);
2191*aca3beaaSApple OSS Distributions }
2192*aca3beaaSApple OSS Distributions }
2193*aca3beaaSApple OSS Distributions
2194*aca3beaaSApple OSS Distributions int
netagent_ioctl(u_long cmd,caddr_t data)2195*aca3beaaSApple OSS Distributions netagent_ioctl(u_long cmd, caddr_t data)
2196*aca3beaaSApple OSS Distributions {
2197*aca3beaaSApple OSS Distributions int error = 0;
2198*aca3beaaSApple OSS Distributions
2199*aca3beaaSApple OSS Distributions switch (cmd) {
2200*aca3beaaSApple OSS Distributions case SIOCGIFAGENTLIST32:
2201*aca3beaaSApple OSS Distributions case SIOCGIFAGENTLIST64: {
2202*aca3beaaSApple OSS Distributions /* Check entitlement if the client requests agent dump */
2203*aca3beaaSApple OSS Distributions errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
2204*aca3beaaSApple OSS Distributions if (cred_result != 0) {
2205*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
2206*aca3beaaSApple OSS Distributions return EINVAL;
2207*aca3beaaSApple OSS Distributions }
2208*aca3beaaSApple OSS Distributions break;
2209*aca3beaaSApple OSS Distributions }
2210*aca3beaaSApple OSS Distributions default:
2211*aca3beaaSApple OSS Distributions break;
2212*aca3beaaSApple OSS Distributions }
2213*aca3beaaSApple OSS Distributions
2214*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2215*aca3beaaSApple OSS Distributions switch (cmd) {
2216*aca3beaaSApple OSS Distributions case SIOCGIFAGENTDATA32: {
2217*aca3beaaSApple OSS Distributions struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
2218*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(ifsir32->netagent_uuid, false, false);
2219*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2220*aca3beaaSApple OSS Distributions error = ENOENT;
2221*aca3beaaSApple OSS Distributions break;
2222*aca3beaaSApple OSS Distributions }
2223*aca3beaaSApple OSS Distributions uuid_copy(ifsir32->netagent_uuid, wrapper->netagent->netagent_uuid);
2224*aca3beaaSApple OSS Distributions memcpy(ifsir32->netagent_domain, wrapper->netagent->netagent_domain, sizeof(ifsir32->netagent_domain));
2225*aca3beaaSApple OSS Distributions memcpy(ifsir32->netagent_type, wrapper->netagent->netagent_type, sizeof(ifsir32->netagent_type));
2226*aca3beaaSApple OSS Distributions memcpy(ifsir32->netagent_desc, wrapper->netagent->netagent_desc, sizeof(ifsir32->netagent_desc));
2227*aca3beaaSApple OSS Distributions ifsir32->netagent_flags = wrapper->netagent->netagent_flags;
2228*aca3beaaSApple OSS Distributions if (ifsir32->netagent_data_size == 0) {
2229*aca3beaaSApple OSS Distributions // First pass, client wants data size
2230*aca3beaaSApple OSS Distributions ifsir32->netagent_data_size = wrapper->netagent->netagent_data_size;
2231*aca3beaaSApple OSS Distributions } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
2232*aca3beaaSApple OSS Distributions ifsir32->netagent_data_size == wrapper->netagent->netagent_data_size) {
2233*aca3beaaSApple OSS Distributions // Second pass, client wants data buffer filled out
2234*aca3beaaSApple OSS Distributions error = copyout(wrapper->netagent->netagent_data, ifsir32->netagent_data, wrapper->netagent->netagent_data_size);
2235*aca3beaaSApple OSS Distributions } else {
2236*aca3beaaSApple OSS Distributions error = EINVAL;
2237*aca3beaaSApple OSS Distributions }
2238*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2239*aca3beaaSApple OSS Distributions break;
2240*aca3beaaSApple OSS Distributions }
2241*aca3beaaSApple OSS Distributions case SIOCGIFAGENTDATA64: {
2242*aca3beaaSApple OSS Distributions struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
2243*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(ifsir64->netagent_uuid, false, false);
2244*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2245*aca3beaaSApple OSS Distributions error = ENOENT;
2246*aca3beaaSApple OSS Distributions break;
2247*aca3beaaSApple OSS Distributions }
2248*aca3beaaSApple OSS Distributions uuid_copy(ifsir64->netagent_uuid, wrapper->netagent->netagent_uuid);
2249*aca3beaaSApple OSS Distributions memcpy(ifsir64->netagent_domain, wrapper->netagent->netagent_domain, sizeof(ifsir64->netagent_domain));
2250*aca3beaaSApple OSS Distributions memcpy(ifsir64->netagent_type, wrapper->netagent->netagent_type, sizeof(ifsir64->netagent_type));
2251*aca3beaaSApple OSS Distributions memcpy(ifsir64->netagent_desc, wrapper->netagent->netagent_desc, sizeof(ifsir64->netagent_desc));
2252*aca3beaaSApple OSS Distributions ifsir64->netagent_flags = wrapper->netagent->netagent_flags;
2253*aca3beaaSApple OSS Distributions if (ifsir64->netagent_data_size == 0) {
2254*aca3beaaSApple OSS Distributions // First pass, client wants data size
2255*aca3beaaSApple OSS Distributions ifsir64->netagent_data_size = wrapper->netagent->netagent_data_size;
2256*aca3beaaSApple OSS Distributions } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
2257*aca3beaaSApple OSS Distributions ifsir64->netagent_data_size == wrapper->netagent->netagent_data_size) {
2258*aca3beaaSApple OSS Distributions // Second pass, client wants data buffer filled out
2259*aca3beaaSApple OSS Distributions error = copyout(wrapper->netagent->netagent_data, ifsir64->netagent_data, wrapper->netagent->netagent_data_size);
2260*aca3beaaSApple OSS Distributions } else {
2261*aca3beaaSApple OSS Distributions error = EINVAL;
2262*aca3beaaSApple OSS Distributions }
2263*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2264*aca3beaaSApple OSS Distributions break;
2265*aca3beaaSApple OSS Distributions }
2266*aca3beaaSApple OSS Distributions case SIOCGIFAGENTLIST32: {
2267*aca3beaaSApple OSS Distributions struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
2268*aca3beaaSApple OSS Distributions if (ifsir32->data_size == 0) {
2269*aca3beaaSApple OSS Distributions // First pass, client wants data size
2270*aca3beaaSApple OSS Distributions ifsir32->data_size = netagent_dump_get_data_size_locked();
2271*aca3beaaSApple OSS Distributions } else if (ifsir32->data != USER_ADDR_NULL &&
2272*aca3beaaSApple OSS Distributions ifsir32->data_size > 0 &&
2273*aca3beaaSApple OSS Distributions ifsir32->data_size == netagent_dump_get_data_size_locked()) {
2274*aca3beaaSApple OSS Distributions // Second pass, client wants data buffer filled out
2275*aca3beaaSApple OSS Distributions u_int8_t *response = NULL;
2276*aca3beaaSApple OSS Distributions response = (u_int8_t *)kalloc_data(ifsir32->data_size, Z_NOWAIT | Z_ZERO);
2277*aca3beaaSApple OSS Distributions if (response == NULL) {
2278*aca3beaaSApple OSS Distributions error = ENOMEM;
2279*aca3beaaSApple OSS Distributions break;
2280*aca3beaaSApple OSS Distributions }
2281*aca3beaaSApple OSS Distributions
2282*aca3beaaSApple OSS Distributions netagent_dump_copy_data_locked(response, ifsir32->data_size);
2283*aca3beaaSApple OSS Distributions error = copyout(response, ifsir32->data, ifsir32->data_size);
2284*aca3beaaSApple OSS Distributions kfree_data(response, ifsir32->data_size);
2285*aca3beaaSApple OSS Distributions } else {
2286*aca3beaaSApple OSS Distributions error = EINVAL;
2287*aca3beaaSApple OSS Distributions }
2288*aca3beaaSApple OSS Distributions break;
2289*aca3beaaSApple OSS Distributions }
2290*aca3beaaSApple OSS Distributions case SIOCGIFAGENTLIST64: {
2291*aca3beaaSApple OSS Distributions struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
2292*aca3beaaSApple OSS Distributions if (ifsir64->data_size == 0) {
2293*aca3beaaSApple OSS Distributions // First pass, client wants data size
2294*aca3beaaSApple OSS Distributions ifsir64->data_size = netagent_dump_get_data_size_locked();
2295*aca3beaaSApple OSS Distributions } else if (ifsir64->data != USER_ADDR_NULL &&
2296*aca3beaaSApple OSS Distributions ifsir64->data_size > 0 &&
2297*aca3beaaSApple OSS Distributions ifsir64->data_size == netagent_dump_get_data_size_locked()) {
2298*aca3beaaSApple OSS Distributions // Second pass, client wants data buffer filled out
2299*aca3beaaSApple OSS Distributions u_int8_t *response = NULL;
2300*aca3beaaSApple OSS Distributions response = (u_int8_t *)kalloc_data(ifsir64->data_size, Z_NOWAIT | Z_ZERO);
2301*aca3beaaSApple OSS Distributions if (response == NULL) {
2302*aca3beaaSApple OSS Distributions error = ENOMEM;
2303*aca3beaaSApple OSS Distributions break;
2304*aca3beaaSApple OSS Distributions }
2305*aca3beaaSApple OSS Distributions
2306*aca3beaaSApple OSS Distributions netagent_dump_copy_data_locked(response, ifsir64->data_size);
2307*aca3beaaSApple OSS Distributions error = copyout(response, ifsir64->data, ifsir64->data_size);
2308*aca3beaaSApple OSS Distributions kfree_data(response, ifsir64->data_size);
2309*aca3beaaSApple OSS Distributions } else {
2310*aca3beaaSApple OSS Distributions error = EINVAL;
2311*aca3beaaSApple OSS Distributions }
2312*aca3beaaSApple OSS Distributions break;
2313*aca3beaaSApple OSS Distributions }
2314*aca3beaaSApple OSS Distributions default: {
2315*aca3beaaSApple OSS Distributions error = EINVAL;
2316*aca3beaaSApple OSS Distributions break;
2317*aca3beaaSApple OSS Distributions }
2318*aca3beaaSApple OSS Distributions }
2319*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2320*aca3beaaSApple OSS Distributions return error;
2321*aca3beaaSApple OSS Distributions }
2322*aca3beaaSApple OSS Distributions
2323*aca3beaaSApple OSS Distributions u_int32_t
netagent_get_flags(uuid_t uuid)2324*aca3beaaSApple OSS Distributions netagent_get_flags(uuid_t uuid)
2325*aca3beaaSApple OSS Distributions {
2326*aca3beaaSApple OSS Distributions u_int32_t flags = 0;
2327*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2328*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(uuid, false, false);
2329*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2330*aca3beaaSApple OSS Distributions flags = wrapper->netagent->netagent_flags;
2331*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2332*aca3beaaSApple OSS Distributions } else {
2333*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
2334*aca3beaaSApple OSS Distributions }
2335*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2336*aca3beaaSApple OSS Distributions
2337*aca3beaaSApple OSS Distributions return flags;
2338*aca3beaaSApple OSS Distributions }
2339*aca3beaaSApple OSS Distributions
2340*aca3beaaSApple OSS Distributions errno_t
netagent_set_flags(uuid_t uuid,u_int32_t flags)2341*aca3beaaSApple OSS Distributions netagent_set_flags(uuid_t uuid, u_int32_t flags)
2342*aca3beaaSApple OSS Distributions {
2343*aca3beaaSApple OSS Distributions errno_t error = 0;
2344*aca3beaaSApple OSS Distributions bool updated = false;
2345*aca3beaaSApple OSS Distributions
2346*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2347*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(uuid, true, false);
2348*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2349*aca3beaaSApple OSS Distributions // Don't allow the clients to clear
2350*aca3beaaSApple OSS Distributions // NETAGENT_FLAG_REGISTERED.
2351*aca3beaaSApple OSS Distributions uint32_t registered =
2352*aca3beaaSApple OSS Distributions wrapper->netagent->netagent_flags & NETAGENT_FLAG_REGISTERED;
2353*aca3beaaSApple OSS Distributions flags |= registered;
2354*aca3beaaSApple OSS Distributions if (wrapper->netagent->netagent_flags != flags) {
2355*aca3beaaSApple OSS Distributions wrapper->netagent->netagent_flags = flags;
2356*aca3beaaSApple OSS Distributions wrapper->generation = g_next_generation++;
2357*aca3beaaSApple OSS Distributions updated = true;
2358*aca3beaaSApple OSS Distributions }
2359*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2360*aca3beaaSApple OSS Distributions } else {
2361*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG,
2362*aca3beaaSApple OSS Distributions "Attempt to set flags for invalid netagent");
2363*aca3beaaSApple OSS Distributions error = ENOENT;
2364*aca3beaaSApple OSS Distributions }
2365*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2366*aca3beaaSApple OSS Distributions if (updated) {
2367*aca3beaaSApple OSS Distributions netagent_post_event(uuid, KEV_NETAGENT_UPDATED, true, false);
2368*aca3beaaSApple OSS Distributions }
2369*aca3beaaSApple OSS Distributions
2370*aca3beaaSApple OSS Distributions return error;
2371*aca3beaaSApple OSS Distributions }
2372*aca3beaaSApple OSS Distributions
2373*aca3beaaSApple OSS Distributions u_int32_t
netagent_get_generation(uuid_t uuid)2374*aca3beaaSApple OSS Distributions netagent_get_generation(uuid_t uuid)
2375*aca3beaaSApple OSS Distributions {
2376*aca3beaaSApple OSS Distributions u_int32_t generation = 0;
2377*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2378*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(uuid, false, false);
2379*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2380*aca3beaaSApple OSS Distributions generation = wrapper->generation;
2381*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2382*aca3beaaSApple OSS Distributions } else {
2383*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
2384*aca3beaaSApple OSS Distributions }
2385*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2386*aca3beaaSApple OSS Distributions
2387*aca3beaaSApple OSS Distributions return generation;
2388*aca3beaaSApple OSS Distributions }
2389*aca3beaaSApple OSS Distributions
2390*aca3beaaSApple OSS Distributions bool
netagent_get_agent_domain_and_type(uuid_t uuid,char * domain,char * type)2391*aca3beaaSApple OSS Distributions netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
2392*aca3beaaSApple OSS Distributions {
2393*aca3beaaSApple OSS Distributions bool found = FALSE;
2394*aca3beaaSApple OSS Distributions if (domain == NULL || type == NULL) {
2395*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
2396*aca3beaaSApple OSS Distributions return FALSE;
2397*aca3beaaSApple OSS Distributions }
2398*aca3beaaSApple OSS Distributions
2399*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2400*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(uuid, false, false);
2401*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2402*aca3beaaSApple OSS Distributions found = TRUE;
2403*aca3beaaSApple OSS Distributions memcpy(domain, wrapper->netagent->netagent_domain, NETAGENT_DOMAINSIZE);
2404*aca3beaaSApple OSS Distributions memcpy(type, wrapper->netagent->netagent_type, NETAGENT_TYPESIZE);
2405*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2406*aca3beaaSApple OSS Distributions } else {
2407*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Type requested for invalid netagent");
2408*aca3beaaSApple OSS Distributions }
2409*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2410*aca3beaaSApple OSS Distributions
2411*aca3beaaSApple OSS Distributions return found;
2412*aca3beaaSApple OSS Distributions }
2413*aca3beaaSApple OSS Distributions
2414*aca3beaaSApple OSS Distributions int
netagent_kernel_trigger(uuid_t uuid)2415*aca3beaaSApple OSS Distributions netagent_kernel_trigger(uuid_t uuid)
2416*aca3beaaSApple OSS Distributions {
2417*aca3beaaSApple OSS Distributions int error = 0;
2418*aca3beaaSApple OSS Distributions
2419*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2420*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(uuid, false, false);
2421*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2422*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
2423*aca3beaaSApple OSS Distributions error = ENOENT;
2424*aca3beaaSApple OSS Distributions goto done;
2425*aca3beaaSApple OSS Distributions }
2426*aca3beaaSApple OSS Distributions
2427*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
2428*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
2429*aca3beaaSApple OSS Distributions // Agent does not accept kernel triggers
2430*aca3beaaSApple OSS Distributions error = EINVAL;
2431*aca3beaaSApple OSS Distributions goto done;
2432*aca3beaaSApple OSS Distributions }
2433*aca3beaaSApple OSS Distributions
2434*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2435*aca3beaaSApple OSS Distributions // Agent already active
2436*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
2437*aca3beaaSApple OSS Distributions error = 0;
2438*aca3beaaSApple OSS Distributions goto done;
2439*aca3beaaSApple OSS Distributions }
2440*aca3beaaSApple OSS Distributions
2441*aca3beaaSApple OSS Distributions error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
2442*aca3beaaSApple OSS Distributions NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
2443*aca3beaaSApple OSS Distributions done:
2444*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2445*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2446*aca3beaaSApple OSS Distributions }
2447*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2448*aca3beaaSApple OSS Distributions return error;
2449*aca3beaaSApple OSS Distributions }
2450*aca3beaaSApple OSS Distributions
2451*aca3beaaSApple OSS Distributions int
netagent_client_message_with_params(uuid_t agent_uuid,uuid_t necp_client_uuid,pid_t pid,void * handle,u_int8_t message_type,struct necp_client_agent_parameters * parameters,void ** assigned_results,size_t * assigned_results_length)2452*aca3beaaSApple OSS Distributions netagent_client_message_with_params(uuid_t agent_uuid,
2453*aca3beaaSApple OSS Distributions uuid_t necp_client_uuid,
2454*aca3beaaSApple OSS Distributions pid_t pid,
2455*aca3beaaSApple OSS Distributions void *handle,
2456*aca3beaaSApple OSS Distributions u_int8_t message_type,
2457*aca3beaaSApple OSS Distributions struct necp_client_agent_parameters *parameters,
2458*aca3beaaSApple OSS Distributions void **assigned_results,
2459*aca3beaaSApple OSS Distributions size_t *assigned_results_length)
2460*aca3beaaSApple OSS Distributions {
2461*aca3beaaSApple OSS Distributions int error = 0;
2462*aca3beaaSApple OSS Distributions
2463*aca3beaaSApple OSS Distributions if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
2464*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
2465*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
2466*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ERROR &&
2467*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
2468*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS &&
2469*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_ABORT_NEXUS &&
2470*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS &&
2471*aca3beaaSApple OSS Distributions message_type != NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2472*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
2473*aca3beaaSApple OSS Distributions return EINVAL;
2474*aca3beaaSApple OSS Distributions }
2475*aca3beaaSApple OSS Distributions
2476*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2477*aca3beaaSApple OSS Distributions bool should_unlock_list = true;
2478*aca3beaaSApple OSS Distributions bool should_unlock_wrapper = true;
2479*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(agent_uuid, false, false);
2480*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2481*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2482*aca3beaaSApple OSS Distributions error = ENOENT;
2483*aca3beaaSApple OSS Distributions goto done;
2484*aca3beaaSApple OSS Distributions }
2485*aca3beaaSApple OSS Distributions
2486*aca3beaaSApple OSS Distributions if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2487*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2488*aca3beaaSApple OSS Distributions // Agent does not accept user triggers
2489*aca3beaaSApple OSS Distributions // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
2490*aca3beaaSApple OSS Distributions error = ENOTSUP;
2491*aca3beaaSApple OSS Distributions
2492*aca3beaaSApple OSS Distributions
2493*aca3beaaSApple OSS Distributions pid_t report_pid = 0;
2494*aca3beaaSApple OSS Distributions uuid_t report_proc_uuid = {};
2495*aca3beaaSApple OSS Distributions if (parameters != NULL) {
2496*aca3beaaSApple OSS Distributions report_pid = parameters->u.nexus_request.epid;
2497*aca3beaaSApple OSS Distributions uuid_copy(report_proc_uuid, parameters->u.nexus_request.euuid);
2498*aca3beaaSApple OSS Distributions } else {
2499*aca3beaaSApple OSS Distributions struct proc *p = current_proc();
2500*aca3beaaSApple OSS Distributions if (p != NULL) {
2501*aca3beaaSApple OSS Distributions report_pid = proc_pid(p);
2502*aca3beaaSApple OSS Distributions proc_getexecutableuuid(p, report_proc_uuid, sizeof(report_proc_uuid));
2503*aca3beaaSApple OSS Distributions }
2504*aca3beaaSApple OSS Distributions }
2505*aca3beaaSApple OSS Distributions netagent_send_cellular_failed_event(wrapper, report_pid, report_proc_uuid);
2506*aca3beaaSApple OSS Distributions goto done;
2507*aca3beaaSApple OSS Distributions }
2508*aca3beaaSApple OSS Distributions } else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
2509*aca3beaaSApple OSS Distributions message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS ||
2510*aca3beaaSApple OSS Distributions message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2511*aca3beaaSApple OSS Distributions bool is_nexus_agent = ((wrapper->netagent->netagent_flags &
2512*aca3beaaSApple OSS Distributions (NETAGENT_FLAG_NEXUS_PROVIDER |
2513*aca3beaaSApple OSS Distributions NETAGENT_FLAG_NEXUS_LISTENER |
2514*aca3beaaSApple OSS Distributions NETAGENT_FLAG_CUSTOM_IP_NEXUS |
2515*aca3beaaSApple OSS Distributions NETAGENT_FLAG_CUSTOM_ETHER_NEXUS |
2516*aca3beaaSApple OSS Distributions NETAGENT_FLAG_INTERPOSE_NEXUS)) != 0);
2517*aca3beaaSApple OSS Distributions if (!is_nexus_agent) {
2518*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
2519*aca3beaaSApple OSS Distributions // Agent is not a nexus provider
2520*aca3beaaSApple OSS Distributions error = EINVAL;
2521*aca3beaaSApple OSS Distributions goto done;
2522*aca3beaaSApple OSS Distributions }
2523*aca3beaaSApple OSS Distributions
2524*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
2525*aca3beaaSApple OSS Distributions // Agent not active
2526*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
2527*aca3beaaSApple OSS Distributions error = EINVAL;
2528*aca3beaaSApple OSS Distributions goto done;
2529*aca3beaaSApple OSS Distributions }
2530*aca3beaaSApple OSS Distributions } else if (message_type == NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS ||
2531*aca3beaaSApple OSS Distributions message_type == NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2532*aca3beaaSApple OSS Distributions bool is_group_agent = ((wrapper->netagent->netagent_flags & (NETAGENT_FLAG_SUPPORTS_GROUPS)) != 0);
2533*aca3beaaSApple OSS Distributions if (!is_group_agent) {
2534*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent for group operation is not a group provider");
2535*aca3beaaSApple OSS Distributions error = EINVAL;
2536*aca3beaaSApple OSS Distributions goto done;
2537*aca3beaaSApple OSS Distributions }
2538*aca3beaaSApple OSS Distributions
2539*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
2540*aca3beaaSApple OSS Distributions // Agent not active
2541*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_INFO, "Requested netagent for group operation is not active");
2542*aca3beaaSApple OSS Distributions error = EINVAL;
2543*aca3beaaSApple OSS Distributions goto done;
2544*aca3beaaSApple OSS Distributions }
2545*aca3beaaSApple OSS Distributions }
2546*aca3beaaSApple OSS Distributions
2547*aca3beaaSApple OSS Distributions if (wrapper->control_unit == 0) {
2548*aca3beaaSApple OSS Distributions if (wrapper->event_handler == NULL) {
2549*aca3beaaSApple OSS Distributions // No event handler registered for kernel agent
2550*aca3beaaSApple OSS Distributions error = EINVAL;
2551*aca3beaaSApple OSS Distributions } else {
2552*aca3beaaSApple OSS Distributions // We hold the wrapper lock during the event handler callout, so it is expected
2553*aca3beaaSApple OSS Distributions // that the event handler will not lead to any registrations or unregistrations
2554*aca3beaaSApple OSS Distributions // of network agents.
2555*aca3beaaSApple OSS Distributions // We release the list lock before calling the event handler to allow other threads
2556*aca3beaaSApple OSS Distributions // to access the list while the event is processing.
2557*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2558*aca3beaaSApple OSS Distributions should_unlock_list = false;
2559*aca3beaaSApple OSS Distributions error = wrapper->event_handler(message_type, necp_client_uuid, pid, handle,
2560*aca3beaaSApple OSS Distributions wrapper->event_context, parameters,
2561*aca3beaaSApple OSS Distributions assigned_results, assigned_results_length);
2562*aca3beaaSApple OSS Distributions if (error != 0) {
2563*aca3beaaSApple OSS Distributions VERIFY(assigned_results == NULL || *assigned_results == NULL);
2564*aca3beaaSApple OSS Distributions VERIFY(assigned_results_length == NULL || *assigned_results_length == 0);
2565*aca3beaaSApple OSS Distributions }
2566*aca3beaaSApple OSS Distributions }
2567*aca3beaaSApple OSS Distributions } else {
2568*aca3beaaSApple OSS Distributions // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2569*aca3beaaSApple OSS Distributions if (message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2570*aca3beaaSApple OSS Distributions message_type = NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS;
2571*aca3beaaSApple OSS Distributions }
2572*aca3beaaSApple OSS Distributions
2573*aca3beaaSApple OSS Distributions if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_ERROR) {
2574*aca3beaaSApple OSS Distributions const int32_t client_error = parameters->u.error;
2575*aca3beaaSApple OSS Distributions if (wrapper->last_client_error != client_error || // Always notify for an error change
2576*aca3beaaSApple OSS Distributions (client_error == 0 && wrapper->client_error_count == 0) || // Only notify once for no-error
2577*aca3beaaSApple OSS Distributions (client_error != 0 && wrapper->client_error_count < NETAGENT_MAX_CLIENT_ERROR_COUNT)) {
2578*aca3beaaSApple OSS Distributions if (NETAGENT_LOCK_SHARED_TO_EXCLUSIVE(wrapper)) {
2579*aca3beaaSApple OSS Distributions if (wrapper->last_client_error != client_error) {
2580*aca3beaaSApple OSS Distributions wrapper->last_client_error = client_error;
2581*aca3beaaSApple OSS Distributions wrapper->client_error_count = 1;
2582*aca3beaaSApple OSS Distributions } else {
2583*aca3beaaSApple OSS Distributions wrapper->client_error_count++;
2584*aca3beaaSApple OSS Distributions }
2585*aca3beaaSApple OSS Distributions error = netagent_send_error_message(wrapper, necp_client_uuid, message_type, client_error);
2586*aca3beaaSApple OSS Distributions } else {
2587*aca3beaaSApple OSS Distributions // If NETAGENT_LOCK_SHARED_TO_EXCLUSIVE fails, it unlocks automatically
2588*aca3beaaSApple OSS Distributions should_unlock_wrapper = false;
2589*aca3beaaSApple OSS Distributions }
2590*aca3beaaSApple OSS Distributions }
2591*aca3beaaSApple OSS Distributions } else if (message_type == NETAGENT_MESSAGE_TYPE_ADD_GROUP_MEMBERS ||
2592*aca3beaaSApple OSS Distributions message_type == NETAGENT_MESSAGE_TYPE_REMOVE_GROUP_MEMBERS) {
2593*aca3beaaSApple OSS Distributions error = netagent_send_group_message(wrapper, necp_client_uuid, message_type, ¶meters->u.group_members);
2594*aca3beaaSApple OSS Distributions } else {
2595*aca3beaaSApple OSS Distributions error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
2596*aca3beaaSApple OSS Distributions }
2597*aca3beaaSApple OSS Distributions if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2598*aca3beaaSApple OSS Distributions if (NETAGENT_LOCK_SHARED_TO_EXCLUSIVE(wrapper)) {
2599*aca3beaaSApple OSS Distributions // Grab the lock exclusively to add a pending client to the list
2600*aca3beaaSApple OSS Distributions struct netagent_client *new_pending_client = NULL;
2601*aca3beaaSApple OSS Distributions new_pending_client = kalloc_type(struct netagent_client, Z_WAITOK);
2602*aca3beaaSApple OSS Distributions if (new_pending_client == NULL) {
2603*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
2604*aca3beaaSApple OSS Distributions } else {
2605*aca3beaaSApple OSS Distributions uuid_copy(new_pending_client->client_id, necp_client_uuid);
2606*aca3beaaSApple OSS Distributions if (parameters != NULL) {
2607*aca3beaaSApple OSS Distributions new_pending_client->client_pid = parameters->u.nexus_request.epid;
2608*aca3beaaSApple OSS Distributions uuid_copy(new_pending_client->client_proc_uuid, parameters->u.nexus_request.euuid);
2609*aca3beaaSApple OSS Distributions } else {
2610*aca3beaaSApple OSS Distributions struct proc *p = current_proc();
2611*aca3beaaSApple OSS Distributions if (p != NULL) {
2612*aca3beaaSApple OSS Distributions new_pending_client->client_pid = proc_pid(p);
2613*aca3beaaSApple OSS Distributions proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
2614*aca3beaaSApple OSS Distributions }
2615*aca3beaaSApple OSS Distributions }
2616*aca3beaaSApple OSS Distributions LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
2617*aca3beaaSApple OSS Distributions }
2618*aca3beaaSApple OSS Distributions } else {
2619*aca3beaaSApple OSS Distributions // If NETAGENT_LOCK_SHARED_TO_EXCLUSIVE fails, it unlocks automatically
2620*aca3beaaSApple OSS Distributions should_unlock_wrapper = false;
2621*aca3beaaSApple OSS Distributions }
2622*aca3beaaSApple OSS Distributions }
2623*aca3beaaSApple OSS Distributions }
2624*aca3beaaSApple OSS Distributions NETAGENTLOG(((error && error != ENOENT) ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
2625*aca3beaaSApple OSS Distributions if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2626*aca3beaaSApple OSS Distributions uuid_string_t uuid_str;
2627*aca3beaaSApple OSS Distributions uuid_unparse(agent_uuid, uuid_str);
2628*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_NOTICE, "Triggered network agent %s, error = %d", uuid_str, error);
2629*aca3beaaSApple OSS Distributions }
2630*aca3beaaSApple OSS Distributions done:
2631*aca3beaaSApple OSS Distributions if (should_unlock_wrapper && wrapper != NULL) {
2632*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2633*aca3beaaSApple OSS Distributions }
2634*aca3beaaSApple OSS Distributions if (should_unlock_list) {
2635*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2636*aca3beaaSApple OSS Distributions }
2637*aca3beaaSApple OSS Distributions return error;
2638*aca3beaaSApple OSS Distributions }
2639*aca3beaaSApple OSS Distributions
2640*aca3beaaSApple OSS Distributions int
netagent_client_message(uuid_t agent_uuid,uuid_t necp_client_uuid,pid_t pid,void * handle,u_int8_t message_type)2641*aca3beaaSApple OSS Distributions netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, pid_t pid, void *handle, u_int8_t message_type)
2642*aca3beaaSApple OSS Distributions {
2643*aca3beaaSApple OSS Distributions return netagent_client_message_with_params(agent_uuid, necp_client_uuid, pid, handle, message_type, NULL, NULL, NULL);
2644*aca3beaaSApple OSS Distributions }
2645*aca3beaaSApple OSS Distributions
2646*aca3beaaSApple OSS Distributions int
netagent_use(uuid_t agent_uuid,uint64_t * out_use_count)2647*aca3beaaSApple OSS Distributions netagent_use(uuid_t agent_uuid, uint64_t *out_use_count)
2648*aca3beaaSApple OSS Distributions {
2649*aca3beaaSApple OSS Distributions int error = 0;
2650*aca3beaaSApple OSS Distributions
2651*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2652*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(agent_uuid, true, false);
2653*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2654*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "netagent_assert: Requested netagent UUID is not registered");
2655*aca3beaaSApple OSS Distributions error = ENOENT;
2656*aca3beaaSApple OSS Distributions goto done;
2657*aca3beaaSApple OSS Distributions }
2658*aca3beaaSApple OSS Distributions
2659*aca3beaaSApple OSS Distributions uint64_t current_count = wrapper->use_count;
2660*aca3beaaSApple OSS Distributions wrapper->use_count++;
2661*aca3beaaSApple OSS Distributions
2662*aca3beaaSApple OSS Distributions if (out_use_count != NULL) {
2663*aca3beaaSApple OSS Distributions *out_use_count = current_count;
2664*aca3beaaSApple OSS Distributions }
2665*aca3beaaSApple OSS Distributions
2666*aca3beaaSApple OSS Distributions done:
2667*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2668*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2669*aca3beaaSApple OSS Distributions }
2670*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2671*aca3beaaSApple OSS Distributions return error;
2672*aca3beaaSApple OSS Distributions }
2673*aca3beaaSApple OSS Distributions
2674*aca3beaaSApple OSS Distributions int
netagent_copyout(uuid_t agent_uuid,user_addr_t user_addr,u_int32_t user_size)2675*aca3beaaSApple OSS Distributions netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
2676*aca3beaaSApple OSS Distributions {
2677*aca3beaaSApple OSS Distributions int error = 0;
2678*aca3beaaSApple OSS Distributions
2679*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2680*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(agent_uuid, false, false);
2681*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2682*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2683*aca3beaaSApple OSS Distributions error = ENOENT;
2684*aca3beaaSApple OSS Distributions goto done;
2685*aca3beaaSApple OSS Distributions }
2686*aca3beaaSApple OSS Distributions
2687*aca3beaaSApple OSS Distributions u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent->netagent_data_size);
2688*aca3beaaSApple OSS Distributions if (user_size < total_size) {
2689*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
2690*aca3beaaSApple OSS Distributions error = EINVAL;
2691*aca3beaaSApple OSS Distributions goto done;
2692*aca3beaaSApple OSS Distributions }
2693*aca3beaaSApple OSS Distributions
2694*aca3beaaSApple OSS Distributions error = copyout(wrapper->netagent, user_addr, total_size);
2695*aca3beaaSApple OSS Distributions
2696*aca3beaaSApple OSS Distributions NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
2697*aca3beaaSApple OSS Distributions done:
2698*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2699*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2700*aca3beaaSApple OSS Distributions }
2701*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2702*aca3beaaSApple OSS Distributions return error;
2703*aca3beaaSApple OSS Distributions }
2704*aca3beaaSApple OSS Distributions
2705*aca3beaaSApple OSS Distributions #define NETAGENT_TOKEN_EVENT_INTERVAL_NSEC (NSEC_PER_SEC * 10) // Only fire repeated events up to once every 10 seconds
2706*aca3beaaSApple OSS Distributions
2707*aca3beaaSApple OSS Distributions int
netagent_acquire_token(uuid_t agent_uuid,user_addr_t user_addr,u_int32_t user_size,int * retval)2708*aca3beaaSApple OSS Distributions netagent_acquire_token(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size, int *retval)
2709*aca3beaaSApple OSS Distributions {
2710*aca3beaaSApple OSS Distributions int error = 0;
2711*aca3beaaSApple OSS Distributions
2712*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2713*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(agent_uuid, true, false);
2714*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2715*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Network agent for request UUID could not be found");
2716*aca3beaaSApple OSS Distributions error = ENOENT;
2717*aca3beaaSApple OSS Distributions goto done;
2718*aca3beaaSApple OSS Distributions }
2719*aca3beaaSApple OSS Distributions
2720*aca3beaaSApple OSS Distributions struct netagent_token *token = TAILQ_FIRST(&wrapper->token_list);
2721*aca3beaaSApple OSS Distributions if (token == NULL) {
2722*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_DEBUG, "Network agent does not have any tokens");
2723*aca3beaaSApple OSS Distributions if (wrapper->token_low_water != 0) {
2724*aca3beaaSApple OSS Distributions // Only fire an event if one hasn't occurred in the last 10 seconds
2725*aca3beaaSApple OSS Distributions if (mach_absolute_time() >= wrapper->need_tokens_event_deadline) {
2726*aca3beaaSApple OSS Distributions int event_error = netagent_send_tokens_needed(wrapper);
2727*aca3beaaSApple OSS Distributions if (event_error == 0) {
2728*aca3beaaSApple OSS Distributions // Reset the deadline
2729*aca3beaaSApple OSS Distributions uint64_t deadline = 0;
2730*aca3beaaSApple OSS Distributions nanoseconds_to_absolutetime(NETAGENT_TOKEN_EVENT_INTERVAL_NSEC, &deadline);
2731*aca3beaaSApple OSS Distributions clock_absolutetime_interval_to_deadline(deadline, &deadline);
2732*aca3beaaSApple OSS Distributions wrapper->need_tokens_event_deadline = deadline;
2733*aca3beaaSApple OSS Distributions }
2734*aca3beaaSApple OSS Distributions }
2735*aca3beaaSApple OSS Distributions }
2736*aca3beaaSApple OSS Distributions error = ENODATA;
2737*aca3beaaSApple OSS Distributions goto done;
2738*aca3beaaSApple OSS Distributions }
2739*aca3beaaSApple OSS Distributions
2740*aca3beaaSApple OSS Distributions if (user_size < token->token_length) {
2741*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, token->token_length);
2742*aca3beaaSApple OSS Distributions error = EMSGSIZE;
2743*aca3beaaSApple OSS Distributions goto done;
2744*aca3beaaSApple OSS Distributions }
2745*aca3beaaSApple OSS Distributions
2746*aca3beaaSApple OSS Distributions error = copyout(token->token_bytes, user_addr, token->token_length);
2747*aca3beaaSApple OSS Distributions if (error == 0) {
2748*aca3beaaSApple OSS Distributions *retval = (int)token->token_length;
2749*aca3beaaSApple OSS Distributions }
2750*aca3beaaSApple OSS Distributions
2751*aca3beaaSApple OSS Distributions NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied token content (error %d)", error);
2752*aca3beaaSApple OSS Distributions
2753*aca3beaaSApple OSS Distributions TAILQ_REMOVE(&wrapper->token_list, token, token_chain);
2754*aca3beaaSApple OSS Distributions netagent_token_free(token);
2755*aca3beaaSApple OSS Distributions if (wrapper->token_count > 0) {
2756*aca3beaaSApple OSS Distributions wrapper->token_count--;
2757*aca3beaaSApple OSS Distributions }
2758*aca3beaaSApple OSS Distributions if (wrapper->token_count < wrapper->token_low_water) {
2759*aca3beaaSApple OSS Distributions (void)netagent_send_tokens_needed(wrapper);
2760*aca3beaaSApple OSS Distributions }
2761*aca3beaaSApple OSS Distributions done:
2762*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2763*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2764*aca3beaaSApple OSS Distributions }
2765*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2766*aca3beaaSApple OSS Distributions return error;
2767*aca3beaaSApple OSS Distributions }
2768*aca3beaaSApple OSS Distributions
2769*aca3beaaSApple OSS Distributions int
netagent_trigger(struct proc * p,struct netagent_trigger_args * uap,int32_t * retval)2770*aca3beaaSApple OSS Distributions netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
2771*aca3beaaSApple OSS Distributions {
2772*aca3beaaSApple OSS Distributions #pragma unused(p, retval)
2773*aca3beaaSApple OSS Distributions uuid_t agent_uuid = {};
2774*aca3beaaSApple OSS Distributions int error = 0;
2775*aca3beaaSApple OSS Distributions
2776*aca3beaaSApple OSS Distributions if (uap == NULL) {
2777*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "uap == NULL");
2778*aca3beaaSApple OSS Distributions return EINVAL;
2779*aca3beaaSApple OSS Distributions }
2780*aca3beaaSApple OSS Distributions
2781*aca3beaaSApple OSS Distributions if (uap->agent_uuid) {
2782*aca3beaaSApple OSS Distributions if (uap->agent_uuidlen != sizeof(uuid_t)) {
2783*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "Incorrect length (got %zu, expected %lu)",
2784*aca3beaaSApple OSS Distributions (size_t)uap->agent_uuidlen, sizeof(uuid_t));
2785*aca3beaaSApple OSS Distributions return ERANGE;
2786*aca3beaaSApple OSS Distributions }
2787*aca3beaaSApple OSS Distributions
2788*aca3beaaSApple OSS Distributions error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
2789*aca3beaaSApple OSS Distributions if (error) {
2790*aca3beaaSApple OSS Distributions NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
2791*aca3beaaSApple OSS Distributions return error;
2792*aca3beaaSApple OSS Distributions }
2793*aca3beaaSApple OSS Distributions }
2794*aca3beaaSApple OSS Distributions
2795*aca3beaaSApple OSS Distributions if (uuid_is_null(agent_uuid)) {
2796*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
2797*aca3beaaSApple OSS Distributions return EINVAL;
2798*aca3beaaSApple OSS Distributions }
2799*aca3beaaSApple OSS Distributions
2800*aca3beaaSApple OSS Distributions NETAGENT_LIST_LOCK_SHARED();
2801*aca3beaaSApple OSS Distributions struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid_and_lock(agent_uuid, false, false);
2802*aca3beaaSApple OSS Distributions if (wrapper == NULL) {
2803*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
2804*aca3beaaSApple OSS Distributions error = ENOENT;
2805*aca3beaaSApple OSS Distributions goto done;
2806*aca3beaaSApple OSS Distributions }
2807*aca3beaaSApple OSS Distributions
2808*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2809*aca3beaaSApple OSS Distributions // Agent does not accept triggers
2810*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
2811*aca3beaaSApple OSS Distributions error = ENOTSUP;
2812*aca3beaaSApple OSS Distributions goto done;
2813*aca3beaaSApple OSS Distributions }
2814*aca3beaaSApple OSS Distributions
2815*aca3beaaSApple OSS Distributions if ((wrapper->netagent->netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2816*aca3beaaSApple OSS Distributions // Agent already active
2817*aca3beaaSApple OSS Distributions NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
2818*aca3beaaSApple OSS Distributions error = 0;
2819*aca3beaaSApple OSS Distributions goto done;
2820*aca3beaaSApple OSS Distributions }
2821*aca3beaaSApple OSS Distributions
2822*aca3beaaSApple OSS Distributions error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
2823*aca3beaaSApple OSS Distributions NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
2824*aca3beaaSApple OSS Distributions done:
2825*aca3beaaSApple OSS Distributions if (wrapper != NULL) {
2826*aca3beaaSApple OSS Distributions NETAGENT_UNLOCK(wrapper);
2827*aca3beaaSApple OSS Distributions }
2828*aca3beaaSApple OSS Distributions NETAGENT_LIST_UNLOCK();
2829*aca3beaaSApple OSS Distributions return error;
2830*aca3beaaSApple OSS Distributions }
2831