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