]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/network_agent.c
e0489c5d89c24a8c44174240e447c7d1662531ee
[apple/xnu.git] / bsd / net / network_agent.c
1 /*
2 * Copyright (c) 2014-2018 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_wrapper {
91 LIST_ENTRY(netagent_wrapper) master_chain;
92 u_int32_t control_unit;
93 netagent_event_f event_handler;
94 void *event_context;
95 u_int32_t generation;
96 u_int64_t use_count;
97 struct netagent_client_list_s pending_triggers_list;
98 struct netagent netagent;
99 };
100
101 struct netagent_session {
102 u_int32_t control_unit; // A control unit of 0 indicates an agent owned by the kernel
103 struct netagent_wrapper *wrapper;
104 netagent_event_f event_handler;
105 void *event_context;
106 };
107
108 typedef enum {
109 kNetagentErrorDomainPOSIX = 0,
110 kNetagentErrorDomainUserDefined = 1,
111 } netagent_error_domain_t;
112
113 static LIST_HEAD(_netagent_list, netagent_wrapper) master_netagent_list;
114
115 // Protected by netagent_lock
116 static u_int32_t g_next_generation = 1;
117
118 static kern_ctl_ref netagent_kctlref;
119 static u_int32_t netagent_family;
120 static lck_grp_attr_t *netagent_grp_attr = NULL;
121 static lck_attr_t *netagent_mtx_attr = NULL;
122 static lck_grp_t *netagent_mtx_grp = NULL;
123 decl_lck_rw_data(static, netagent_lock);
124
125 static errno_t netagent_register_control(void);
126 static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
127 void **unitinfo);
128 static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
129 static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
130 mbuf_t m, int flags);
131 static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
132 static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
133 int opt, void *data, size_t *len);
134 static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
135 int opt, void *data, size_t len);
136
137 static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
138
139 static struct netagent_session *netagent_create_session(u_int32_t control_unit);
140 static void netagent_delete_session(struct netagent_session *session);
141
142 // Register
143 static void netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
144 size_t payload_length, mbuf_t packet, size_t offset);
145 static errno_t netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
146 size_t payload_length);
147
148 // Unregister
149 static void netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
150 size_t payload_length, mbuf_t packet, size_t offset);
151 static errno_t netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
152 size_t payload_length);
153
154 // Update
155 static void netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
156 size_t payload_length, mbuf_t packet, size_t offset);
157 static errno_t netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload,
158 size_t payload_length);
159
160 // Assign nexus
161 static void netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
162 size_t payload_length, mbuf_t packet, size_t offset);
163 static errno_t netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
164 size_t payload_length);
165
166 // Set/get assert count
167 static errno_t netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length);
168 static errno_t netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length);
169
170 static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
171 size_t payload_length, mbuf_t packet, size_t offset);
172
173 static struct netagent_wrapper *netagent_find_agent_with_uuid(uuid_t uuid);
174
175 errno_t
176 netagent_init(void)
177 {
178 errno_t result = 0;
179
180 result = netagent_register_control();
181 if (result != 0) {
182 goto done;
183 }
184
185 netagent_grp_attr = lck_grp_attr_alloc_init();
186 if (netagent_grp_attr == NULL) {
187 NETAGENTLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed");
188 result = ENOMEM;
189 goto done;
190 }
191
192 netagent_mtx_grp = lck_grp_alloc_init(NETAGENT_CONTROL_NAME, netagent_grp_attr);
193 if (netagent_mtx_grp == NULL) {
194 NETAGENTLOG0(LOG_ERR, "lck_grp_alloc_init failed");
195 result = ENOMEM;
196 goto done;
197 }
198
199 netagent_mtx_attr = lck_attr_alloc_init();
200 if (netagent_mtx_attr == NULL) {
201 NETAGENTLOG0(LOG_ERR, "lck_attr_alloc_init failed");
202 result = ENOMEM;
203 goto done;
204 }
205
206 lck_rw_init(&netagent_lock, netagent_mtx_grp, netagent_mtx_attr);
207
208 LIST_INIT(&master_netagent_list);
209
210 done:
211 if (result != 0) {
212 if (netagent_mtx_attr != NULL) {
213 lck_attr_free(netagent_mtx_attr);
214 netagent_mtx_attr = NULL;
215 }
216 if (netagent_mtx_grp != NULL) {
217 lck_grp_free(netagent_mtx_grp);
218 netagent_mtx_grp = NULL;
219 }
220 if (netagent_grp_attr != NULL) {
221 lck_grp_attr_free(netagent_grp_attr);
222 netagent_grp_attr = NULL;
223 }
224 if (netagent_kctlref != NULL) {
225 ctl_deregister(netagent_kctlref);
226 netagent_kctlref = NULL;
227 }
228 }
229 return result;
230 }
231
232 static errno_t
233 netagent_register_control(void)
234 {
235 struct kern_ctl_reg kern_ctl;
236 errno_t result = 0;
237
238 // Find a unique value for our interface family
239 result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
240 if (result != 0) {
241 NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
242 return result;
243 }
244
245 bzero(&kern_ctl, sizeof(kern_ctl));
246 strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
247 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
248 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
249 kern_ctl.ctl_sendsize = 64 * 1024;
250 kern_ctl.ctl_recvsize = 64 * 1024;
251 kern_ctl.ctl_connect = netagent_ctl_connect;
252 kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
253 kern_ctl.ctl_send = netagent_ctl_send;
254 kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
255 kern_ctl.ctl_setopt = netagent_ctl_setopt;
256 kern_ctl.ctl_getopt = netagent_ctl_getopt;
257
258 result = ctl_register(&kern_ctl, &netagent_kctlref);
259 if (result != 0) {
260 NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
261 return result;
262 }
263
264 return 0;
265 }
266
267 static errno_t
268 netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
269 {
270 #pragma unused(kctlref)
271 *unitinfo = netagent_create_session(sac->sc_unit);
272 if (*unitinfo == NULL) {
273 // Could not allocate session
274 return ENOBUFS;
275 }
276
277 return 0;
278 }
279
280 static errno_t
281 netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
282 {
283 #pragma unused(kctlref, unit)
284 struct netagent_session *session = (struct netagent_session *)unitinfo;
285 if (session != NULL) {
286 netagent_delete_session(session);
287 }
288
289 return 0;
290 }
291
292 // Kernel events
293 static void
294 netagent_post_event(uuid_t agent_uuid, u_int32_t event_code, bool update_necp, bool should_update_immediately)
295 {
296 if (update_necp) {
297 necp_update_all_clients_immediately_if_needed(should_update_immediately);
298 }
299
300 struct kev_msg ev_msg;
301 memset(&ev_msg, 0, sizeof(ev_msg));
302
303 struct kev_netagent_data event_data;
304
305 ev_msg.vendor_code = KEV_VENDOR_APPLE;
306 ev_msg.kev_class = KEV_NETWORK_CLASS;
307 ev_msg.kev_subclass = KEV_NETAGENT_SUBCLASS;
308 ev_msg.event_code = event_code;
309
310 uuid_copy(event_data.netagent_uuid, agent_uuid);
311 ev_msg.dv[0].data_ptr = &event_data;
312 ev_msg.dv[0].data_length = sizeof(event_data);
313
314 kev_post_msg(&ev_msg);
315 }
316
317 // Message handling
318 static u_int8_t *
319 netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
320 u_int32_t message_id, u_int32_t error, size_t payload_length)
321 {
322 memset(buffer, 0, sizeof(struct netagent_message_header));
323 ((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
324 ((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
325 ((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
326 ((struct netagent_message_header *)(void *)buffer)->message_error = error;
327 ((struct netagent_message_header *)(void *)buffer)->message_payload_length = (u_int32_t)payload_length;
328 return buffer + sizeof(struct netagent_message_header);
329 }
330
331 static int
332 netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
333 {
334 if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
335 return EINVAL;
336 }
337
338 return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
339 }
340
341 static int
342 netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int8_t trigger_type)
343 {
344 int error = 0;
345 struct netagent_trigger_message *trigger_message = NULL;
346 u_int8_t *trigger = NULL;
347 size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
348
349 MALLOC(trigger, u_int8_t *, trigger_size, M_NETAGENT, M_WAITOK);
350 if (trigger == NULL) {
351 return ENOMEM;
352 }
353
354 (void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
355
356 trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
357 trigger_message->trigger_flags = flags;
358 if (p != NULL) {
359 trigger_message->trigger_pid = proc_pid(p);
360 proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
361 } else {
362 trigger_message->trigger_pid = 0;
363 uuid_clear(trigger_message->trigger_proc_uuid);
364 }
365
366 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)trigger, trigger_size))) {
367 NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
368 }
369
370 FREE(trigger, M_NETAGENT);
371 return error;
372 }
373
374 static int
375 netagent_send_client_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type)
376 {
377 int error = 0;
378 struct netagent_client_message *client_message = NULL;
379 u_int8_t *message = NULL;
380 size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_message);
381
382 MALLOC(message, u_int8_t *, message_size, M_NETAGENT, M_WAITOK);
383 if (message == NULL) {
384 return ENOMEM;
385 }
386
387 (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_message));
388
389 client_message = (struct netagent_client_message *)(void *)(message + sizeof(struct netagent_message_header));
390 uuid_copy(client_message->client_id, client_id);
391
392 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)message, message_size))) {
393 NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
394 }
395
396 FREE(message, M_NETAGENT);
397 return error;
398 }
399
400 static int
401 netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
402 {
403 int error = 0;
404 u_int8_t *response = NULL;
405 size_t response_size = sizeof(struct netagent_message_header);
406 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
407 if (response == NULL) {
408 return ENOMEM;
409 }
410 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
411
412 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
413 NETAGENTLOG0(LOG_ERR, "Failed to send response");
414 }
415
416 FREE(response, M_NETAGENT);
417 return error;
418 }
419
420 static errno_t
421 netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
422 u_int32_t message_id, u_int32_t error_code)
423 {
424 int error = 0;
425 u_int8_t *response = NULL;
426 size_t response_size = sizeof(struct netagent_message_header);
427
428 if (session == NULL) {
429 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
430 return EINVAL;
431 }
432
433 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
434 if (response == NULL) {
435 return ENOMEM;
436 }
437 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
438 message_id, error_code, 0);
439
440 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
441 NETAGENTLOG0(LOG_ERR, "Failed to send response");
442 }
443
444 FREE(response, M_NETAGENT);
445 return error;
446 }
447
448 static errno_t
449 netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
450 {
451 #pragma unused(kctlref, unit, flags)
452 struct netagent_session *session = (struct netagent_session *)unitinfo;
453 struct netagent_message_header header;
454 int error = 0;
455
456 if (session == NULL) {
457 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
458 error = EINVAL;
459 goto done;
460 }
461
462 if (mbuf_pkthdr_len(packet) < sizeof(header)) {
463 NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
464 mbuf_pkthdr_len(packet), sizeof(header));
465 error = EINVAL;
466 goto done;
467 }
468
469 error = mbuf_copydata(packet, 0, sizeof(header), &header);
470 if (error) {
471 NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
472 error = ENOBUFS;
473 goto done;
474 }
475
476 switch (header.message_type) {
477 case NETAGENT_MESSAGE_TYPE_REGISTER: {
478 netagent_handle_register_message(session, header.message_id, header.message_payload_length,
479 packet, sizeof(header));
480 break;
481 }
482 case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
483 netagent_handle_unregister_message(session, header.message_id, header.message_payload_length,
484 packet, sizeof(header));
485 break;
486 }
487 case NETAGENT_MESSAGE_TYPE_UPDATE: {
488 netagent_handle_update_message(session, header.message_id, header.message_payload_length,
489 packet, sizeof(header));
490 break;
491 }
492 case NETAGENT_MESSAGE_TYPE_GET: {
493 netagent_handle_get(session, header.message_id, header.message_payload_length,
494 packet, sizeof(header));
495 break;
496 }
497 case NETAGENT_MESSAGE_TYPE_ASSERT: {
498 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
499 break;
500 }
501 case NETAGENT_MESSAGE_TYPE_UNASSERT: {
502 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
503 break;
504 }
505 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS: {
506 netagent_handle_assign_nexus_message(session, header.message_id, header.message_payload_length,
507 packet, sizeof(header));
508 break;
509 }
510 default: {
511 NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
512 netagent_send_error_response(session, header.message_type, header.message_id,
513 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
514 break;
515 }
516 }
517
518 done:
519 mbuf_freem(packet);
520 return error;
521 }
522
523 static void
524 netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
525 {
526 #pragma unused(kctlref, unit, unitinfo, flags)
527 return;
528 }
529
530 static errno_t
531 netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
532 void *data, size_t *len)
533 {
534 #pragma unused(kctlref, unit)
535 struct netagent_session *session = (struct netagent_session *)unitinfo;
536 errno_t error;
537
538 if (session == NULL) {
539 NETAGENTLOG0(LOG_ERR, "Received a NULL session");
540 error = EINVAL;
541 goto done;
542 }
543
544 switch (opt) {
545 case NETAGENT_OPTION_TYPE_USE_COUNT: {
546 NETAGENTLOG0(LOG_DEBUG, "Request to get use count");
547 error = netagent_handle_use_count_getopt(session, data, len);
548 }
549 break;
550 default:
551 NETAGENTLOG0(LOG_ERR, "Received unknown option");
552 error = ENOPROTOOPT;
553 break;
554 }
555
556 done:
557 return error;
558 }
559
560 static errno_t
561 netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
562 void *data, size_t len)
563 {
564 #pragma unused(kctlref, unit)
565 struct netagent_session *session = (struct netagent_session *)unitinfo;
566 errno_t error;
567
568 if (session == NULL) {
569 NETAGENTLOG0(LOG_ERR, "Received a NULL session");
570 error = EINVAL;
571 goto done;
572 }
573
574 switch (opt) {
575 case NETAGENT_OPTION_TYPE_REGISTER: {
576 NETAGENTLOG0(LOG_DEBUG, "Request for registration");
577 error = netagent_handle_register_setopt(session, data, len);
578 }
579 break;
580 case NETAGENT_OPTION_TYPE_UPDATE: {
581 NETAGENTLOG0(LOG_DEBUG, "Request for update");
582 error = netagent_handle_update_setopt(session, data, len);
583 }
584 break;
585 case NETAGENT_OPTION_TYPE_UNREGISTER: {
586 NETAGENTLOG0(LOG_DEBUG, "Request for unregistration");
587 error = netagent_handle_unregister_setopt(session, data, len);
588 }
589 break;
590 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS: {
591 NETAGENTLOG0(LOG_DEBUG, "Request for assigning nexus");
592 error = netagent_handle_assign_nexus_setopt(session, data, len);
593 }
594 break;
595 case NETAGENT_OPTION_TYPE_USE_COUNT: {
596 NETAGENTLOG0(LOG_DEBUG, "Request to set use count");
597 error = netagent_handle_use_count_setopt(session, data, len);
598 }
599 break;
600 default:
601 NETAGENTLOG0(LOG_ERR, "Received unknown option");
602 error = ENOPROTOOPT;
603 break;
604 }
605
606 done:
607 return error;
608 }
609
610 // Session Management
611 static struct netagent_session *
612 netagent_create_session(u_int32_t control_unit)
613 {
614 struct netagent_session *new_session = NULL;
615
616 MALLOC(new_session, struct netagent_session *, sizeof(*new_session), M_NETAGENT, M_WAITOK);
617 if (new_session == NULL) {
618 goto done;
619 }
620 NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
621 memset(new_session, 0, sizeof(*new_session));
622 new_session->control_unit = control_unit;
623 new_session->wrapper = NULL;
624 done:
625 return new_session;
626 }
627
628 netagent_session_t
629 netagent_create(netagent_event_f event_handler, void *context)
630 {
631 struct netagent_session *session = netagent_create_session(0);
632 if (session == NULL) {
633 return NULL;
634 }
635
636 session->event_handler = event_handler;
637 session->event_context = context;
638 return session;
639 }
640
641 static void
642 netagent_free_wrapper(struct netagent_wrapper *wrapper)
643 {
644 // Free any pending client triggers
645 struct netagent_client *search_client = NULL;
646 struct netagent_client *temp_client = NULL;
647 LIST_FOREACH_SAFE(search_client, &wrapper->pending_triggers_list, client_chain, temp_client) {
648 LIST_REMOVE(search_client, client_chain);
649 FREE(search_client, M_NETAGENT);
650 }
651
652 // Free wrapper itself
653 FREE(wrapper, M_NETAGENT);
654 }
655
656 static void
657 netagent_unregister_session_wrapper(struct netagent_session *session)
658 {
659 bool unregistered = FALSE;
660 uuid_t unregistered_uuid;
661 struct netagent_wrapper *wrapper = NULL;
662 lck_rw_lock_exclusive(&netagent_lock);
663 if (session != NULL) {
664 wrapper = session->wrapper;
665 if (wrapper != NULL) {
666 if (netagent_registered_count > 0) {
667 netagent_registered_count--;
668 }
669 if ((session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
670 netagent_active_count > 0) {
671 netagent_active_count--;
672 }
673
674 LIST_REMOVE(wrapper, master_chain);
675
676 unregistered = TRUE;
677 uuid_copy(unregistered_uuid, session->wrapper->netagent.netagent_uuid);
678
679 netagent_free_wrapper(session->wrapper);
680 session->wrapper = NULL;
681 NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
682 }
683 }
684 lck_rw_done(&netagent_lock);
685
686 if (unregistered) {
687 ifnet_clear_netagent(unregistered_uuid);
688 netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED, TRUE, false);
689 }
690 }
691
692 static void
693 netagent_delete_session(struct netagent_session *session)
694 {
695 if (session != NULL) {
696 netagent_unregister_session_wrapper(session);
697 FREE(session, M_NETAGENT);
698 }
699 }
700
701 void
702 netagent_destroy(netagent_session_t session)
703 {
704 return netagent_delete_session((struct netagent_session *)session);
705 }
706
707 static size_t
708 netagent_packet_get_netagent_data_size(mbuf_t packet, size_t offset, int *err)
709 {
710 int error = 0;
711
712 struct netagent netagent_peek;
713 memset(&netagent_peek, 0, sizeof(netagent_peek));
714
715 *err = 0;
716
717 error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
718 if (error) {
719 *err = ENOENT;
720 return 0;
721 }
722
723 return netagent_peek.netagent_data_size;
724 }
725
726 static errno_t
727 netagent_handle_register_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper)
728 {
729 lck_rw_lock_exclusive(&netagent_lock);
730
731 if (session->wrapper != NULL) {
732 lck_rw_done(&netagent_lock);
733 return EINVAL;
734 }
735
736 new_wrapper->control_unit = session->control_unit;
737 new_wrapper->event_handler = session->event_handler;
738 new_wrapper->event_context = session->event_context;
739 new_wrapper->generation = g_next_generation++;
740
741 session->wrapper = new_wrapper;
742 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
743 LIST_INIT(&new_wrapper->pending_triggers_list);
744
745 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
746 netagent_registered_count++;
747 if (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) {
748 netagent_active_count++;
749 }
750
751 lck_rw_done(&netagent_lock);
752
753 return 0;
754 }
755
756 errno_t
757 netagent_register(netagent_session_t _session, struct netagent *agent)
758 {
759 struct netagent_wrapper *new_wrapper = NULL;
760 uuid_t registered_uuid;
761
762 struct netagent_session *session = (struct netagent_session *)_session;
763 if (session == NULL) {
764 NETAGENTLOG0(LOG_ERR, "Cannot register agent on NULL session");
765 return EINVAL;
766 }
767
768 if (agent == NULL) {
769 NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
770 return EINVAL;
771 }
772
773 if (session->wrapper != NULL) {
774 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
775 return EINVAL;
776 }
777
778 size_t data_size = agent->netagent_data_size;
779 if (data_size > NETAGENT_MAX_DATA_SIZE) {
780 NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu",
781 data_size);
782 return EINVAL;
783 }
784
785 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
786 if (new_wrapper == NULL) {
787 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
788 return ENOMEM;
789 }
790
791 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
792 __nochk_memcpy(&new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
793
794 uuid_copy(registered_uuid, new_wrapper->netagent.netagent_uuid);
795
796 errno_t error = netagent_handle_register_inner(session, new_wrapper);
797 if (error != 0) {
798 FREE(new_wrapper, M_NETAGENT);
799 return error;
800 }
801
802 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
803 netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
804
805 return 0;
806 }
807
808 static errno_t
809 netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
810 size_t payload_length)
811 {
812 struct netagent_wrapper *new_wrapper = NULL;
813 errno_t response_error = 0;
814 struct netagent *register_netagent = (struct netagent *)(void *)payload;
815 uuid_t registered_uuid;
816
817 if (session == NULL) {
818 NETAGENTLOG0(LOG_ERR, "Failed to find session");
819 response_error = EINVAL;
820 goto done;
821 }
822
823 if (payload == NULL) {
824 NETAGENTLOG0(LOG_ERR, "No payload received");
825 response_error = EINVAL;
826 goto done;
827 }
828
829 if (session->wrapper != NULL) {
830 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
831 response_error = EINVAL;
832 goto done;
833 }
834
835 if (payload_length < sizeof(struct netagent)) {
836 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
837 payload_length, sizeof(struct netagent));
838 response_error = EINVAL;
839 goto done;
840 }
841
842 size_t data_size = register_netagent->netagent_data_size;
843 if (data_size > NETAGENT_MAX_DATA_SIZE) {
844 NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %zu", data_size);
845 response_error = EINVAL;
846 goto done;
847 }
848
849 if (payload_length != (sizeof(struct netagent) + data_size)) {
850 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
851 response_error = EINVAL;
852 goto done;
853 }
854
855 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
856 if (new_wrapper == NULL) {
857 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
858 response_error = ENOMEM;
859 goto done;
860 }
861
862 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
863 __nochk_memcpy(&new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
864
865 uuid_copy(registered_uuid, new_wrapper->netagent.netagent_uuid);
866
867 response_error = netagent_handle_register_inner(session, new_wrapper);
868 if (response_error != 0) {
869 FREE(new_wrapper, M_NETAGENT);
870 goto done;
871 }
872
873 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
874 netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
875
876 done:
877 return response_error;
878 }
879
880 static void
881 netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
882 size_t payload_length, mbuf_t packet, size_t offset)
883 {
884 errno_t error;
885 struct netagent_wrapper *new_wrapper = NULL;
886 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
887 uuid_t registered_uuid;
888
889 if (session == NULL) {
890 NETAGENTLOG0(LOG_ERR, "Failed to find session");
891 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
892 goto fail;
893 }
894
895 if (session->wrapper != NULL) {
896 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
897 response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
898 goto fail;
899 }
900
901 if (payload_length < sizeof(struct netagent)) {
902 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%zu < %zu)",
903 payload_length, sizeof(struct netagent));
904 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
905 goto fail;
906 }
907
908 size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
909 if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
910 NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %zu",
911 error, data_size);
912 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
913 goto fail;
914 }
915
916 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
917 if (new_wrapper == NULL) {
918 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
919 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
920 goto fail;
921 }
922
923 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
924
925 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
926 &new_wrapper->netagent);
927 if (error) {
928 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
929 FREE(new_wrapper, M_NETAGENT);
930 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
931 goto fail;
932 }
933
934 uuid_copy(registered_uuid, new_wrapper->netagent.netagent_uuid);
935
936 error = netagent_handle_register_inner(session, new_wrapper);
937 if (error) {
938 NETAGENTLOG(LOG_ERR, "Failed to register agent: %d", error);
939 FREE(new_wrapper, M_NETAGENT);
940 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
941 goto fail;
942 }
943
944 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
945 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
946 netagent_post_event(registered_uuid, KEV_NETAGENT_REGISTERED, TRUE, false);
947 return;
948 fail:
949 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
950 }
951
952 errno_t
953 netagent_unregister(netagent_session_t _session)
954 {
955 struct netagent_session *session = (struct netagent_session *)_session;
956 if (session == NULL) {
957 NETAGENTLOG0(LOG_ERR, "Cannot unregister NULL session");
958 return EINVAL;
959 }
960
961 netagent_unregister_session_wrapper(session);
962 return 0;
963 }
964
965 static errno_t
966 netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
967 size_t payload_length)
968 {
969 #pragma unused(payload, payload_length)
970 errno_t response_error = 0;
971
972 if (session == NULL) {
973 NETAGENTLOG0(LOG_ERR, "Failed to find session");
974 response_error = EINVAL;
975 goto done;
976 }
977
978 netagent_unregister_session_wrapper(session);
979
980 done:
981 return response_error;
982 }
983
984 static void
985 netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
986 size_t payload_length, mbuf_t packet, size_t offset)
987 {
988 #pragma unused(payload_length, packet, offset)
989 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
990
991 if (session == NULL) {
992 NETAGENTLOG0(LOG_ERR, "Failed to find session");
993 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
994 goto fail;
995 }
996
997 netagent_unregister_session_wrapper(session);
998
999 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
1000 return;
1001 fail:
1002 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
1003 }
1004
1005 static void
1006 netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
1007 pid_t pid, uuid_t proc_uuid)
1008 {
1009 if (strncmp(wrapper->netagent.netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
1010 return;
1011 }
1012
1013 struct kev_netpolicy_ifdenied ev_ifdenied;
1014
1015 bzero(&ev_ifdenied, sizeof(ev_ifdenied));
1016
1017 ev_ifdenied.ev_data.epid = (u_int64_t)pid;
1018 uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
1019 ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
1020
1021 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
1022 }
1023
1024 static errno_t
1025 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)
1026 {
1027 errno_t response_error = 0;
1028
1029 if (agent_changed == NULL) {
1030 NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
1031 return EINVAL;
1032 }
1033
1034 lck_rw_lock_exclusive(&netagent_lock);
1035
1036 if (session->wrapper == NULL) {
1037 lck_rw_done(&netagent_lock);
1038 response_error = ENOENT;
1039 return response_error;
1040 }
1041
1042 if (uuid_compare(session->wrapper->netagent.netagent_uuid, new_wrapper->netagent.netagent_uuid) != 0 ||
1043 memcmp(&session->wrapper->netagent.netagent_domain, &new_wrapper->netagent.netagent_domain,
1044 sizeof(new_wrapper->netagent.netagent_domain)) != 0 ||
1045 memcmp(&session->wrapper->netagent.netagent_type, &new_wrapper->netagent.netagent_type,
1046 sizeof(new_wrapper->netagent.netagent_type)) != 0) {
1047 lck_rw_done(&netagent_lock);
1048 NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
1049 if (error_domain == kNetagentErrorDomainPOSIX) {
1050 response_error = EINVAL;
1051 } else if (error_domain == kNetagentErrorDomainUserDefined) {
1052 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
1053 }
1054 return response_error;
1055 }
1056
1057 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
1058 if (session->wrapper->netagent.netagent_data_size == new_wrapper->netagent.netagent_data_size &&
1059 memcmp(&session->wrapper->netagent, &new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
1060 // Agent is exactly identical, don't increment the generation count
1061
1062 // Make a copy of the list of pending clients, and clear the current list
1063 struct netagent_client_list_s pending_triggers_list_copy;
1064 LIST_INIT(&pending_triggers_list_copy);
1065 struct netagent_client *search_client = NULL;
1066 struct netagent_client *temp_client = NULL;
1067 LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
1068 LIST_REMOVE(search_client, client_chain);
1069 LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
1070 }
1071 lck_rw_done(&netagent_lock);
1072
1073 // Update pending client triggers without holding a lock
1074 search_client = NULL;
1075 temp_client = NULL;
1076 LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
1077 necp_force_update_client(search_client->client_id, session->wrapper->netagent.netagent_uuid, session->wrapper->generation);
1078 netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
1079 LIST_REMOVE(search_client, client_chain);
1080 FREE(search_client, M_NETAGENT);
1081 }
1082 NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
1083 *agent_changed = FALSE;
1084 return response_error;
1085 }
1086
1087 new_wrapper->generation = g_next_generation++;
1088 new_wrapper->use_count = session->wrapper->use_count;
1089
1090 if ((new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1091 !(session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1092 netagent_active_count++;
1093 } else if (!(new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1094 (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
1095 netagent_active_count > 0) {
1096 netagent_active_count--;
1097 }
1098
1099 LIST_REMOVE(session->wrapper, master_chain);
1100 netagent_free_wrapper(session->wrapper);
1101 session->wrapper = new_wrapper;
1102 new_wrapper->control_unit = session->control_unit;
1103 new_wrapper->event_handler = session->event_handler;
1104 new_wrapper->event_context = session->event_context;
1105 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
1106 LIST_INIT(&new_wrapper->pending_triggers_list);
1107
1108 NETAGENTLOG0(LOG_DEBUG, "Updated agent");
1109 *agent_changed = TRUE;
1110
1111 lck_rw_done(&netagent_lock);
1112
1113 return response_error;
1114 }
1115
1116 errno_t
1117 netagent_update(netagent_session_t _session, struct netagent *agent)
1118 {
1119 u_int8_t agent_changed;
1120 struct netagent_wrapper *new_wrapper = NULL;
1121 bool should_update_immediately;
1122 uuid_t updated_uuid;
1123
1124 struct netagent_session *session = (struct netagent_session *)_session;
1125 if (session == NULL) {
1126 NETAGENTLOG0(LOG_ERR, "Cannot update agent on NULL session");
1127 return EINVAL;
1128 }
1129
1130 if (agent == NULL) {
1131 NETAGENTLOG0(LOG_ERR, "Cannot register NULL agent");
1132 return EINVAL;
1133 }
1134
1135 if (session->wrapper == NULL) {
1136 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1137 return EINVAL;
1138 }
1139
1140 size_t data_size = agent->netagent_data_size;
1141 if (data_size > NETAGENT_MAX_DATA_SIZE) {
1142 NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1143 return EINVAL;
1144 }
1145
1146 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1147 if (new_wrapper == NULL) {
1148 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1149 return ENOMEM;
1150 }
1151
1152 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1153 __nochk_memcpy(&new_wrapper->netagent, agent, sizeof(struct netagent) + data_size);
1154
1155 uuid_copy(updated_uuid, new_wrapper->netagent.netagent_uuid);
1156 should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1157
1158 errno_t error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1159 if (error == 0) {
1160 netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1161 if (agent_changed == FALSE) {
1162 // The session wrapper does not need the "new_wrapper" as nothing changed
1163 FREE(new_wrapper, M_NETAGENT);
1164 }
1165 } else {
1166 FREE(new_wrapper, M_NETAGENT);
1167 return error;
1168 }
1169
1170 return 0;
1171 }
1172
1173 static errno_t
1174 netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1175 {
1176 struct netagent_wrapper *new_wrapper = NULL;
1177 errno_t response_error = 0;
1178 struct netagent *update_netagent = (struct netagent *)(void *)payload;
1179 u_int8_t agent_changed;
1180 bool should_update_immediately;
1181 uuid_t updated_uuid;
1182
1183 if (session == NULL) {
1184 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1185 response_error = EINVAL;
1186 goto done;
1187 }
1188
1189 if (payload == NULL) {
1190 NETAGENTLOG0(LOG_ERR, "No payload received");
1191 response_error = EINVAL;
1192 goto done;
1193 }
1194
1195 if (session->wrapper == NULL) {
1196 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1197 response_error = ENOENT;
1198 goto done;
1199 }
1200
1201 if (payload_length < sizeof(struct netagent)) {
1202 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1203 payload_length, sizeof(struct netagent));
1204 response_error = EINVAL;
1205 goto done;
1206 }
1207
1208 size_t data_size = update_netagent->netagent_data_size;
1209 if (data_size > NETAGENT_MAX_DATA_SIZE) {
1210 NETAGENTLOG(LOG_ERR, "Update message size (%zu > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1211 response_error = EINVAL;
1212 goto done;
1213 }
1214
1215 if (payload_length != (sizeof(struct netagent) + data_size)) {
1216 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %zu)", (sizeof(struct netagent) + data_size), payload_length);
1217 response_error = EINVAL;
1218 goto done;
1219 }
1220
1221 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1222 if (new_wrapper == NULL) {
1223 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1224 response_error = ENOMEM;
1225 goto done;
1226 }
1227
1228 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1229 __nochk_memcpy(&new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1230
1231 uuid_copy(updated_uuid, new_wrapper->netagent.netagent_uuid);
1232 should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1233
1234 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1235 if (response_error == 0) {
1236 netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1237 if (agent_changed == FALSE) {
1238 // The session wrapper does not need the "new_wrapper" as nothing changed
1239 FREE(new_wrapper, M_NETAGENT);
1240 }
1241 } else {
1242 FREE(new_wrapper, M_NETAGENT);
1243 }
1244
1245 done:
1246 return response_error;
1247 }
1248
1249 static void
1250 netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1251 size_t payload_length, mbuf_t packet, size_t offset)
1252 {
1253 int error;
1254 struct netagent_wrapper *new_wrapper = NULL;
1255 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1256 u_int8_t agent_changed;
1257 uuid_t updated_uuid;
1258 bool should_update_immediately;
1259
1260 if (session == NULL) {
1261 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1262 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1263 goto fail;
1264 }
1265
1266 if (session->wrapper == NULL) {
1267 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1268 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1269 goto fail;
1270 }
1271
1272 if (payload_length < sizeof(struct netagent)) {
1273 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%zu < %zu)",
1274 payload_length, sizeof(struct netagent));
1275 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1276 goto fail;
1277 }
1278
1279 size_t data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1280 if (error || data_size > NETAGENT_MAX_DATA_SIZE) {
1281 NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %zu",
1282 error, data_size);
1283 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1284 goto fail;
1285 }
1286
1287 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1288 if (new_wrapper == NULL) {
1289 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1290 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1291 goto fail;
1292 }
1293
1294 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1295
1296 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, &new_wrapper->netagent);
1297 if (error) {
1298 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1299 FREE(new_wrapper, M_NETAGENT);
1300 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1301 goto fail;
1302 }
1303
1304 uuid_copy(updated_uuid, new_wrapper->netagent.netagent_uuid);
1305 should_update_immediately = (NETAGENT_FLAG_UPDATE_IMMEDIATELY == (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_UPDATE_IMMEDIATELY));
1306
1307 response_error = (u_int32_t)netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainUserDefined);
1308 if (response_error != 0) {
1309 FREE(new_wrapper, M_NETAGENT);
1310 goto fail;
1311 }
1312
1313 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1314 netagent_post_event(updated_uuid, KEV_NETAGENT_UPDATED, agent_changed, should_update_immediately);
1315
1316 if (agent_changed == FALSE) {
1317 // The session wrapper does not need the "new_wrapper" as nothing changed
1318 FREE(new_wrapper, M_NETAGENT);
1319 }
1320
1321 return;
1322 fail:
1323 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1324 }
1325
1326 static void
1327 netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1328 size_t payload_length, mbuf_t packet, size_t offset)
1329 {
1330 #pragma unused(payload_length, packet, offset)
1331 u_int8_t *response = NULL;
1332 u_int8_t *cursor = NULL;
1333 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1334
1335 if (session == NULL) {
1336 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1337 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1338 goto fail;
1339 }
1340
1341 lck_rw_lock_shared(&netagent_lock);
1342
1343 if (session->wrapper == NULL) {
1344 lck_rw_done(&netagent_lock);
1345 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1346 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1347 goto fail;
1348 }
1349
1350 size_t response_size = sizeof(struct netagent_message_header) + sizeof(session->wrapper->netagent)
1351 + session->wrapper->netagent.netagent_data_size;
1352 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
1353 if (response == NULL) {
1354 goto fail;
1355 }
1356
1357 cursor = response;
1358 cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1359 NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1360 response_size - sizeof(struct netagent_message_header));
1361 memcpy(cursor, &session->wrapper->netagent, sizeof(session->wrapper->netagent) +
1362 session->wrapper->netagent.netagent_data_size);
1363
1364 lck_rw_done(&netagent_lock);
1365
1366 if (!netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size)) {
1367 NETAGENTLOG0(LOG_ERR, "Failed to send response");
1368 }
1369 FREE(response, M_NETAGENT);
1370 return;
1371 fail:
1372 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1373 }
1374
1375 errno_t
1376 netagent_assign_nexus(netagent_session_t _session, uuid_t necp_client_uuid,
1377 void *assign_message, size_t assigned_results_length)
1378 {
1379 struct netagent_session *session = (struct netagent_session *)_session;
1380 uuid_t netagent_uuid;
1381 if (session == NULL) {
1382 NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1383 return EINVAL;
1384 }
1385
1386 lck_rw_lock_shared(&netagent_lock);
1387 if (session->wrapper == NULL) {
1388 lck_rw_done(&netagent_lock);
1389 NETAGENTLOG0(LOG_ERR, "Session has no agent");
1390 return ENOENT;
1391 }
1392 uuid_copy(netagent_uuid, session->wrapper->netagent.netagent_uuid);
1393 lck_rw_done(&netagent_lock);
1394
1395 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1396 int error = necp_assign_client_result(netagent_uuid, necp_client_uuid, assign_message, assigned_results_length);
1397 if (error) {
1398 // necp_assign_client_result returns POSIX errors; don't error for ENOENT
1399 NETAGENTLOG((error == ENOENT ? LOG_DEBUG : LOG_ERR), "Client assignment failed: %d", error);
1400 return error;
1401 }
1402
1403 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1404 return 0;
1405 }
1406
1407 errno_t
1408 netagent_update_flow_protoctl_event(netagent_session_t _session,
1409 uuid_t client_id, uint32_t protoctl_event_code,
1410 uint32_t protoctl_event_val, uint32_t protoctl_event_tcp_seq_number)
1411 {
1412 struct netagent_session *session = (struct netagent_session *)_session;
1413 uuid_t netagent_uuid;
1414 int error = 0;
1415
1416 if (session == NULL) {
1417 NETAGENTLOG0(LOG_ERR, "Cannot assign nexus from NULL session");
1418 return EINVAL;
1419 }
1420
1421 lck_rw_lock_shared(&netagent_lock);
1422 if (session->wrapper == NULL) {
1423 lck_rw_done(&netagent_lock);
1424 NETAGENTLOG0(LOG_ERR, "Session has no agent");
1425 return ENOENT;
1426 }
1427 uuid_copy(netagent_uuid, session->wrapper->netagent.netagent_uuid);
1428 lck_rw_done(&netagent_lock);
1429
1430 error = necp_update_flow_protoctl_event(netagent_uuid,
1431 client_id, protoctl_event_code, protoctl_event_val, protoctl_event_tcp_seq_number);
1432
1433 return error;
1434 }
1435
1436 static errno_t
1437 netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1438 size_t payload_length)
1439 {
1440 errno_t response_error = 0;
1441 struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1442 uuid_t client_id;
1443 uuid_t netagent_uuid;
1444 u_int8_t *assigned_results = NULL;
1445
1446 if (session == NULL) {
1447 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1448 response_error = ENOENT;
1449 goto done;
1450 }
1451
1452 if (payload == NULL) {
1453 NETAGENTLOG0(LOG_ERR, "No payload received");
1454 response_error = EINVAL;
1455 goto done;
1456 }
1457
1458 lck_rw_lock_shared(&netagent_lock);
1459 if (session->wrapper == NULL) {
1460 lck_rw_done(&netagent_lock);
1461 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1462 response_error = ENOENT;
1463 goto done;
1464 }
1465
1466 uuid_copy(netagent_uuid, session->wrapper->netagent.netagent_uuid);
1467 lck_rw_done(&netagent_lock);
1468
1469 if (payload_length < sizeof(uuid_t)) {
1470 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1471 response_error = EINVAL;
1472 goto done;
1473 }
1474
1475 memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1476 size_t assigned_results_length = (payload_length - sizeof(client_id));
1477
1478 if (assigned_results_length > 0) {
1479 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1480 if (assigned_results == NULL) {
1481 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1482 response_error = ENOMEM;
1483 goto done;
1484 }
1485 memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1486 }
1487
1488 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1489 response_error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1490 if (response_error) {
1491 // necp_assign_client_result returns POSIX errors
1492 if (assigned_results) {
1493 FREE(assigned_results, M_NETAGENT);
1494 }
1495 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1496 goto done;
1497 }
1498
1499 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1500 done:
1501 return response_error;
1502 }
1503
1504
1505 static void
1506 netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1507 size_t payload_length, mbuf_t packet, size_t offset)
1508 {
1509 int error = 0;
1510 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1511 uuid_t client_id;
1512 uuid_t netagent_uuid;
1513 u_int8_t *assigned_results = NULL;
1514
1515 if (session == NULL) {
1516 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1517 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1518 goto fail;
1519 }
1520
1521 lck_rw_lock_shared(&netagent_lock);
1522 if (session->wrapper == NULL) {
1523 lck_rw_done(&netagent_lock);
1524 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1525 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1526 goto fail;
1527 }
1528 uuid_copy(netagent_uuid, session->wrapper->netagent.netagent_uuid);
1529 lck_rw_done(&netagent_lock);
1530
1531 if (payload_length < sizeof(uuid_t)) {
1532 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1533 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1534 goto fail;
1535 }
1536
1537 error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1538 if (error) {
1539 NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1540 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1541 goto fail;
1542 }
1543
1544 size_t assigned_results_length = (payload_length - sizeof(client_id));
1545 if (assigned_results_length > 0) {
1546 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1547 if (assigned_results == NULL) {
1548 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1549 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1550 goto fail;
1551 }
1552
1553 error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1554 if (error) {
1555 FREE(assigned_results, M_NETAGENT);
1556 NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1557 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1558 goto fail;
1559 }
1560 }
1561
1562 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1563 error = necp_assign_client_result(netagent_uuid, client_id, assigned_results, assigned_results_length);
1564 if (error) {
1565 if (assigned_results) {
1566 FREE(assigned_results, M_NETAGENT);
1567 }
1568 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1569 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1570 goto fail;
1571 }
1572
1573 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1574 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1575 return;
1576 fail:
1577 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1578 }
1579
1580 errno_t
1581 netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1582 {
1583 errno_t response_error = 0;
1584 uint64_t use_count = 0;
1585
1586 if (session == NULL) {
1587 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1588 response_error = ENOENT;
1589 goto done;
1590 }
1591
1592 if (payload == NULL) {
1593 NETAGENTLOG0(LOG_ERR, "No payload received");
1594 response_error = EINVAL;
1595 goto done;
1596 }
1597
1598 if (payload_length != sizeof(use_count)) {
1599 NETAGENTLOG(LOG_ERR, "Payload length is invalid (%lu)", payload_length);
1600 response_error = EINVAL;
1601 goto done;
1602 }
1603
1604 memcpy(&use_count, payload, sizeof(use_count));
1605
1606 lck_rw_lock_shared(&netagent_lock);
1607
1608 if (session->wrapper == NULL) {
1609 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1610 response_error = ENOENT;
1611 lck_rw_done(&netagent_lock);
1612 goto done;
1613 }
1614
1615 session->wrapper->use_count = use_count;
1616
1617 lck_rw_done(&netagent_lock);
1618
1619 done:
1620 return response_error;
1621 }
1622
1623 errno_t
1624 netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1625 {
1626 errno_t response_error = 0;
1627 uint64_t use_count = 0;
1628
1629 if (session == NULL) {
1630 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1631 response_error = ENOENT;
1632 goto done;
1633 }
1634
1635 if (buffer == NULL) {
1636 NETAGENTLOG0(LOG_ERR, "No payload received");
1637 response_error = EINVAL;
1638 goto done;
1639 }
1640
1641 if (*buffer_length != sizeof(use_count)) {
1642 NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length);
1643 response_error = EINVAL;
1644 goto done;
1645 }
1646
1647 lck_rw_lock_shared(&netagent_lock);
1648
1649 if (session->wrapper == NULL) {
1650 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1651 response_error = ENOENT;
1652 lck_rw_done(&netagent_lock);
1653 goto done;
1654 }
1655
1656 use_count = session->wrapper->use_count;
1657 lck_rw_done(&netagent_lock);
1658
1659 memcpy(buffer, &use_count, sizeof(use_count));
1660 *buffer_length = sizeof(use_count);
1661
1662 done:
1663 return response_error;
1664 }
1665
1666 static struct netagent_wrapper *
1667 netagent_find_agent_with_uuid(uuid_t uuid)
1668 {
1669 struct netagent_wrapper *search_netagent = NULL;
1670
1671 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1672 if (uuid_compare(search_netagent->netagent.netagent_uuid, uuid) == 0) {
1673 return search_netagent;
1674 }
1675 }
1676
1677 return NULL;
1678 }
1679
1680 void
1681 netagent_post_updated_interfaces(uuid_t uuid)
1682 {
1683 struct netagent_wrapper *wrapper = NULL;
1684 lck_rw_lock_shared(&netagent_lock);
1685 wrapper = netagent_find_agent_with_uuid(uuid);
1686 lck_rw_done(&netagent_lock);
1687
1688 if (wrapper != NULL) {
1689 netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, TRUE, false);
1690 } else {
1691 NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
1692 }
1693
1694 return;
1695 }
1696
1697 static u_int32_t
1698 netagent_dump_get_data_size_locked()
1699 {
1700 struct netagent_wrapper *search_netagent = NULL;
1701 u_int32_t total_netagent_data_size = 0;
1702 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1703 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1704 total_netagent_data_size += sizeof(search_netagent->netagent.netagent_uuid);
1705 }
1706 return total_netagent_data_size;
1707 }
1708
1709 static void
1710 netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
1711 {
1712 size_t response_size = 0;
1713 u_int8_t *cursor = NULL;
1714 struct netagent_wrapper *search_netagent = NULL;
1715
1716 response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
1717 cursor = buffer;
1718 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1719 memcpy(cursor, search_netagent->netagent.netagent_uuid, sizeof(search_netagent->netagent.netagent_uuid));
1720 cursor += sizeof(search_netagent->netagent.netagent_uuid);
1721 }
1722 }
1723
1724 int
1725 netagent_ioctl(u_long cmd, caddr_t data)
1726 {
1727 int error = 0;
1728
1729 switch (cmd) {
1730 case SIOCGIFAGENTLIST32:
1731 case SIOCGIFAGENTLIST64: {
1732 /* Check entitlement if the client requests agent dump */
1733 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
1734 if (cred_result != 0) {
1735 NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
1736 return EINVAL;
1737 }
1738 break;
1739 }
1740 default:
1741 break;
1742 }
1743
1744 lck_rw_lock_shared(&netagent_lock);
1745 switch (cmd) {
1746 case SIOCGIFAGENTDATA32: {
1747 struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
1748 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
1749 if (wrapper == NULL) {
1750 error = ENOENT;
1751 break;
1752 }
1753 uuid_copy(ifsir32->netagent_uuid, wrapper->netagent.netagent_uuid);
1754 memcpy(ifsir32->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir32->netagent_domain));
1755 memcpy(ifsir32->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir32->netagent_type));
1756 memcpy(ifsir32->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir32->netagent_desc));
1757 ifsir32->netagent_flags = wrapper->netagent.netagent_flags;
1758 if (ifsir32->netagent_data_size == 0) {
1759 // First pass, client wants data size
1760 ifsir32->netagent_data_size = wrapper->netagent.netagent_data_size;
1761 } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
1762 ifsir32->netagent_data_size == wrapper->netagent.netagent_data_size) {
1763 // Second pass, client wants data buffer filled out
1764 error = copyout(wrapper->netagent.netagent_data, ifsir32->netagent_data, wrapper->netagent.netagent_data_size);
1765 } else {
1766 error = EINVAL;
1767 }
1768 break;
1769 }
1770 case SIOCGIFAGENTDATA64: {
1771 struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
1772 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
1773 if (wrapper == NULL) {
1774 error = ENOENT;
1775 break;
1776 }
1777 uuid_copy(ifsir64->netagent_uuid, wrapper->netagent.netagent_uuid);
1778 memcpy(ifsir64->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir64->netagent_domain));
1779 memcpy(ifsir64->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir64->netagent_type));
1780 memcpy(ifsir64->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir64->netagent_desc));
1781 ifsir64->netagent_flags = wrapper->netagent.netagent_flags;
1782 if (ifsir64->netagent_data_size == 0) {
1783 // First pass, client wants data size
1784 ifsir64->netagent_data_size = wrapper->netagent.netagent_data_size;
1785 } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
1786 ifsir64->netagent_data_size == wrapper->netagent.netagent_data_size) {
1787 // Second pass, client wants data buffer filled out
1788 error = copyout(wrapper->netagent.netagent_data, ifsir64->netagent_data, wrapper->netagent.netagent_data_size);
1789 } else {
1790 error = EINVAL;
1791 }
1792 break;
1793 }
1794 case SIOCGIFAGENTLIST32: {
1795 struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
1796 if (ifsir32->data_size == 0) {
1797 // First pass, client wants data size
1798 ifsir32->data_size = netagent_dump_get_data_size_locked();
1799 } else if (ifsir32->data != USER_ADDR_NULL &&
1800 ifsir32->data_size > 0 &&
1801 ifsir32->data_size == netagent_dump_get_data_size_locked()) {
1802 // Second pass, client wants data buffer filled out
1803 u_int8_t *response = NULL;
1804 MALLOC(response, u_int8_t *, ifsir32->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1805 if (response == NULL) {
1806 error = ENOMEM;
1807 break;
1808 }
1809
1810 netagent_dump_copy_data_locked(response, ifsir32->data_size);
1811 error = copyout(response, ifsir32->data, ifsir32->data_size);
1812 FREE(response, M_NETAGENT);
1813 } else {
1814 error = EINVAL;
1815 }
1816 break;
1817 }
1818 case SIOCGIFAGENTLIST64: {
1819 struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
1820 if (ifsir64->data_size == 0) {
1821 // First pass, client wants data size
1822 ifsir64->data_size = netagent_dump_get_data_size_locked();
1823 } else if (ifsir64->data != USER_ADDR_NULL &&
1824 ifsir64->data_size > 0 &&
1825 ifsir64->data_size == netagent_dump_get_data_size_locked()) {
1826 // Second pass, client wants data buffer filled out
1827 u_int8_t *response = NULL;
1828 MALLOC(response, u_int8_t *, ifsir64->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1829 if (response == NULL) {
1830 error = ENOMEM;
1831 break;
1832 }
1833
1834 netagent_dump_copy_data_locked(response, ifsir64->data_size);
1835 error = copyout(response, ifsir64->data, ifsir64->data_size);
1836 FREE(response, M_NETAGENT);
1837 } else {
1838 error = EINVAL;
1839 }
1840 break;
1841 }
1842 default: {
1843 error = EINVAL;
1844 break;
1845 }
1846 }
1847 lck_rw_done(&netagent_lock);
1848 return error;
1849 }
1850
1851 u_int32_t
1852 netagent_get_flags(uuid_t uuid)
1853 {
1854 u_int32_t flags = 0;
1855 lck_rw_lock_shared(&netagent_lock);
1856 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1857 if (wrapper != NULL) {
1858 flags = wrapper->netagent.netagent_flags;
1859 } else {
1860 NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
1861 }
1862 lck_rw_done(&netagent_lock);
1863
1864 return flags;
1865 }
1866
1867 errno_t
1868 netagent_set_flags(uuid_t uuid, u_int32_t flags)
1869 {
1870 errno_t error = 0;
1871 lck_rw_lock_exclusive(&netagent_lock);
1872 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1873 if (wrapper != NULL) {
1874 wrapper->netagent.netagent_flags = flags;
1875 } else {
1876 NETAGENTLOG0(LOG_DEBUG,
1877 "Attempt to set flags for invalid netagent");
1878 error = ENOENT;
1879 }
1880 lck_rw_done(&netagent_lock);
1881
1882 return error;
1883 }
1884
1885 u_int32_t
1886 netagent_get_generation(uuid_t uuid)
1887 {
1888 u_int32_t generation = 0;
1889 lck_rw_lock_shared(&netagent_lock);
1890 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1891 if (wrapper != NULL) {
1892 generation = wrapper->generation;
1893 } else {
1894 NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
1895 }
1896 lck_rw_done(&netagent_lock);
1897
1898 return generation;
1899 }
1900
1901 bool
1902 netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
1903 {
1904 bool found = FALSE;
1905 if (domain == NULL || type == NULL) {
1906 NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
1907 return FALSE;
1908 }
1909
1910 lck_rw_lock_shared(&netagent_lock);
1911 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1912 if (wrapper != NULL) {
1913 found = TRUE;
1914 memcpy(domain, wrapper->netagent.netagent_domain, NETAGENT_DOMAINSIZE);
1915 memcpy(type, wrapper->netagent.netagent_type, NETAGENT_TYPESIZE);
1916 } else {
1917 NETAGENTLOG0(LOG_ERR, "Type requested for invalid netagent");
1918 }
1919 lck_rw_done(&netagent_lock);
1920
1921 return found;
1922 }
1923
1924 int
1925 netagent_kernel_trigger(uuid_t uuid)
1926 {
1927 int error = 0;
1928
1929 lck_rw_lock_shared(&netagent_lock);
1930 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1931 if (wrapper == NULL) {
1932 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
1933 error = ENOENT;
1934 goto done;
1935 }
1936
1937 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
1938 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
1939 // Agent does not accept kernel triggers
1940 error = EINVAL;
1941 goto done;
1942 }
1943
1944 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1945 // Agent already active
1946 NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
1947 error = 0;
1948 goto done;
1949 }
1950
1951 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
1952 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
1953 done:
1954 lck_rw_done(&netagent_lock);
1955 return error;
1956 }
1957
1958 int
1959 netagent_client_message_with_params(uuid_t agent_uuid,
1960 uuid_t necp_client_uuid,
1961 pid_t pid,
1962 void *handle,
1963 u_int8_t message_type,
1964 struct necp_client_agent_parameters *parameters,
1965 void **assigned_results,
1966 size_t *assigned_results_length)
1967 {
1968 int error = 0;
1969
1970 if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
1971 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
1972 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
1973 message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
1974 message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS &&
1975 message_type != NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
1976 NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
1977 return EINVAL;
1978 }
1979
1980 lck_rw_lock_shared(&netagent_lock);
1981 bool should_unlock = TRUE;
1982 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1983 if (wrapper == NULL) {
1984 NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
1985 error = ENOENT;
1986 goto done;
1987 }
1988
1989 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1990 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1991 // Agent does not accept user triggers
1992 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1993 error = ENOTSUP;
1994
1995
1996 pid_t report_pid = 0;
1997 uuid_t report_proc_uuid = {};
1998 if (parameters != NULL) {
1999 report_pid = parameters->u.nexus_request.epid;
2000 uuid_copy(report_proc_uuid, parameters->u.nexus_request.euuid);
2001 } else {
2002 struct proc *p = current_proc();
2003 if (p != NULL) {
2004 report_pid = proc_pid(p);
2005 proc_getexecutableuuid(p, report_proc_uuid, sizeof(report_proc_uuid));
2006 }
2007 }
2008 netagent_send_cellular_failed_event(wrapper, report_pid, report_proc_uuid);
2009 goto done;
2010 }
2011 } else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
2012 message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS ||
2013 message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2014 bool is_nexus_agent = ((wrapper->netagent.netagent_flags &
2015 (NETAGENT_FLAG_NEXUS_PROVIDER |
2016 NETAGENT_FLAG_NEXUS_LISTENER |
2017 NETAGENT_FLAG_CUSTOM_IP_NEXUS |
2018 NETAGENT_FLAG_CUSTOM_ETHER_NEXUS |
2019 NETAGENT_FLAG_INTERPOSE_NEXUS)) != 0);
2020 if (!is_nexus_agent) {
2021 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
2022 // Agent is not a nexus provider
2023 error = EINVAL;
2024 goto done;
2025 }
2026
2027 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
2028 // Agent not active
2029 NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
2030 error = EINVAL;
2031 goto done;
2032 }
2033 }
2034
2035 if (wrapper->control_unit == 0) {
2036 if (wrapper->event_handler == NULL) {
2037 // No event handler registered for kernel agent
2038 error = EINVAL;
2039 } else {
2040 // We hold the shared lock during the event handler callout, so it is expected
2041 // that the event handler will not lead to any registrations or unregistrations
2042 // of network agents.
2043 error = wrapper->event_handler(message_type, necp_client_uuid, pid, handle,
2044 wrapper->event_context, parameters,
2045 assigned_results, assigned_results_length);
2046 if (error != 0) {
2047 VERIFY(assigned_results == NULL || *assigned_results == NULL);
2048 VERIFY(assigned_results_length == NULL || *assigned_results_length == 0);
2049 }
2050 }
2051 } else {
2052 // ABORT_NEXUS is kernel-private, so translate it for userspace nexus
2053 if (message_type == NETAGENT_MESSAGE_TYPE_ABORT_NEXUS) {
2054 message_type = NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS;
2055 }
2056
2057 error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
2058 if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2059 if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
2060 // Grab the lock exclusively to add a pending client to the list
2061 struct netagent_client *new_pending_client = NULL;
2062 MALLOC(new_pending_client, struct netagent_client *, sizeof(*new_pending_client), M_NETAGENT, M_WAITOK);
2063 if (new_pending_client == NULL) {
2064 NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
2065 } else {
2066 uuid_copy(new_pending_client->client_id, necp_client_uuid);
2067 if (parameters != NULL) {
2068 new_pending_client->client_pid = parameters->u.nexus_request.epid;
2069 uuid_copy(new_pending_client->client_proc_uuid, parameters->u.nexus_request.euuid);
2070 } else {
2071 struct proc *p = current_proc();
2072 if (p != NULL) {
2073 new_pending_client->client_pid = proc_pid(p);
2074 proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
2075 }
2076 }
2077 LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
2078 }
2079 } else {
2080 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
2081 should_unlock = FALSE;
2082 }
2083 }
2084 }
2085 NETAGENTLOG(((error && error != ENOENT) ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
2086 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
2087 uuid_string_t uuid_str;
2088 uuid_unparse(agent_uuid, uuid_str);
2089 NETAGENTLOG(LOG_NOTICE, "Triggered network agent %s, error = %d", uuid_str, error);
2090 }
2091 done:
2092 if (should_unlock) {
2093 lck_rw_done(&netagent_lock);
2094 }
2095 return error;
2096 }
2097
2098 int
2099 netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, pid_t pid, void *handle, u_int8_t message_type)
2100 {
2101 return netagent_client_message_with_params(agent_uuid, necp_client_uuid, pid, handle, message_type, NULL, NULL, NULL);
2102 }
2103
2104 int
2105 netagent_use(uuid_t agent_uuid, uint64_t *out_use_count)
2106 {
2107 int error = 0;
2108
2109 lck_rw_lock_exclusive(&netagent_lock);
2110 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2111 if (wrapper == NULL) {
2112 NETAGENTLOG0(LOG_ERR, "netagent_assert: Requested netagent UUID is not registered");
2113 error = ENOENT;
2114 goto done;
2115 }
2116
2117 uint64_t current_count = wrapper->use_count;
2118 wrapper->use_count++;
2119
2120 if (out_use_count != NULL) {
2121 *out_use_count = current_count;
2122 }
2123
2124 done:
2125 lck_rw_done(&netagent_lock);
2126 return error;
2127 }
2128
2129 int
2130 netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
2131 {
2132 int error = 0;
2133
2134 lck_rw_lock_shared(&netagent_lock);
2135 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2136 if (wrapper == NULL) {
2137 NETAGENTLOG0(LOG_DEBUG, "Requested netagent for nexus instance could not be found");
2138 error = ENOENT;
2139 goto done;
2140 }
2141
2142 u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent.netagent_data_size);
2143 if (user_size < total_size) {
2144 NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
2145 error = EINVAL;
2146 goto done;
2147 }
2148
2149 error = copyout(&wrapper->netagent, user_addr, total_size);
2150
2151 NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
2152 done:
2153 lck_rw_done(&netagent_lock);
2154 return error;
2155 }
2156
2157 int
2158 netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
2159 {
2160 #pragma unused(p, retval)
2161 uuid_t agent_uuid = {};
2162 int error = 0;
2163
2164 if (uap == NULL) {
2165 NETAGENTLOG0(LOG_ERR, "uap == NULL");
2166 return EINVAL;
2167 }
2168
2169 if (uap->agent_uuid) {
2170 if (uap->agent_uuidlen != sizeof(uuid_t)) {
2171 NETAGENTLOG(LOG_ERR, "Incorrect length (got %zu, expected %lu)",
2172 (size_t)uap->agent_uuidlen, sizeof(uuid_t));
2173 return ERANGE;
2174 }
2175
2176 error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
2177 if (error) {
2178 NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
2179 return error;
2180 }
2181 }
2182
2183 if (uuid_is_null(agent_uuid)) {
2184 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
2185 return EINVAL;
2186 }
2187
2188 lck_rw_lock_shared(&netagent_lock);
2189 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
2190 if (wrapper == NULL) {
2191 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
2192 error = ENOENT;
2193 goto done;
2194 }
2195
2196 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
2197 // Agent does not accept triggers
2198 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
2199 error = ENOTSUP;
2200 goto done;
2201 }
2202
2203 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
2204 // Agent already active
2205 NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
2206 error = 0;
2207 goto done;
2208 }
2209
2210 error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
2211 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
2212 done:
2213 lck_rw_done(&netagent_lock);
2214 return error;
2215 }