]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/network_agent.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / net / network_agent.c
CommitLineData
3e170ce0
A
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
47u_int32_t netagent_debug = LOG_NOTICE; // 0=None, 1=Basic
48
49SYSCTL_NODE(_net, OID_AUTO, netagent, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "NetworkAgent");
50SYSCTL_INT(_net_netagent, OID_AUTO, debug, CTLFLAG_LOCKED | CTLFLAG_RW, &netagent_debug, 0, "");
51
52static int netagent_registered_count = 0;
53SYSCTL_INT(_net_netagent, OID_AUTO, registered_count , CTLFLAG_RD | CTLFLAG_LOCKED,
54 &netagent_registered_count, 0, "");
55
56static int netagent_active_count = 0;
57SYSCTL_INT(_net_netagent, OID_AUTO, active_count , CTLFLAG_RD | CTLFLAG_LOCKED,
58 &netagent_active_count, 0, "");
59
60#define NETAGENTLOG(level, format, ...) do { \
61 if (level <= netagent_debug) \
62 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: " format "\n", __FUNCTION__, __VA_ARGS__); \
63} while (0)
64
65#define NETAGENTLOG0(level, msg) do { \
66 if (level <= netagent_debug) \
67 log((level > LOG_NOTICE ? LOG_NOTICE : level), "%s: %s\n", __FUNCTION__, msg); \
68} while (0)
69
70struct netagent_assertion {
71 LIST_ENTRY(netagent_assertion) assertion_chain;
72 uuid_t asserted_uuid;
73};
74
75struct netagent_wrapper {
76 LIST_ENTRY(netagent_wrapper) master_chain;
77 u_int32_t control_unit;
78 struct netagent netagent;
79};
80
81struct netagent_session {
82 u_int32_t control_unit;
83 struct netagent_wrapper *wrapper;
84 LIST_HEAD(_netagent_assertion_list, netagent_assertion) assertion_list;
85};
86
87static LIST_HEAD(_netagent_list, netagent_wrapper) master_netagent_list;
88
89static kern_ctl_ref netagent_kctlref;
90static u_int32_t netagent_family;
91static OSMallocTag netagent_malloc_tag;
92static lck_grp_attr_t *netagent_grp_attr = NULL;
93static lck_attr_t *netagent_mtx_attr = NULL;
94static lck_grp_t *netagent_mtx_grp = NULL;
95decl_lck_rw_data(static, netagent_lock);
96
97static errno_t netagent_register_control(void);
98static errno_t netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
99 void **unitinfo);
100static errno_t netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo);
101static errno_t netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
102 mbuf_t m, int flags);
103static void netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags);
104static errno_t netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
105 int opt, void *data, size_t *len);
106static errno_t netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
107 int opt, void *data, size_t len);
108
109static int netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size);
110
111static struct netagent_session *netagent_create_session(u_int32_t control_unit);
112static void netagent_delete_session(struct netagent_session *session);
113
114static void netagent_handle_register(struct netagent_session *session, u_int32_t message_id,
115 u_int32_t payload_length, mbuf_t packet, int offset);
116static void netagent_handle_unregister(struct netagent_session *session, u_int32_t message_id,
117 u_int32_t payload_length, mbuf_t packet, int offset);
118static void netagent_handle_update(struct netagent_session *session, u_int32_t message_id,
119 u_int32_t payload_length, mbuf_t packet, int offset);
120static void netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
121 u_int32_t payload_length, mbuf_t packet, int offset);
122static void netagent_handle_assert(struct netagent_session *session, u_int32_t message_id,
123 u_int32_t payload_length, mbuf_t packet, int offset);
124static void netagent_handle_unassert(struct netagent_session *session, u_int32_t message_id,
125 u_int32_t payload_length, mbuf_t packet, int offset);
126
127static struct netagent_wrapper *netagent_find_agent_with_uuid(uuid_t uuid);
128
129errno_t
130netagent_init(void)
131{
132 errno_t result = 0;
133
134 result = netagent_register_control();
135 if (result != 0) {
136 goto done;
137 }
138
139 netagent_grp_attr = lck_grp_attr_alloc_init();
140 if (netagent_grp_attr == NULL) {
141 NETAGENTLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed");
142 result = ENOMEM;
143 goto done;
144 }
145
146 netagent_mtx_grp = lck_grp_alloc_init(NETAGENT_CONTROL_NAME, netagent_grp_attr);
147 if (netagent_mtx_grp == NULL) {
148 NETAGENTLOG0(LOG_ERR, "lck_grp_alloc_init failed");
149 result = ENOMEM;
150 goto done;
151 }
152
153 netagent_mtx_attr = lck_attr_alloc_init();
154 if (netagent_mtx_attr == NULL) {
155 NETAGENTLOG0(LOG_ERR, "lck_attr_alloc_init failed");
156 result = ENOMEM;
157 goto done;
158 }
159
160 lck_rw_init(&netagent_lock, netagent_mtx_grp, netagent_mtx_attr);
161
162 LIST_INIT(&master_netagent_list);
163
164done:
165 if (result != 0) {
166 if (netagent_mtx_attr != NULL) {
167 lck_attr_free(netagent_mtx_attr);
168 netagent_mtx_attr = NULL;
169 }
170 if (netagent_mtx_grp != NULL) {
171 lck_grp_free(netagent_mtx_grp);
172 netagent_mtx_grp = NULL;
173 }
174 if (netagent_grp_attr != NULL) {
175 lck_grp_attr_free(netagent_grp_attr);
176 netagent_grp_attr = NULL;
177 }
178 if (netagent_kctlref != NULL) {
179 ctl_deregister(netagent_kctlref);
180 netagent_kctlref = NULL;
181 }
182 }
183 return (result);
184}
185
186static errno_t
187netagent_register_control(void)
188{
189 struct kern_ctl_reg kern_ctl;
190 errno_t result = 0;
191
192 // Create a tag to allocate memory
193 netagent_malloc_tag = OSMalloc_Tagalloc(NETAGENT_CONTROL_NAME, OSMT_DEFAULT);
194
195 // Find a unique value for our interface family
196 result = mbuf_tag_id_find(NETAGENT_CONTROL_NAME, &netagent_family);
197 if (result != 0) {
198 NETAGENTLOG(LOG_ERR, "mbuf_tag_id_find_internal failed: %d", result);
199 return (result);
200 }
201
202 bzero(&kern_ctl, sizeof(kern_ctl));
203 strlcpy(kern_ctl.ctl_name, NETAGENT_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
204 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
205 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; // Require root
206 kern_ctl.ctl_sendsize = 64 * 1024;
207 kern_ctl.ctl_recvsize = 64 * 1024;
208 kern_ctl.ctl_connect = netagent_ctl_connect;
209 kern_ctl.ctl_disconnect = netagent_ctl_disconnect;
210 kern_ctl.ctl_send = netagent_ctl_send;
211 kern_ctl.ctl_rcvd = netagent_ctl_rcvd;
212 kern_ctl.ctl_setopt = netagent_ctl_setopt;
213 kern_ctl.ctl_getopt = netagent_ctl_getopt;
214
215 result = ctl_register(&kern_ctl, &netagent_kctlref);
216 if (result != 0) {
217 NETAGENTLOG(LOG_ERR, "ctl_register failed: %d", result);
218 return (result);
219 }
220
221 return (0);
222}
223
224static errno_t
225netagent_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, void **unitinfo)
226{
227#pragma unused(kctlref)
228 *unitinfo = netagent_create_session(sac->sc_unit);
229 if (*unitinfo == NULL) {
230 // Could not allocate session
231 return (ENOBUFS);
232 }
233
234 return (0);
235}
236
237static errno_t
238netagent_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo)
239{
240#pragma unused(kctlref, unit)
241 struct netagent_session *session = (struct netagent_session *)unitinfo;
242 if (session != NULL) {
243 netagent_delete_session(session);
244 }
245
246 return (0);
247}
248
249// Kernel events
250static void
251netagent_post_event(uuid_t agent_uuid, u_int32_t event_code)
252{
253 struct kev_msg ev_msg;
254 memset(&ev_msg, 0, sizeof(ev_msg));
255
256 struct kev_netagent_data event_data;
257
258 ev_msg.vendor_code = KEV_VENDOR_APPLE;
259 ev_msg.kev_class = KEV_NETWORK_CLASS;
260 ev_msg.kev_subclass = KEV_NETAGENT_SUBCLASS;
261 ev_msg.event_code = event_code;
262
263 uuid_copy(event_data.netagent_uuid, agent_uuid);
264 ev_msg.dv[0].data_ptr = &event_data;
265 ev_msg.dv[0].data_length = sizeof(event_data);
266
267 kev_post_msg(&ev_msg);
268}
269
270// Message handling
271static u_int8_t *
272netagent_buffer_write_message_header(u_int8_t *buffer, u_int8_t message_type, u_int8_t flags,
273 u_int32_t message_id, u_int32_t error, u_int32_t payload_length)
274{
275 ((struct netagent_message_header *)(void *)buffer)->message_type = message_type;
276 ((struct netagent_message_header *)(void *)buffer)->message_flags = flags;
277 ((struct netagent_message_header *)(void *)buffer)->message_id = message_id;
278 ((struct netagent_message_header *)(void *)buffer)->message_error = error;
279 ((struct netagent_message_header *)(void *)buffer)->message_payload_length = payload_length;
280 return (buffer + sizeof(struct netagent_message_header));
281}
282
283static int
284netagent_send_ctl_data(u_int32_t control_unit, u_int8_t *buffer, size_t buffer_size)
285{
286 if (netagent_kctlref == NULL || control_unit == 0 || buffer == NULL || buffer_size == 0) {
287 return (EINVAL);
288 }
289
290 return ctl_enqueuedata(netagent_kctlref, control_unit, buffer, buffer_size, CTL_DATA_EOR);
291}
292
293static int
294netagent_send_trigger(struct netagent_wrapper *wrapper, struct proc *p, u_int32_t flags, u_int32_t trigger_type)
295{
296 int error = 0;
297 struct netagent_trigger_message *trigger_message = NULL;
298 u_int8_t *trigger = NULL;
299 size_t trigger_size = sizeof(struct netagent_message_header) + sizeof(struct netagent_trigger_message);
300
301 MALLOC(trigger, u_int8_t *, trigger_size, M_NETAGENT, M_WAITOK);
302 if (trigger == NULL) {
303 return (ENOMEM);
304 }
305
306 (void)netagent_buffer_write_message_header(trigger, trigger_type, 0, 0, 0, sizeof(struct netagent_trigger_message));
307
308 trigger_message = (struct netagent_trigger_message *)(void *)(trigger + sizeof(struct netagent_message_header));
309 trigger_message->trigger_flags = flags;
310 if (p != NULL) {
311 trigger_message->trigger_pid = proc_pid(p);
312 proc_getexecutableuuid(p, trigger_message->trigger_proc_uuid, sizeof(trigger_message->trigger_proc_uuid));
313 } else {
314 trigger_message->trigger_pid = 0;
315 uuid_clear(trigger_message->trigger_proc_uuid);
316 }
317
318 if ((error = netagent_send_ctl_data(wrapper->control_unit, (u_int8_t *)trigger, trigger_size))) {
319 NETAGENTLOG(LOG_ERR, "Failed to send trigger message on control unit %d", wrapper->control_unit);
320 }
321
322 FREE(trigger, M_NETAGENT);
323 return (error);
324}
325
326static int
327netagent_send_success_response(struct netagent_session *session, u_int8_t message_type, u_int32_t message_id)
328{
329 int error = 0;
330 u_int8_t *response = NULL;
331 size_t response_size = sizeof(struct netagent_message_header);
332 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
333 if (response == NULL) {
334 return (ENOMEM);
335 }
336 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0, 0);
337
338 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
339 NETAGENTLOG0(LOG_ERR, "Failed to send response");
340 }
341
342 FREE(response, M_NETAGENT);
343 return (error);
344}
345
346static int
347netagent_send_error_response(struct netagent_session *session, u_int8_t message_type,
348 u_int32_t message_id, u_int32_t error_code)
349{
350 int error = 0;
351 u_int8_t *response = NULL;
352 size_t response_size = sizeof(struct netagent_message_header);
353 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
354 if (response == NULL) {
355 return (ENOMEM);
356 }
357 (void)netagent_buffer_write_message_header(response, message_type, NETAGENT_MESSAGE_FLAGS_RESPONSE,
358 message_id, error_code, 0);
359
360 if ((error = netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size))) {
361 NETAGENTLOG0(LOG_ERR, "Failed to send response");
362 }
363
364 FREE(response, M_NETAGENT);
365 return (error);
366}
367
368static errno_t
369netagent_ctl_send(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, mbuf_t packet, int flags)
370{
371#pragma unused(kctlref, unit, flags)
372 struct netagent_session *session = (struct netagent_session *)unitinfo;
373 struct netagent_message_header header;
374 int error = 0;
375
376 if (session == NULL) {
377 NETAGENTLOG0(LOG_ERR, "Got a NULL session");
378 error = EINVAL;
379 goto done;
380 }
381
382 if (mbuf_pkthdr_len(packet) < sizeof(header)) {
383 NETAGENTLOG(LOG_ERR, "Got a bad packet, length (%lu) < sizeof header (%lu)",
384 mbuf_pkthdr_len(packet), sizeof(header));
385 error = EINVAL;
386 goto done;
387 }
388
389 error = mbuf_copydata(packet, 0, sizeof(header), &header);
390 if (error) {
391 NETAGENTLOG(LOG_ERR, "mbuf_copydata failed for the header: %d", error);
392 error = ENOBUFS;
393 goto done;
394 }
395
396 switch (header.message_type) {
397 case NETAGENT_MESSAGE_TYPE_REGISTER: {
398 netagent_handle_register(session, header.message_id, header.message_payload_length,
399 packet, sizeof(header));
400 break;
401 }
402 case NETAGENT_MESSAGE_TYPE_UNREGISTER: {
403 netagent_handle_unregister(session, header.message_id, header.message_payload_length,
404 packet, sizeof(header));
405 break;
406 }
407 case NETAGENT_MESSAGE_TYPE_UPDATE: {
408 netagent_handle_update(session, header.message_id, header.message_payload_length,
409 packet, sizeof(header));
410 break;
411 }
412 case NETAGENT_MESSAGE_TYPE_GET: {
413 netagent_handle_get(session, header.message_id, header.message_payload_length,
414 packet, sizeof(header));
415 break;
416 }
417 case NETAGENT_MESSAGE_TYPE_ASSERT: {
418 netagent_handle_assert(session, header.message_id, header.message_payload_length,
419 packet, sizeof(header));
420 break;
421 }
422 case NETAGENT_MESSAGE_TYPE_UNASSERT: {
423 netagent_handle_unassert(session, header.message_id, header.message_payload_length,
424 packet, sizeof(header));
425 break;
426 }
427 default: {
428 NETAGENTLOG(LOG_ERR, "Received unknown message type %d", header.message_type);
429 netagent_send_error_response(session, header.message_type, header.message_id,
430 NETAGENT_MESSAGE_ERROR_UNKNOWN_TYPE);
431 break;
432 }
433 }
434
435done:
436 mbuf_freem(packet);
437 return (error);
438}
439
440static void
441netagent_ctl_rcvd(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int flags)
442{
443#pragma unused(kctlref, unit, unitinfo, flags)
444 return;
445}
446
447static errno_t
448netagent_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
449 void *data, size_t *len)
450{
451#pragma unused(kctlref, unit, unitinfo, opt, data, len)
452 return (0);
453}
454
455static errno_t
456netagent_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo, int opt,
457 void *data, size_t len)
458{
459#pragma unused(kctlref, unit, unitinfo, opt, data, len)
460 return (0);
461}
462
463// Session Management
464static struct netagent_session *
465netagent_create_session(u_int32_t control_unit)
466{
467 struct netagent_session *new_session = NULL;
468
469 MALLOC(new_session, struct netagent_session *, sizeof(*new_session), M_NETAGENT, M_WAITOK);
470 if (new_session == NULL) {
471 goto done;
472 }
473 NETAGENTLOG(LOG_DEBUG, "Create agent session, control unit %d", control_unit);
474 memset(new_session, 0, sizeof(*new_session));
475 new_session->control_unit = control_unit;
476 LIST_INIT(&new_session->assertion_list);
477 new_session->wrapper = NULL;
478done:
479 return (new_session);
480}
481
482static void
483netagent_unregister_session_wrapper(struct netagent_session *session)
484{
485 bool unregistered = FALSE;
486 uuid_t unregistered_uuid;
487 struct netagent_wrapper *wrapper = NULL;
488 lck_rw_lock_exclusive(&netagent_lock);
489 if (session != NULL) {
490 wrapper = session->wrapper;
491 if (wrapper != NULL) {
492 if (netagent_registered_count > 0) {
493 netagent_registered_count--;
494 }
495 if ((session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
496 netagent_active_count > 0) {
497 netagent_active_count--;
498 }
499
500 LIST_REMOVE(wrapper, master_chain);
501
502 unregistered = TRUE;
503 uuid_copy(unregistered_uuid, session->wrapper->netagent.netagent_uuid);
504
505 FREE(wrapper, M_NETAGENT);
506 session->wrapper = NULL;
507 NETAGENTLOG0(LOG_DEBUG, "Unregistered agent");
508 }
509 }
510 lck_rw_done(&netagent_lock);
511
512 if (unregistered) {
513 netagent_post_event(unregistered_uuid, KEV_NETAGENT_UNREGISTERED);
514 ifnet_clear_netagent(unregistered_uuid);
515 }
516}
517
518static void
519netagent_delete_session(struct netagent_session *session)
520{
521 if (session != NULL) {
522 netagent_unregister_session_wrapper(session);
523
524 // Unassert any pending assertions
525 lck_rw_lock_shared(&netagent_lock);
526 struct netagent_assertion *search_assertion = NULL;
527 struct netagent_assertion *temp_assertion = NULL;
528 LIST_FOREACH_SAFE(search_assertion, &session->assertion_list, assertion_chain, temp_assertion) {
529 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(search_assertion->asserted_uuid);
530 if (wrapper != NULL) {
531 netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER_UNASSERT);
532 }
533 LIST_REMOVE(search_assertion, assertion_chain);
534 FREE(search_assertion, M_NETAGENT);
535 }
536 lck_rw_done(&netagent_lock);
537
538 FREE(session, M_NETAGENT);
539 }
540}
541
542static int
543netagent_packet_get_netagent_data_size(mbuf_t packet, int offset, int *err)
544{
545 int error = 0;
546
547 struct netagent netagent_peek;
548 memset(&netagent_peek, 0, sizeof(netagent_peek));
549
550 *err = 0;
551
552 error = mbuf_copydata(packet, offset, sizeof(netagent_peek), &netagent_peek);
553 if (error) {
554 *err = ENOENT;
555 return (-1);
556 }
557
558 return (netagent_peek.netagent_data_size);
559}
560
561static void
562netagent_handle_register(struct netagent_session *session, u_int32_t message_id,
563 u_int32_t payload_length, mbuf_t packet, int offset)
564{
565 int error;
566 int data_size = 0;
567 struct netagent_wrapper *new_wrapper = NULL;
568 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
569 uuid_t netagent_uuid;
570 uuid_clear(netagent_uuid);
571
572 if (session == NULL) {
573 NETAGENTLOG0(LOG_ERR, "Failed to find session");
574 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
575 goto fail;
576 }
577
578 if (session->wrapper != NULL) {
579 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
580 response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
581 goto fail;
582 }
583
584 if (payload_length < sizeof(struct netagent)) {
585 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)",
586 payload_length, sizeof(struct netagent));
587 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
588 goto fail;
589 }
590
591 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
592 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
593 NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %d",
594 error, data_size);
595 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
596 goto fail;
597 }
598
599 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
600 if (new_wrapper == NULL) {
601 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
602 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
603 goto fail;
604 }
605
606 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
607
608 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
609 &new_wrapper->netagent);
610 if (error) {
611 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
612 FREE(new_wrapper, M_NETAGENT);
613 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
614 goto fail;
615 }
616
617 lck_rw_lock_exclusive(&netagent_lock);
618
619 new_wrapper->control_unit = session->control_unit;
620
621 session->wrapper = new_wrapper;
622 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
623
624 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
625 netagent_registered_count++;
626 if (new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) {
627 netagent_active_count++;
628 }
629
630 lck_rw_done(&netagent_lock);
631
632 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
633 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
634 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED);
635 return;
636fail:
637 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
638}
639
640static void
641netagent_handle_unregister(struct netagent_session *session, u_int32_t message_id,
642 u_int32_t payload_length, mbuf_t packet, int offset)
643{
644#pragma unused(payload_length, packet, offset)
645 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
646
647 if (session == NULL) {
648 NETAGENTLOG0(LOG_ERR, "Failed to find session");
649 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
650 goto fail;
651 }
652
653 netagent_unregister_session_wrapper(session);
654
655 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
656 return;
657fail:
658 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
659}
660
661static void
662netagent_handle_update(struct netagent_session *session, u_int32_t message_id,
663 u_int32_t payload_length, mbuf_t packet, int offset)
664{
665 int error;
666 int data_size = 0;
667 struct netagent_wrapper *new_wrapper = NULL;
668 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
669 uuid_t netagent_uuid;
670 uuid_clear(netagent_uuid);
671
672 if (session == NULL) {
673 NETAGENTLOG0(LOG_ERR, "Failed to find session");
674 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
675 goto fail;
676 }
677
678 if (session->wrapper == NULL) {
679 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
680 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
681 goto fail;
682 }
683
684 if (payload_length < sizeof(struct netagent)) {
685 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)",
686 payload_length, sizeof(struct netagent));
687 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
688 goto fail;
689 }
690
691 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
692 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
693 NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %d",
694 error, data_size);
695 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
696 goto fail;
697 }
698
699 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
700 if (new_wrapper == NULL) {
701 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
702 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
703 goto fail;
704 }
705
706 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
707
708 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, &new_wrapper->netagent);
709 if (error) {
710 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
711 FREE(new_wrapper, M_NETAGENT);
712 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
713 goto fail;
714 }
715
716 lck_rw_lock_exclusive(&netagent_lock);
717
718 if (uuid_compare(session->wrapper->netagent.netagent_uuid, new_wrapper->netagent.netagent_uuid) != 0 ||
719 memcmp(&session->wrapper->netagent.netagent_domain, &new_wrapper->netagent.netagent_domain,
720 sizeof(new_wrapper->netagent.netagent_domain)) != 0 ||
721 memcmp(&session->wrapper->netagent.netagent_type, &new_wrapper->netagent.netagent_type,
722 sizeof(new_wrapper->netagent.netagent_type)) != 0) {
723 NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
724 FREE(new_wrapper, M_NETAGENT);
725 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
726 lck_rw_done(&netagent_lock);
727 goto fail;
728 }
729
730 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
731 if ((new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
732 !(session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
733 netagent_active_count++;
734 } else if (!(new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
735 (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
736 netagent_active_count > 0) {
737 netagent_active_count--;
738 }
739
740 LIST_REMOVE(session->wrapper, master_chain);
741 FREE(session->wrapper, M_NETAGENT);
742 session->wrapper = new_wrapper;
743 new_wrapper->control_unit = session->control_unit;
744 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
745
746 lck_rw_done(&netagent_lock);
747
748 NETAGENTLOG0(LOG_DEBUG, "Updated agent");
749 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
750 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED);
751 return;
752fail:
753 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
754}
755
756static void
757netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
758 u_int32_t payload_length, mbuf_t packet, int offset)
759{
760#pragma unused(payload_length, packet, offset)
761 u_int8_t *response = NULL;
762 u_int8_t *cursor = NULL;
763 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
764
765 if (session == NULL) {
766 NETAGENTLOG0(LOG_ERR, "Failed to find session");
767 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
768 goto fail;
769 }
770
771 if (session->wrapper == NULL) {
772 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
773 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
774 goto fail;
775 }
776
777 lck_rw_lock_shared(&netagent_lock);
778
779 size_t response_size = sizeof(struct netagent_message_header) + sizeof(session->wrapper->netagent)
780 + session->wrapper->netagent.netagent_data_size;
781 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
782 if (response == NULL) {
783 goto fail;
784 }
785
786 cursor = response;
787 cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
788 NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
789 response_size - sizeof(struct netagent_message_header));
790 memcpy(cursor, &session->wrapper->netagent, sizeof(session->wrapper->netagent) +
791 session->wrapper->netagent.netagent_data_size);
792
793 lck_rw_done(&netagent_lock);
794
795 if (!netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size)) {
796 NETAGENTLOG0(LOG_ERR, "Failed to send response");
797 }
798 FREE(response, M_NETAGENT);
799 return;
800fail:
801 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
802}
803
804static void
805netagent_handle_assert(struct netagent_session *session, u_int32_t message_id,
806 u_int32_t payload_length, mbuf_t packet, int offset)
807{
808 int error;
809 struct netagent_assertion *new_assertion = NULL;
810 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
811 uuid_t netagent_uuid;
812 uuid_clear(netagent_uuid);
813
814 if (session == NULL) {
815 NETAGENTLOG0(LOG_ERR, "Failed to find session");
816 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
817 goto fail;
818 }
819
820 if (payload_length < sizeof(uuid_t)) {
821 NETAGENTLOG(LOG_ERR, "Assert message size too small for uuid: (%d < %d)",
822 payload_length, sizeof(uuid_t));
823 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
824 goto fail;
825 }
826
827 error = mbuf_copydata(packet, offset, sizeof(uuid_t), &netagent_uuid);
828 if (error) {
829 NETAGENTLOG(LOG_ERR, "Failed to read uuid: %d", error);
830 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
831 goto fail;
832 }
833
834 MALLOC(new_assertion, struct netagent_assertion *, sizeof(*new_assertion), M_NETAGENT, M_WAITOK);
835 if (new_assertion == NULL) {
836 NETAGENTLOG0(LOG_ERR, "Failed to allocate assertion");
837 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
838 goto fail;
839 }
840
841 uuid_copy(new_assertion->asserted_uuid, netagent_uuid);
842
843 lck_rw_lock_shared(&netagent_lock);
844
845 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(netagent_uuid);
846 if (wrapper == NULL) {
847 lck_rw_done(&netagent_lock);
848 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
849 FREE(new_assertion, M_NETAGENT);
850 goto fail;
851 }
852
853 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER_ASSERT);
854 if (error) {
855 lck_rw_done(&netagent_lock);
856 NETAGENTLOG(LOG_ERR, "Failed to trigger assert agent: %d", error);
857 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
858 FREE(new_assertion, M_NETAGENT);
859 goto fail;
860 }
861
862 LIST_INSERT_HEAD(&session->assertion_list, new_assertion, assertion_chain);
863
864 lck_rw_done(&netagent_lock);
865
866 NETAGENTLOG0(LOG_DEBUG, "Asserted agent");
867 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSERT, message_id);
868 return;
869fail:
870 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSERT, message_id, response_error);
871}
872
873static void
874netagent_handle_unassert(struct netagent_session *session, u_int32_t message_id,
875 u_int32_t payload_length, mbuf_t packet, int offset)
876{
877 int error;
878 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
879 uuid_t netagent_uuid;
880 uuid_clear(netagent_uuid);
881
882 if (session == NULL) {
883 NETAGENTLOG0(LOG_ERR, "Failed to find session");
884 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
885 goto fail;
886 }
887
888 if (payload_length < sizeof(uuid_t)) {
889 NETAGENTLOG(LOG_ERR, "Unassert message size too small for uuid: (%d < %d)",
890 payload_length, sizeof(uuid_t));
891 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
892 goto fail;
893 }
894
895 error = mbuf_copydata(packet, offset, sizeof(uuid_t), &netagent_uuid);
896 if (error) {
897 NETAGENTLOG(LOG_ERR, "Failed to read uuid: %d", error);
898 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
899 goto fail;
900 }
901
902 struct netagent_assertion *found_assertion = NULL;
903 struct netagent_assertion *search_assertion = NULL;
904 LIST_FOREACH(search_assertion, &session->assertion_list, assertion_chain) {
905 if (uuid_compare(search_assertion->asserted_uuid, netagent_uuid) == 0) {
906 found_assertion = search_assertion;
907 break;
908 }
909 }
910
911 if (found_assertion == NULL) {
912 NETAGENTLOG0(LOG_ERR, "Netagent uuid not previously asserted");
913 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
914 goto fail;
915 }
916
917 LIST_REMOVE(found_assertion, assertion_chain);
918 FREE(found_assertion, M_NETAGENT);
919 found_assertion = NULL;
920
921 lck_rw_lock_shared(&netagent_lock);
922
923 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(netagent_uuid);
924 if (wrapper == NULL) {
925 lck_rw_done(&netagent_lock);
926 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
927 goto fail;
928 }
929
930 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER_UNASSERT);
931 if (error) {
932 lck_rw_done(&netagent_lock);
933 NETAGENTLOG(LOG_ERR, "Failed to trigger assert agent: %d", error);
934 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
935 goto fail;
936 }
937
938 lck_rw_done(&netagent_lock);
939
940 NETAGENTLOG0(LOG_DEBUG, "Unasserted agent");
941 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNASSERT, message_id);
942 return;
943fail:
944 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNASSERT, message_id, response_error);
945}
946
947static struct netagent_wrapper *
948netagent_find_agent_with_uuid(uuid_t uuid)
949{
950 struct netagent_wrapper *search_netagent = NULL;
951
952 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
953 if (uuid_compare(search_netagent->netagent.netagent_uuid, uuid) == 0) {
954 return (search_netagent);
955 }
956 }
957
958 return (NULL);
959}
960
961void
962netagent_post_updated_interfaces(uuid_t uuid)
963{
964 struct netagent_wrapper *wrapper = NULL;
965 lck_rw_lock_shared(&netagent_lock);
966 wrapper = netagent_find_agent_with_uuid(uuid);
967 lck_rw_done(&netagent_lock);
968
969 if (wrapper != NULL) {
970 netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES);
971 } else {
972 NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
973 }
974
975 return;
976}
977
978int
979netagent_ioctl(u_long cmd, caddr_t data)
980{
981 int error = 0;
982
983 lck_rw_lock_shared(&netagent_lock);
984 switch (cmd) {
985 case SIOCGIFAGENTDATA32: {
986 struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
987 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
988 if (wrapper == NULL) {
989 error = ENOENT;
990 break;
991 }
992 uuid_copy(ifsir32->netagent_uuid, wrapper->netagent.netagent_uuid);
993 memcpy(ifsir32->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir32->netagent_domain));
994 memcpy(ifsir32->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir32->netagent_type));
995 memcpy(ifsir32->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir32->netagent_desc));
996 ifsir32->netagent_flags = wrapper->netagent.netagent_flags;
997 if (ifsir32->netagent_data_size == 0) {
998 // First pass, client wants data size
999 ifsir32->netagent_data_size = wrapper->netagent.netagent_data_size;
1000 } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
1001 ifsir32->netagent_data_size == wrapper->netagent.netagent_data_size) {
1002 // Second pass, client wants data buffer filled out
1003 error = copyout(wrapper->netagent.netagent_data, ifsir32->netagent_data, wrapper->netagent.netagent_data_size);
1004 } else {
1005 error = EINVAL;
1006 }
1007 break;
1008 }
1009 case SIOCGIFAGENTDATA64: {
1010 struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
1011 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
1012 if (wrapper == NULL) {
1013 error = ENOENT;
1014 break;
1015 }
1016 uuid_copy(ifsir64->netagent_uuid, wrapper->netagent.netagent_uuid);
1017 memcpy(ifsir64->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir64->netagent_domain));
1018 memcpy(ifsir64->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir64->netagent_type));
1019 memcpy(ifsir64->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir64->netagent_desc));
1020 ifsir64->netagent_flags = wrapper->netagent.netagent_flags;
1021 if (ifsir64->netagent_data_size == 0) {
1022 // First pass, client wants data size
1023 ifsir64->netagent_data_size = wrapper->netagent.netagent_data_size;
1024 } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
1025 ifsir64->netagent_data_size == wrapper->netagent.netagent_data_size) {
1026 // Second pass, client wants data buffer filled out
1027 error = copyout(wrapper->netagent.netagent_data, ifsir64->netagent_data, wrapper->netagent.netagent_data_size);
1028 } else {
1029 error = EINVAL;
1030 }
1031 break;
1032 }
1033 default: {
1034 error = EINVAL;
1035 break;
1036 }
1037 }
1038 lck_rw_done(&netagent_lock);
1039 return (error);
1040}
1041
1042u_int32_t
1043netagent_get_flags(uuid_t uuid)
1044{
1045 u_int32_t flags = 0;
1046 lck_rw_lock_shared(&netagent_lock);
1047 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1048 if (wrapper != NULL) {
1049 flags = wrapper->netagent.netagent_flags;
1050 } else {
1051 NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
1052 }
1053 lck_rw_done(&netagent_lock);
1054
1055 return (flags);
1056}
1057
1058int
1059netagent_kernel_trigger(uuid_t uuid)
1060{
1061 int error = 0;
1062
1063 lck_rw_lock_shared(&netagent_lock);
1064 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1065 if (wrapper == NULL) {
1066 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
1067 error = ENOENT;
1068 goto done;
1069 }
1070
1071 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
1072 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
1073 // Agent does not accept kernel triggers
1074 error = EINVAL;
1075 goto done;
1076 }
1077
1078 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1079 // Agent already active
1080 NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
1081 error = 0;
1082 goto done;
1083 }
1084
1085 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
1086 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
1087done:
1088 lck_rw_done(&netagent_lock);
1089 return (error);
1090}
1091
1092int
1093netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
1094{
1095#pragma unused(p, retval)
1096 uuid_t agent_uuid;
1097 int error = 0;
1098
1099 if (uap == NULL) {
1100 NETAGENTLOG0(LOG_ERR, "uap == NULL");
1101 return (EINVAL);
1102 }
1103
1104 if (uap->agent_uuid) {
1105 if (uap->agent_uuidlen != sizeof(uuid_t)) {
1106 NETAGENTLOG(LOG_ERR, "Incorrect length (got %d, expected %d)",
1107 uap->agent_uuidlen, sizeof(uuid_t));
1108 return (ERANGE);
1109 }
1110
1111 error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
1112 if (error) {
1113 NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
1114 return (error);
1115 }
1116 }
1117
1118 if (uuid_is_null(agent_uuid)) {
1119 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
1120 return (EINVAL);
1121 }
1122
1123 lck_rw_lock_shared(&netagent_lock);
1124 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1125 if (wrapper == NULL) {
1126 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
1127 error = ENOENT;
1128 goto done;
1129 }
1130
1131 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1132 // Agent does not accept triggers
1133 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
1134 error = EINVAL;
1135 goto done;
1136 }
1137
1138 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1139 // Agent already active
1140 NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
1141 error = 0;
1142 goto done;
1143 }
1144
1145 error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
1146 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
1147done:
1148 lck_rw_done(&netagent_lock);
1149 return (error);
1150}