]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/network_agent.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / bsd / net / network_agent.c
1 /*
2 * Copyright (c) 2014 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 <libkern/OSMalloc.h>
36 #include <sys/kernel.h>
37 #include <sys/kern_control.h>
38 #include <sys/mbuf.h>
39 #include <sys/kpi_mbuf.h>
40 #include <sys/sysctl.h>
41 #include <sys/priv.h>
42 #include <sys/kern_event.h>
43 #include <sys/sysproto.h>
44 #include <net/network_agent.h>
45 #include <net/if_var.h>
46 #include <net/necp.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 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
64 } while (0)
65
66 #define NETAGENTLOG0(level, msg) do { \
67 if (level <= netagent_debug) \
68 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: %s\n", __FUNCTION__, msg); \
69 } while (0)
70
71 struct netagent_client {
72 LIST_ENTRY(netagent_client) client_chain;
73 uuid_t client_id;
74 uuid_t client_proc_uuid;
75 pid_t client_pid;
76 };
77
78 LIST_HEAD(netagent_client_list_s, netagent_client);
79
80 struct netagent_wrapper {
81 LIST_ENTRY(netagent_wrapper) master_chain;
82 u_int32_t control_unit;
83 u_int32_t generation;
84 struct netagent_client_list_s pending_triggers_list;
85 struct netagent netagent;
86 };
87
88 struct netagent_session {
89 u_int32_t control_unit;
90 struct netagent_wrapper *wrapper;
91 };
92
93 typedef enum {
94 kNetagentErrorDomainPOSIX = 0,
95 kNetagentErrorDomainUserDefined = 1,
96 } netagent_error_domain_t;
97
98 static LIST_HEAD(_netagent_list, netagent_wrapper) master_netagent_list;
99
100 // Protected by netagent_lock
101 static u_int32_t g_next_generation = 1;
102
103 static kern_ctl_ref netagent_kctlref;
104 static u_int32_t netagent_family;
105 static OSMallocTag netagent_malloc_tag;
106 static lck_grp_attr_t *netagent_grp_attr = NULL;
107 static lck_attr_t *netagent_mtx_attr = NULL;
108 static lck_grp_t *netagent_mtx_grp = NULL;
109 decl_lck_rw_data(static, netagent_lock);
110
111 static errno_t netagent_register_control(void);
112 static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
113 void **unitinfo);
114 static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
115 static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
116 mbuf_t m, int flags);
117 static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
118 static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
119 int opt, void *data, size_t *len);
120 static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
121 int opt, void *data, size_t len);
122
123 static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
124
125 static struct netagent_session *netagent_create_session(u_int32_t control_unit);
126 static void netagent_delete_session(struct netagent_session *session);
127
128 // Register
129 static void netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
130 u_int32_t payload_length, mbuf_t packet, int offset);
131 static errno_t netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
132 u_int32_t payload_length);
133
134 // Unregister
135 static void netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
136 u_int32_t payload_length, mbuf_t packet, int offset);
137 static errno_t netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
138 u_int32_t payload_length);
139
140 // Update
141 static void netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
142 u_int32_t payload_length, mbuf_t packet, int offset);
143 static errno_t netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload,
144 u_int32_t payload_length);
145
146 // Assign nexus
147 static void netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
148 u_int32_t payload_length, mbuf_t packet, int offset);
149 static errno_t netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
150 u_int32_t payload_length);
151
152 static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
153 u_int32_t payload_length, mbuf_t packet, int offset);
154
155 static struct netagent_wrapper *netagent_find_agent_with_uuid(uuid_t uuid);
156
157 errno_t
158 netagent_init(void)
159 {
160 errno_t result = 0;
161
162 result = netagent_register_control();
163 if (result != 0) {
164 goto done;
165 }
166
167 netagent_grp_attr = lck_grp_attr_alloc_init();
168 if (netagent_grp_attr == NULL) {
169 NETAGENTLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed");
170 result = ENOMEM;
171 goto done;
172 }
173
174 netagent_mtx_grp = lck_grp_alloc_init(NETAGENT_CONTROL_NAME, netagent_grp_attr);
175 if (netagent_mtx_grp == NULL) {
176 NETAGENTLOG0(LOG_ERR, "lck_grp_alloc_init failed");
177 result = ENOMEM;
178 goto done;
179 }
180
181 netagent_mtx_attr = lck_attr_alloc_init();
182 if (netagent_mtx_attr == NULL) {
183 NETAGENTLOG0(LOG_ERR, "lck_attr_alloc_init failed");
184 result = ENOMEM;
185 goto done;
186 }
187
188 lck_rw_init(&netagent_lock, netagent_mtx_grp, netagent_mtx_attr);
189
190 LIST_INIT(&master_netagent_list);
191
192 done:
193 if (result != 0) {
194 if (netagent_mtx_attr != NULL) {
195 lck_attr_free(netagent_mtx_attr);
196 netagent_mtx_attr = NULL;
197 }
198 if (netagent_mtx_grp != NULL) {
199 lck_grp_free(netagent_mtx_grp);
200 netagent_mtx_grp = NULL;
201 }
202 if (netagent_grp_attr != NULL) {
203 lck_grp_attr_free(netagent_grp_attr);
204 netagent_grp_attr = NULL;
205 }
206 if (netagent_kctlref != NULL) {
207 ctl_deregister(netagent_kctlref);
208 netagent_kctlref = NULL;
209 }
210 }
211 return (result);
212 }
213
214 static errno_t
215 netagent_register_control(void)
216 {
217 struct kern_ctl_reg kern_ctl;
218 errno_t result = 0;
219
220 // Create a tag to allocate memory
221 netagent_malloc_tag = OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME, OSMT_DEFAULT);
222
223 // Find a unique value for our interface family
224 result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
225 if (result != 0) {
226 NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
227 return (result);
228 }
229
230 bzero(&kern_ctl, sizeof(kern_ctl));
231 strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
232 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
233 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
234 kern_ctl.ctl_sendsize = 64 * 1024;
235 kern_ctl.ctl_recvsize = 64 * 1024;
236 kern_ctl.ctl_connect = netagent_ctl_connect;
237 kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
238 kern_ctl.ctl_send = netagent_ctl_send;
239 kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
240 kern_ctl.ctl_setopt = netagent_ctl_setopt;
241 kern_ctl.ctl_getopt = netagent_ctl_getopt;
242
243 result = ctl_register(&kern_ctl, &netagent_kctlref);
244 if (result != 0) {
245 NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
246 return (result);
247 }
248
249 return (0);
250 }
251
252 static errno_t
253 netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
254 {
255 #pragma unused(kctlref)
256 *unitinfo = netagent_create_session(sac->sc_unit);
257 if (*unitinfo == NULL) {
258 // Could not allocate session
259 return (ENOBUFS);
260 }
261
262 return (0);
263 }
264
265 static errno_t
266 netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
267 {
268 #pragma unused(kctlref, unit)
269 struct netagent_session *session = (struct netagent_session *)unitinfo;
270 if (session != NULL) {
271 netagent_delete_session(session);
272 }
273
274 return (0);
275 }
276
277 // Kernel events
278 static void
279 netagent_post_event(uuid_t agent_uuid, u_int32_t event_code, bool update_necp)
280 {
281 if (update_necp) {
282 necp_update_all_clients();
283 }
284
285 struct kev_msg ev_msg;
286 memset(&ev_msg, 0, sizeof(ev_msg));
287
288 struct kev_netagent_data event_data;
289
290 ev_msg.vendor_code = KEV_VENDOR_APPLE;
291 ev_msg.kev_class = KEV_NETWORK_CLASS;
292 ev_msg.kev_subclass = KEV_NETAGENT_SUBCLASS;
293 ev_msg.event_code = event_code;
294
295 uuid_copy(event_data.netagent_uuid, agent_uuid);
296 ev_msg.dv[0].data_ptr = &event_data;
297 ev_msg.dv[0].data_length = sizeof(event_data);
298
299 kev_post_msg(&ev_msg);
300 }
301
302 // Message handling
303 static u_int8_t *
304 netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
305 u_int32_t message_id, u_int32_t error, u_int32_t payload_length)
306 {
307 ((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
308 ((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
309 ((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
310 ((struct netagent_message_header *)(void *)buffer)->message_error = error;
311 ((struct netagent_message_header *)(void *)buffer)->message_payload_length = payload_length;
312 return (buffer + sizeof(struct netagent_message_header));
313 }
314
315 static int
316 netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
317 {
318 if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
319 return (EINVAL);
320 }
321
322 return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
323 }
324
325 static int
326 netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int32_t trigger_type)
327 {
328 int error = 0;
329 struct netagent_trigger_message *trigger_message = NULL;
330 u_int8_t *trigger = NULL;
331 size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
332
333 MALLOC(trigger, u_int8_t *, trigger_size, M_NETAGENT, M_WAITOK);
334 if (trigger == NULL) {
335 return (ENOMEM);
336 }
337
338 (void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
339
340 trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
341 trigger_message->trigger_flags = flags;
342 if (p != NULL) {
343 trigger_message->trigger_pid = proc_pid(p);
344 proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
345 } else {
346 trigger_message->trigger_pid = 0;
347 uuid_clear(trigger_message->trigger_proc_uuid);
348 }
349
350 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)trigger, trigger_size))) {
351 NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
352 }
353
354 FREE(trigger, M_NETAGENT);
355 return (error);
356 }
357
358 static int
359 netagent_send_client_message(struct netagent_wrapper *wrapper, uuid_t client_id, u_int8_t message_type)
360 {
361 int error = 0;
362 struct netagent_client_message *client_message = NULL;
363 u_int8_t *message = NULL;
364 size_t message_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_client_message);
365
366 MALLOC(message, u_int8_t *, message_size, M_NETAGENT, M_WAITOK);
367 if (message == NULL) {
368 return (ENOMEM);
369 }
370
371 (void)netagent_buffer_write_message_header(message, message_type, 0, 0, 0, sizeof(struct netagent_client_message));
372
373 client_message = (struct netagent_client_message *)(void *)(message + sizeof(struct netagent_message_header));
374 uuid_copy(client_message->client_id, client_id);
375
376 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)message, message_size))) {
377 NETAGENTLOG(LOG_ERR, "Failed to send client message %d on control unit %d", message_type, wrapper->control_unit);
378 }
379
380 FREE(message, M_NETAGENT);
381 return (error);
382 }
383
384 static int
385 netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
386 {
387 int error = 0;
388 u_int8_t *response = NULL;
389 size_t response_size = sizeof(struct netagent_message_header);
390 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
391 if (response == NULL) {
392 return (ENOMEM);
393 }
394 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
395
396 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
397 NETAGENTLOG0(LOG_ERR, "Failed to send response");
398 }
399
400 FREE(response, M_NETAGENT);
401 return (error);
402 }
403
404 static int
405 netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
406 u_int32_t message_id, u_int32_t error_code)
407 {
408 int error = 0;
409 u_int8_t *response = NULL;
410 size_t response_size = sizeof(struct netagent_message_header);
411 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
412 if (response == NULL) {
413 return (ENOMEM);
414 }
415 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
416 message_id, error_code, 0);
417
418 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
419 NETAGENTLOG0(LOG_ERR, "Failed to send response");
420 }
421
422 FREE(response, M_NETAGENT);
423 return (error);
424 }
425
426 static errno_t
427 netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
428 {
429 #pragma unused(kctlref, unit, flags)
430 struct netagent_session *session = (struct netagent_session *)unitinfo;
431 struct netagent_message_header header;
432 int error = 0;
433
434 if (session == NULL) {
435 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
436 error = EINVAL;
437 goto done;
438 }
439
440 if (mbuf_pkthdr_len(packet) < sizeof(header)) {
441 NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
442 mbuf_pkthdr_len(packet), sizeof(header));
443 error = EINVAL;
444 goto done;
445 }
446
447 error = mbuf_copydata(packet, 0, sizeof(header), &header);
448 if (error) {
449 NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
450 error = ENOBUFS;
451 goto done;
452 }
453
454 switch (header.message_type) {
455 case NETAGENT_MESSAGE_TYPE_REGISTER: {
456 netagent_handle_register_message(session, header.message_id, header.message_payload_length,
457 packet, sizeof(header));
458 break;
459 }
460 case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
461 netagent_handle_unregister_message(session, header.message_id, header.message_payload_length,
462 packet, sizeof(header));
463 break;
464 }
465 case NETAGENT_MESSAGE_TYPE_UPDATE: {
466 netagent_handle_update_message(session, header.message_id, header.message_payload_length,
467 packet, sizeof(header));
468 break;
469 }
470 case NETAGENT_MESSAGE_TYPE_GET: {
471 netagent_handle_get(session, header.message_id, header.message_payload_length,
472 packet, sizeof(header));
473 break;
474 }
475 case NETAGENT_MESSAGE_TYPE_ASSERT: {
476 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_ASSERT no longer supported");
477 break;
478 }
479 case NETAGENT_MESSAGE_TYPE_UNASSERT: {
480 NETAGENTLOG0(LOG_ERR, "NETAGENT_MESSAGE_TYPE_UNASSERT no longer supported");
481 break;
482 }
483 case NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS: {
484 netagent_handle_assign_nexus_message(session, header.message_id, header.message_payload_length,
485 packet, sizeof(header));
486 break;
487 }
488 default: {
489 NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
490 netagent_send_error_response(session, header.message_type, header.message_id,
491 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
492 break;
493 }
494 }
495
496 done:
497 mbuf_freem(packet);
498 return (error);
499 }
500
501 static void
502 netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
503 {
504 #pragma unused(kctlref, unit, unitinfo, flags)
505 return;
506 }
507
508 static errno_t
509 netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
510 void *data, size_t *len)
511 {
512 #pragma unused(kctlref, unit, unitinfo, opt, data, len)
513 return (0);
514 }
515
516 static errno_t
517 netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
518 void *data, size_t len)
519 {
520 #pragma unused(kctlref, unit)
521 struct netagent_session *session = (struct netagent_session *)unitinfo;
522 errno_t error;
523
524 if (session == NULL) {
525 NETAGENTLOG0(LOG_ERR, "Received a NULL session");
526 error = EINVAL;
527 goto done;
528 }
529
530 switch (opt) {
531 case NETAGENT_OPTION_TYPE_REGISTER: {
532 NETAGENTLOG0(LOG_DEBUG, "Request for registration");
533 error = netagent_handle_register_setopt(session, data, len);
534 }
535 break;
536 case NETAGENT_OPTION_TYPE_UPDATE: {
537 NETAGENTLOG0(LOG_DEBUG, "Request for update");
538 error = netagent_handle_update_setopt(session, data, len);
539 }
540 break;
541 case NETAGENT_OPTION_TYPE_UNREGISTER: {
542 NETAGENTLOG0(LOG_DEBUG, "Request for unregistration");
543 error = netagent_handle_unregister_setopt(session, data, len);
544 }
545 break;
546 case NETAGENT_OPTION_TYPE_ASSIGN_NEXUS: {
547 NETAGENTLOG0(LOG_DEBUG, "Request for assigning nexus");
548 error = netagent_handle_assign_nexus_setopt(session, data, len);
549 }
550 break;
551 default:
552 NETAGENTLOG0(LOG_ERR, "Received unknown option");
553 error = ENOPROTOOPT;
554 break;
555 }
556
557 done:
558 return (error);
559 }
560
561 // Session Management
562 static struct netagent_session *
563 netagent_create_session(u_int32_t control_unit)
564 {
565 struct netagent_session *new_session = NULL;
566
567 MALLOC(new_session, struct netagent_session *, sizeof(*new_session), M_NETAGENT, M_WAITOK);
568 if (new_session == NULL) {
569 goto done;
570 }
571 NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
572 memset(new_session, 0, sizeof(*new_session));
573 new_session->control_unit = control_unit;
574 new_session->wrapper = NULL;
575 done:
576 return (new_session);
577 }
578
579 static void
580 netagent_free_wrapper(struct netagent_wrapper *wrapper)
581 {
582 // Free any pending client triggers
583 struct netagent_client *search_client = NULL;
584 struct netagent_client *temp_client = NULL;
585 LIST_FOREACH_SAFE(search_client, &wrapper->pending_triggers_list, client_chain, temp_client) {
586 LIST_REMOVE(search_client, client_chain);
587 FREE(search_client, M_NETAGENT);
588 }
589
590 // Free wrapper itself
591 FREE(wrapper, M_NETAGENT);
592 }
593
594 static void
595 netagent_unregister_session_wrapper(struct netagent_session *session)
596 {
597 bool unregistered = FALSE;
598 uuid_t unregistered_uuid;
599 struct netagent_wrapper *wrapper = NULL;
600 lck_rw_lock_exclusive(&netagent_lock);
601 if (session != NULL) {
602 wrapper = session->wrapper;
603 if (wrapper != NULL) {
604 if (netagent_registered_count > 0) {
605 netagent_registered_count--;
606 }
607 if ((session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
608 netagent_active_count > 0) {
609 netagent_active_count--;
610 }
611
612 LIST_REMOVE(wrapper, master_chain);
613
614 unregistered = TRUE;
615 uuid_copy(unregistered_uuid, session->wrapper->netagent.netagent_uuid);
616
617 netagent_free_wrapper(session->wrapper);
618 session->wrapper = NULL;
619 NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
620 }
621 }
622 lck_rw_done(&netagent_lock);
623
624 if (unregistered) {
625 ifnet_clear_netagent(unregistered_uuid);
626 netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED, TRUE);
627 }
628 }
629
630 static void
631 netagent_delete_session(struct netagent_session *session)
632 {
633 if (session != NULL) {
634 netagent_unregister_session_wrapper(session);
635 FREE(session, M_NETAGENT);
636 }
637 }
638
639 static int
640 netagent_packet_get_netagent_data_size(mbuf_t packet, int offset, int *err)
641 {
642 int error = 0;
643
644 struct netagent netagent_peek;
645 memset(&netagent_peek, 0, sizeof(netagent_peek));
646
647 *err = 0;
648
649 error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
650 if (error) {
651 *err = ENOENT;
652 return (-1);
653 }
654
655 return (netagent_peek.netagent_data_size);
656 }
657
658 static errno_t
659 netagent_handle_register_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper)
660 {
661 lck_rw_lock_exclusive(&netagent_lock);
662
663 new_wrapper->control_unit = session->control_unit;
664 new_wrapper->generation = g_next_generation++;
665
666 session->wrapper = new_wrapper;
667 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
668 LIST_INIT(&new_wrapper->pending_triggers_list);
669
670 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
671 netagent_registered_count++;
672 if (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) {
673 netagent_active_count++;
674 }
675
676 lck_rw_done(&netagent_lock);
677
678 return 0;
679 }
680
681 static errno_t
682 netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payload,
683 u_int32_t payload_length)
684 {
685 int data_size = 0;
686 struct netagent_wrapper *new_wrapper = NULL;
687 u_int32_t response_error = 0;
688 struct netagent *register_netagent = (struct netagent *)(void *)payload;
689
690 if (session == NULL) {
691 NETAGENTLOG0(LOG_ERR, "Failed to find session");
692 response_error = EINVAL;
693 goto done;
694 }
695
696 if (payload == NULL) {
697 NETAGENTLOG0(LOG_ERR, "No payload received");
698 response_error = EINVAL;
699 goto done;
700 }
701
702 if (session->wrapper != NULL) {
703 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
704 response_error = EINVAL;
705 goto done;
706 }
707
708 if (payload_length < sizeof(struct netagent)) {
709 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)",
710 payload_length, sizeof(struct netagent));
711 response_error = EINVAL;
712 goto done;
713 }
714
715 data_size = register_netagent->netagent_data_size;
716 if (data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
717 NETAGENTLOG(LOG_ERR, "Register message size could not be read, data_size %d",
718 data_size);
719 response_error = EINVAL;
720 goto done;
721 }
722
723 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
724 if (new_wrapper == NULL) {
725 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
726 response_error = ENOMEM;
727 goto done;
728 }
729
730 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
731 memcpy(&new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
732
733 response_error = netagent_handle_register_inner(session, new_wrapper);
734 if (response_error != 0) {
735 FREE(new_wrapper, M_NETAGENT);
736 goto done;
737 }
738
739 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
740 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE);
741
742 done:
743 return response_error;
744 }
745
746 static void
747 netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
748 u_int32_t payload_length, mbuf_t packet, int offset)
749 {
750 int error;
751 int data_size = 0;
752 struct netagent_wrapper *new_wrapper = NULL;
753 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
754 uuid_t netagent_uuid;
755 uuid_clear(netagent_uuid);
756
757 if (session == NULL) {
758 NETAGENTLOG0(LOG_ERR, "Failed to find session");
759 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
760 goto fail;
761 }
762
763 if (session->wrapper != NULL) {
764 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
765 response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
766 goto fail;
767 }
768
769 if (payload_length < sizeof(struct netagent)) {
770 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)",
771 payload_length, sizeof(struct netagent));
772 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
773 goto fail;
774 }
775
776 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
777 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
778 NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %d",
779 error, data_size);
780 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
781 goto fail;
782 }
783
784 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
785 if (new_wrapper == NULL) {
786 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
787 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
788 goto fail;
789 }
790
791 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
792
793 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
794 &new_wrapper->netagent);
795 if (error) {
796 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
797 FREE(new_wrapper, M_NETAGENT);
798 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
799 goto fail;
800 }
801
802 (void)netagent_handle_register_inner(session, new_wrapper);
803
804 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
805 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
806 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE);
807 return;
808 fail:
809 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
810 }
811
812 static errno_t
813 netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
814 u_int32_t payload_length)
815 {
816 #pragma unused(payload, payload_length)
817 u_int32_t response_error = 0;
818
819 if (session == NULL) {
820 NETAGENTLOG0(LOG_ERR, "Failed to find session");
821 response_error = EINVAL;
822 goto done;
823 }
824
825 netagent_unregister_session_wrapper(session);
826
827 done:
828 return response_error;
829 }
830
831 static void
832 netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
833 u_int32_t payload_length, mbuf_t packet, int offset)
834 {
835 #pragma unused(payload_length, packet, offset)
836 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
837
838 if (session == NULL) {
839 NETAGENTLOG0(LOG_ERR, "Failed to find session");
840 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
841 goto fail;
842 }
843
844 netagent_unregister_session_wrapper(session);
845
846 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
847 return;
848 fail:
849 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
850 }
851
852 static void
853 netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
854 pid_t pid, uuid_t proc_uuid)
855 {
856 if (strncmp(wrapper->netagent.netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
857 return;
858 }
859
860 struct kev_netpolicy_ifdenied ev_ifdenied;
861
862 bzero(&ev_ifdenied, sizeof(ev_ifdenied));
863
864 ev_ifdenied.ev_data.epid = pid;
865 uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
866 ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
867
868 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
869 }
870
871 static errno_t
872 netagent_handle_update_inner(struct netagent_session *session, struct netagent_wrapper *new_wrapper, u_int32_t data_size, u_int8_t *agent_changed, netagent_error_domain_t error_domain)
873 {
874 u_int32_t response_error = 0;
875
876 if (agent_changed == NULL) {
877 NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
878 return EINVAL;
879 }
880
881 lck_rw_lock_exclusive(&netagent_lock);
882
883 if (uuid_compare(session->wrapper->netagent.netagent_uuid, new_wrapper->netagent.netagent_uuid) != 0 ||
884 memcmp(&session->wrapper->netagent.netagent_domain, &new_wrapper->netagent.netagent_domain,
885 sizeof(new_wrapper->netagent.netagent_domain)) != 0 ||
886 memcmp(&session->wrapper->netagent.netagent_type, &new_wrapper->netagent.netagent_type,
887 sizeof(new_wrapper->netagent.netagent_type)) != 0) {
888 lck_rw_done(&netagent_lock);
889 NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
890 if (error_domain == kNetagentErrorDomainPOSIX) {
891 response_error = EINVAL;
892 } else if (error_domain == kNetagentErrorDomainUserDefined) {
893 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
894 }
895 return response_error;
896 }
897
898 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
899 if (session->wrapper->netagent.netagent_data_size == new_wrapper->netagent.netagent_data_size &&
900 memcmp(&session->wrapper->netagent, &new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
901 // Agent is exactly identical, don't increment the generation count
902
903 // Make a copy of the list of pending clients, and clear the current list
904 struct netagent_client_list_s pending_triggers_list_copy;
905 LIST_INIT(&pending_triggers_list_copy);
906 struct netagent_client *search_client = NULL;
907 struct netagent_client *temp_client = NULL;
908 LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
909 LIST_REMOVE(search_client, client_chain);
910 LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
911 }
912 lck_rw_done(&netagent_lock);
913
914 // Update pending client triggers without holding a lock
915 search_client = NULL;
916 temp_client = NULL;
917 LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
918 necp_force_update_client(search_client->client_id, session->wrapper->netagent.netagent_uuid);
919 netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
920 LIST_REMOVE(search_client, client_chain);
921 FREE(search_client, M_NETAGENT);
922 }
923 NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
924 *agent_changed = FALSE;
925 return response_error;
926 }
927
928 new_wrapper->generation = g_next_generation++;
929
930 if ((new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
931 !(session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
932 netagent_active_count++;
933 } else if (!(new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
934 (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
935 netagent_active_count > 0) {
936 netagent_active_count--;
937 }
938
939 LIST_REMOVE(session->wrapper, master_chain);
940 netagent_free_wrapper(session->wrapper);
941 session->wrapper = new_wrapper;
942 new_wrapper->control_unit = session->control_unit;
943 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
944 LIST_INIT(&new_wrapper->pending_triggers_list);
945
946 NETAGENTLOG0(LOG_DEBUG, "Updated agent");
947 *agent_changed = TRUE;
948
949 lck_rw_done(&netagent_lock);
950
951 return response_error;
952 }
953
954 static errno_t
955 netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, u_int32_t payload_length)
956 {
957 u_int32_t data_size = 0;
958 struct netagent_wrapper *new_wrapper = NULL;
959 errno_t response_error = 0;
960 struct netagent *update_netagent = (struct netagent *)(void *)payload;
961 u_int8_t agent_changed;
962
963 if (session == NULL) {
964 NETAGENTLOG0(LOG_ERR, "Failed to find session");
965 response_error = EINVAL;
966 goto done;
967 }
968
969 if (payload == NULL) {
970 NETAGENTLOG0(LOG_ERR, "No payload received");
971 response_error = EINVAL;
972 goto done;
973 }
974
975 if (session->wrapper == NULL) {
976 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
977 response_error = ENOENT;
978 goto done;
979 }
980
981 if (payload_length < sizeof(struct netagent)) {
982 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)",
983 payload_length, sizeof(struct netagent));
984 response_error = EINVAL;
985 goto done;
986 }
987
988 data_size = update_netagent->netagent_data_size;
989 if (data_size > NETAGENT_MAX_DATA_SIZE) {
990 NETAGENTLOG(LOG_ERR, "Update message size (%u > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
991 response_error = EINVAL;
992 goto done;
993 }
994
995 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
996 if (new_wrapper == NULL) {
997 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
998 response_error = ENOMEM;
999 goto done;
1000 }
1001
1002 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1003 memcpy(&new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1004
1005 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1006 if (response_error == 0) {
1007 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed);
1008 if (agent_changed == FALSE) {
1009 // The session wrapper does not need the "new_wrapper" as nothing changed
1010 FREE(new_wrapper, M_NETAGENT);
1011 }
1012 } else {
1013 FREE(new_wrapper, M_NETAGENT);
1014 }
1015
1016 done:
1017 return response_error;
1018 }
1019
1020 static void
1021 netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1022 u_int32_t payload_length, mbuf_t packet, int offset)
1023 {
1024 int error;
1025 int data_size = 0;
1026 struct netagent_wrapper *new_wrapper = NULL;
1027 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1028 u_int8_t agent_changed;
1029
1030 if (session == NULL) {
1031 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1032 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1033 goto fail;
1034 }
1035
1036 if (session->wrapper == NULL) {
1037 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1038 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1039 goto fail;
1040 }
1041
1042 if (payload_length < sizeof(struct netagent)) {
1043 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)",
1044 payload_length, sizeof(struct netagent));
1045 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1046 goto fail;
1047 }
1048
1049 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1050 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
1051 NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %d",
1052 error, data_size);
1053 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1054 goto fail;
1055 }
1056
1057 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1058 if (new_wrapper == NULL) {
1059 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1060 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1061 goto fail;
1062 }
1063
1064 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1065
1066 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, &new_wrapper->netagent);
1067 if (error) {
1068 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1069 FREE(new_wrapper, M_NETAGENT);
1070 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1071 goto fail;
1072 }
1073
1074 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed , kNetagentErrorDomainUserDefined);
1075 if (response_error != 0) {
1076 FREE(new_wrapper, M_NETAGENT);
1077 goto fail;
1078 }
1079
1080 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1081 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed);
1082
1083 if (agent_changed == FALSE) {
1084 // The session wrapper does not need the "new_wrapper" as nothing changed
1085 FREE(new_wrapper, M_NETAGENT);
1086 }
1087
1088 return;
1089 fail:
1090 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1091 }
1092
1093 static void
1094 netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1095 u_int32_t payload_length, mbuf_t packet, int offset)
1096 {
1097 #pragma unused(payload_length, packet, offset)
1098 u_int8_t *response = NULL;
1099 u_int8_t *cursor = NULL;
1100 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1101
1102 if (session == NULL) {
1103 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1104 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1105 goto fail;
1106 }
1107
1108 if (session->wrapper == NULL) {
1109 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1110 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1111 goto fail;
1112 }
1113
1114 lck_rw_lock_shared(&netagent_lock);
1115
1116 size_t response_size = sizeof(struct netagent_message_header) + sizeof(session->wrapper->netagent)
1117 + session->wrapper->netagent.netagent_data_size;
1118 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
1119 if (response == NULL) {
1120 goto fail;
1121 }
1122
1123 cursor = response;
1124 cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1125 NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1126 response_size - sizeof(struct netagent_message_header));
1127 memcpy(cursor, &session->wrapper->netagent, sizeof(session->wrapper->netagent) +
1128 session->wrapper->netagent.netagent_data_size);
1129
1130 lck_rw_done(&netagent_lock);
1131
1132 if (!netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size)) {
1133 NETAGENTLOG0(LOG_ERR, "Failed to send response");
1134 }
1135 FREE(response, M_NETAGENT);
1136 return;
1137 fail:
1138 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1139 }
1140
1141 static errno_t
1142 netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1143 u_int32_t payload_length)
1144 {
1145 errno_t response_error = 0;
1146 struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1147 uuid_t client_id;
1148 u_int8_t *assigned_results = NULL;
1149
1150 if (session == NULL) {
1151 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1152 response_error = ENOENT;
1153 goto done;
1154 }
1155
1156 if (payload == NULL) {
1157 NETAGENTLOG0(LOG_ERR, "No payload received");
1158 response_error = EINVAL;
1159 goto done;
1160 }
1161
1162 if (session->wrapper == NULL) {
1163 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1164 response_error = ENOENT;
1165 goto done;
1166 }
1167
1168 if (payload_length < sizeof(uuid_t)) {
1169 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1170 response_error = EINVAL;
1171 goto done;
1172 }
1173
1174 memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1175 size_t assigned_results_length = (payload_length - sizeof(client_id));
1176
1177 if (assigned_results_length > 0) {
1178 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1179 if (assigned_results == NULL) {
1180 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1181 response_error = ENOMEM;
1182 goto done;
1183 }
1184 memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1185 }
1186
1187 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1188 response_error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1189 if (response_error) {
1190 // necp_assign_client_result returns POSIX errors
1191 if (assigned_results) {
1192 FREE(assigned_results, M_NETAGENT);
1193 }
1194 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1195 goto done;
1196 }
1197
1198 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1199 done:
1200 return response_error;
1201 }
1202
1203
1204 static void
1205 netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1206 u_int32_t payload_length, mbuf_t packet, int offset)
1207 {
1208 int error = 0;
1209 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1210 uuid_t client_id;
1211 u_int8_t *assigned_results = NULL;
1212
1213 if (session == NULL) {
1214 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1215 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1216 goto fail;
1217 }
1218
1219 if (session->wrapper == NULL) {
1220 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1221 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1222 goto fail;
1223 }
1224
1225 if (payload_length < sizeof(uuid_t)) {
1226 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1227 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1228 goto fail;
1229 }
1230
1231 error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1232 if (error) {
1233 NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1234 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1235 goto fail;
1236 }
1237
1238 size_t assigned_results_length = (payload_length - sizeof(client_id));
1239 if (assigned_results_length > 0) {
1240 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1241 if (assigned_results == NULL) {
1242 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1243 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1244 goto fail;
1245 }
1246
1247 error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1248 if (error) {
1249 FREE(assigned_results, M_NETAGENT);
1250 NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1251 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1252 goto fail;
1253 }
1254 }
1255
1256 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1257 error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1258 if (error) {
1259 if (assigned_results) {
1260 FREE(assigned_results, M_NETAGENT);
1261 }
1262 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1263 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1264 goto fail;
1265 }
1266
1267 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1268 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1269 return;
1270 fail:
1271 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1272 }
1273
1274 static struct netagent_wrapper *
1275 netagent_find_agent_with_uuid(uuid_t uuid)
1276 {
1277 struct netagent_wrapper *search_netagent = NULL;
1278
1279 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1280 if (uuid_compare(search_netagent->netagent.netagent_uuid, uuid) == 0) {
1281 return (search_netagent);
1282 }
1283 }
1284
1285 return (NULL);
1286 }
1287
1288 void
1289 netagent_post_updated_interfaces(uuid_t uuid)
1290 {
1291 struct netagent_wrapper *wrapper = NULL;
1292 lck_rw_lock_shared(&netagent_lock);
1293 wrapper = netagent_find_agent_with_uuid(uuid);
1294 lck_rw_done(&netagent_lock);
1295
1296 if (wrapper != NULL) {
1297 netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, TRUE);
1298 } else {
1299 NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
1300 }
1301
1302 return;
1303 }
1304
1305 static u_int32_t
1306 netagent_dump_get_data_size_locked()
1307 {
1308 struct netagent_wrapper *search_netagent = NULL;
1309 u_int32_t total_netagent_data_size = 0;
1310 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1311 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1312 total_netagent_data_size += sizeof(search_netagent->netagent.netagent_uuid);
1313 }
1314 return total_netagent_data_size;
1315 }
1316
1317 static void
1318 netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
1319 {
1320 size_t response_size = 0;
1321 u_int8_t *cursor = NULL;
1322 struct netagent_wrapper *search_netagent = NULL;
1323
1324 response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
1325 cursor = buffer;
1326 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1327 memcpy(cursor, search_netagent->netagent.netagent_uuid, sizeof(search_netagent->netagent.netagent_uuid));
1328 cursor += sizeof(search_netagent->netagent.netagent_uuid);
1329 }
1330 }
1331
1332 int
1333 netagent_ioctl(u_long cmd, caddr_t data)
1334 {
1335 int error = 0;
1336
1337 switch (cmd) {
1338 case SIOCGIFAGENTLIST32:
1339 case SIOCGIFAGENTLIST64: {
1340 /* Check entitlement if the client requests agent dump */
1341 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
1342 if (cred_result != 0) {
1343 NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
1344 return EINVAL;
1345 }
1346 break;
1347 }
1348 default:
1349 break;
1350 }
1351
1352 lck_rw_lock_shared(&netagent_lock);
1353 switch (cmd) {
1354 case SIOCGIFAGENTDATA32: {
1355 struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
1356 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
1357 if (wrapper == NULL) {
1358 error = ENOENT;
1359 break;
1360 }
1361 uuid_copy(ifsir32->netagent_uuid, wrapper->netagent.netagent_uuid);
1362 memcpy(ifsir32->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir32->netagent_domain));
1363 memcpy(ifsir32->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir32->netagent_type));
1364 memcpy(ifsir32->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir32->netagent_desc));
1365 ifsir32->netagent_flags = wrapper->netagent.netagent_flags;
1366 if (ifsir32->netagent_data_size == 0) {
1367 // First pass, client wants data size
1368 ifsir32->netagent_data_size = wrapper->netagent.netagent_data_size;
1369 } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
1370 ifsir32->netagent_data_size == wrapper->netagent.netagent_data_size) {
1371 // Second pass, client wants data buffer filled out
1372 error = copyout(wrapper->netagent.netagent_data, ifsir32->netagent_data, wrapper->netagent.netagent_data_size);
1373 } else {
1374 error = EINVAL;
1375 }
1376 break;
1377 }
1378 case SIOCGIFAGENTDATA64: {
1379 struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
1380 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
1381 if (wrapper == NULL) {
1382 error = ENOENT;
1383 break;
1384 }
1385 uuid_copy(ifsir64->netagent_uuid, wrapper->netagent.netagent_uuid);
1386 memcpy(ifsir64->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir64->netagent_domain));
1387 memcpy(ifsir64->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir64->netagent_type));
1388 memcpy(ifsir64->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir64->netagent_desc));
1389 ifsir64->netagent_flags = wrapper->netagent.netagent_flags;
1390 if (ifsir64->netagent_data_size == 0) {
1391 // First pass, client wants data size
1392 ifsir64->netagent_data_size = wrapper->netagent.netagent_data_size;
1393 } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
1394 ifsir64->netagent_data_size == wrapper->netagent.netagent_data_size) {
1395 // Second pass, client wants data buffer filled out
1396 error = copyout(wrapper->netagent.netagent_data, ifsir64->netagent_data, wrapper->netagent.netagent_data_size);
1397 } else {
1398 error = EINVAL;
1399 }
1400 break;
1401 }
1402 case SIOCGIFAGENTLIST32: {
1403 struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
1404 if (ifsir32->data_size == 0) {
1405 // First pass, client wants data size
1406 ifsir32->data_size = netagent_dump_get_data_size_locked();
1407 } else if (ifsir32->data != USER_ADDR_NULL &&
1408 ifsir32->data_size > 0 &&
1409 ifsir32->data_size == netagent_dump_get_data_size_locked()) {
1410 // Second pass, client wants data buffer filled out
1411 u_int8_t *response = NULL;
1412 MALLOC(response, u_int8_t *, ifsir32->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1413 if (response == NULL) {
1414 error = ENOMEM;
1415 break;
1416 }
1417
1418 netagent_dump_copy_data_locked(response, ifsir32->data_size);
1419 error = copyout(response, ifsir32->data, ifsir32->data_size);
1420 FREE(response, M_NETAGENT);
1421 } else {
1422 error = EINVAL;
1423 }
1424 break;
1425 }
1426 case SIOCGIFAGENTLIST64: {
1427 struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
1428 if (ifsir64->data_size == 0) {
1429 // First pass, client wants data size
1430 ifsir64->data_size = netagent_dump_get_data_size_locked();
1431 } else if (ifsir64->data != USER_ADDR_NULL &&
1432 ifsir64->data_size > 0 &&
1433 ifsir64->data_size == netagent_dump_get_data_size_locked()) {
1434 // Second pass, client wants data buffer filled out
1435 u_int8_t *response = NULL;
1436 MALLOC(response, u_int8_t *, ifsir64->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1437 if (response == NULL) {
1438 error = ENOMEM;
1439 break;
1440 }
1441
1442 netagent_dump_copy_data_locked(response, ifsir64->data_size);
1443 error = copyout(response, ifsir64->data, ifsir64->data_size);
1444 FREE(response, M_NETAGENT);
1445 } else {
1446 error = EINVAL;
1447 }
1448 break;
1449 }
1450 default: {
1451 error = EINVAL;
1452 break;
1453 }
1454 }
1455 lck_rw_done(&netagent_lock);
1456 return (error);
1457 }
1458
1459 u_int32_t
1460 netagent_get_flags(uuid_t uuid)
1461 {
1462 u_int32_t flags = 0;
1463 lck_rw_lock_shared(&netagent_lock);
1464 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1465 if (wrapper != NULL) {
1466 flags = wrapper->netagent.netagent_flags;
1467 } else {
1468 NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
1469 }
1470 lck_rw_done(&netagent_lock);
1471
1472 return (flags);
1473 }
1474
1475 u_int32_t
1476 netagent_get_generation(uuid_t uuid)
1477 {
1478 u_int32_t generation = 0;
1479 lck_rw_lock_shared(&netagent_lock);
1480 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1481 if (wrapper != NULL) {
1482 generation = wrapper->generation;
1483 } else {
1484 NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
1485 }
1486 lck_rw_done(&netagent_lock);
1487
1488 return (generation);
1489 }
1490
1491 bool
1492 netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
1493 {
1494 bool found = FALSE;
1495 if (domain == NULL || type == NULL) {
1496 NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
1497 return (FALSE);
1498 }
1499
1500 lck_rw_lock_shared(&netagent_lock);
1501 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1502 if (wrapper != NULL) {
1503 found = TRUE;
1504 memcpy(domain, wrapper->netagent.netagent_domain, NETAGENT_DOMAINSIZE);
1505 memcpy(type, wrapper->netagent.netagent_type, NETAGENT_TYPESIZE);
1506 } else {
1507 NETAGENTLOG0(LOG_DEBUG, "Type requested for invalid netagent");
1508 }
1509 lck_rw_done(&netagent_lock);
1510
1511 return (found);
1512 }
1513
1514 int
1515 netagent_kernel_trigger(uuid_t uuid)
1516 {
1517 int error = 0;
1518
1519 lck_rw_lock_shared(&netagent_lock);
1520 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1521 if (wrapper == NULL) {
1522 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
1523 error = ENOENT;
1524 goto done;
1525 }
1526
1527 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
1528 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
1529 // Agent does not accept kernel triggers
1530 error = EINVAL;
1531 goto done;
1532 }
1533
1534 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1535 // Agent already active
1536 NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
1537 error = 0;
1538 goto done;
1539 }
1540
1541 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
1542 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
1543 done:
1544 lck_rw_done(&netagent_lock);
1545 return (error);
1546 }
1547
1548 int
1549 netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, u_int8_t message_type)
1550 {
1551 int error = 0;
1552
1553 if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
1554 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
1555 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
1556 message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
1557 message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS) {
1558 NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
1559 return(EINVAL);
1560 }
1561
1562 lck_rw_lock_shared(&netagent_lock);
1563 bool should_unlock = TRUE;
1564 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1565 if (wrapper == NULL) {
1566 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance could not be found");
1567 error = ENOENT;
1568 goto done;
1569 }
1570
1571 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1572 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1573 // Agent does not accept user triggers
1574 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1575 error = ENOTSUP;
1576
1577 struct proc *p = current_proc();
1578 pid_t current_pid = 0;
1579 uuid_t current_proc_uuid;
1580 uuid_clear(current_proc_uuid);
1581 if (p != NULL) {
1582 current_pid = proc_pid(p);
1583 proc_getexecutableuuid(p, current_proc_uuid, sizeof(current_proc_uuid));
1584 }
1585 netagent_send_cellular_failed_event(wrapper, current_pid, current_proc_uuid);
1586 goto done;
1587 }
1588 } else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
1589 message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS) {
1590 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_NEXUS_PROVIDER) == 0) {
1591 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
1592 // Agent is not a nexus provider
1593 error = EINVAL;
1594 goto done;
1595 }
1596
1597 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
1598 // Agent not active
1599 NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
1600 error = EINVAL;
1601 goto done;
1602 }
1603 }
1604
1605 error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
1606 if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1607 if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
1608 // Grab the lock exclusively to add a pending client to the list
1609 struct netagent_client *new_pending_client = NULL;
1610 MALLOC(new_pending_client, struct netagent_client *, sizeof(*new_pending_client), M_NETAGENT, M_WAITOK);
1611 if (new_pending_client == NULL) {
1612 NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
1613 } else {
1614 uuid_copy(new_pending_client->client_id, necp_client_uuid);
1615 struct proc *p = current_proc();
1616 if (p != NULL) {
1617 new_pending_client->client_pid = proc_pid(p);
1618 proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
1619 }
1620 LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
1621 }
1622 } else {
1623 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
1624 should_unlock = FALSE;
1625 }
1626 }
1627 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
1628 done:
1629 if (should_unlock) {
1630 lck_rw_done(&netagent_lock);
1631 }
1632 return (error);
1633 }
1634
1635 int
1636 netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
1637 {
1638 int error = 0;
1639
1640 lck_rw_lock_shared(&netagent_lock);
1641 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1642 if (wrapper == NULL) {
1643 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance could not be found");
1644 error = ENOENT;
1645 goto done;
1646 }
1647
1648 u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent.netagent_data_size);
1649 if (user_size < total_size) {
1650 NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
1651 error = EINVAL;
1652 goto done;
1653 }
1654
1655 error = copyout(&wrapper->netagent, user_addr, total_size);
1656
1657 NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
1658 done:
1659 lck_rw_done(&netagent_lock);
1660 return (error);
1661 }
1662
1663 int
1664 netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
1665 {
1666 #pragma unused(p, retval)
1667 uuid_t agent_uuid;
1668 int error = 0;
1669
1670 if (uap == NULL) {
1671 NETAGENTLOG0(LOG_ERR, "uap == NULL");
1672 return (EINVAL);
1673 }
1674
1675 if (uap->agent_uuid) {
1676 if (uap->agent_uuidlen != sizeof(uuid_t)) {
1677 NETAGENTLOG(LOG_ERR, "Incorrect length (got %d, expected %d)",
1678 uap->agent_uuidlen, sizeof(uuid_t));
1679 return (ERANGE);
1680 }
1681
1682 error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
1683 if (error) {
1684 NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
1685 return (error);
1686 }
1687 }
1688
1689 if (uuid_is_null(agent_uuid)) {
1690 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
1691 return (EINVAL);
1692 }
1693
1694 lck_rw_lock_shared(&netagent_lock);
1695 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1696 if (wrapper == NULL) {
1697 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
1698 error = ENOENT;
1699 goto done;
1700 }
1701
1702 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1703 // Agent does not accept triggers
1704 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
1705 error = ENOTSUP;
1706 goto done;
1707 }
1708
1709 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1710 // Agent already active
1711 NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
1712 error = 0;
1713 goto done;
1714 }
1715
1716 error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
1717 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
1718 done:
1719 lck_rw_done(&netagent_lock);
1720 return (error);
1721 }