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