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