]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/network_agent.c
xnu-3789.70.16.tar.gz
[apple/xnu.git] / bsd / net / network_agent.c
1 /*
2 * Copyright (c) 2014, 2016, 2017 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", data_size);
750 response_error = EINVAL;
751 goto done;
752 }
753
754 if (payload_length != (sizeof(struct netagent) + data_size)) {
755 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent) + data_size), payload_length);
756 response_error = EINVAL;
757 goto done;
758 }
759
760 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
761 if (new_wrapper == NULL) {
762 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
763 response_error = ENOMEM;
764 goto done;
765 }
766
767 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
768 memcpy(&new_wrapper->netagent, register_netagent, sizeof(struct netagent) + data_size);
769
770 response_error = netagent_handle_register_inner(session, new_wrapper);
771 if (response_error != 0) {
772 FREE(new_wrapper, M_NETAGENT);
773 goto done;
774 }
775
776 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
777 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE);
778
779 done:
780 return response_error;
781 }
782
783 static void
784 netagent_handle_register_message(struct netagent_session *session, u_int32_t message_id,
785 u_int32_t payload_length, mbuf_t packet, int offset)
786 {
787 int error;
788 int data_size = 0;
789 struct netagent_wrapper *new_wrapper = NULL;
790 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
791 uuid_t netagent_uuid;
792 uuid_clear(netagent_uuid);
793
794 if (session == NULL) {
795 NETAGENTLOG0(LOG_ERR, "Failed to find session");
796 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
797 goto fail;
798 }
799
800 if (session->wrapper != NULL) {
801 NETAGENTLOG0(LOG_ERR, "Session already has a registered agent");
802 response_error = NETAGENT_MESSAGE_ERROR_ALREADY_REGISTERED;
803 goto fail;
804 }
805
806 if (payload_length < sizeof(struct netagent)) {
807 NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)",
808 payload_length, sizeof(struct netagent));
809 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
810 goto fail;
811 }
812
813 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
814 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
815 NETAGENTLOG(LOG_ERR, "Register message size could not be read, error %d data_size %d",
816 error, data_size);
817 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
818 goto fail;
819 }
820
821 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
822 if (new_wrapper == NULL) {
823 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
824 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
825 goto fail;
826 }
827
828 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
829
830 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size,
831 &new_wrapper->netagent);
832 if (error) {
833 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
834 FREE(new_wrapper, M_NETAGENT);
835 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
836 goto fail;
837 }
838
839 (void)netagent_handle_register_inner(session, new_wrapper);
840
841 NETAGENTLOG0(LOG_DEBUG, "Registered new agent");
842 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id);
843 netagent_post_event(new_wrapper->netagent.netagent_uuid, KEV_NETAGENT_REGISTERED, TRUE);
844 return;
845 fail:
846 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_REGISTER, message_id, response_error);
847 }
848
849 static errno_t
850 netagent_handle_unregister_setopt(struct netagent_session *session, u_int8_t *payload,
851 u_int32_t payload_length)
852 {
853 #pragma unused(payload, payload_length)
854 u_int32_t response_error = 0;
855
856 if (session == NULL) {
857 NETAGENTLOG0(LOG_ERR, "Failed to find session");
858 response_error = EINVAL;
859 goto done;
860 }
861
862 netagent_unregister_session_wrapper(session);
863
864 done:
865 return response_error;
866 }
867
868 static void
869 netagent_handle_unregister_message(struct netagent_session *session, u_int32_t message_id,
870 u_int32_t payload_length, mbuf_t packet, int offset)
871 {
872 #pragma unused(payload_length, packet, offset)
873 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
874
875 if (session == NULL) {
876 NETAGENTLOG0(LOG_ERR, "Failed to find session");
877 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
878 goto fail;
879 }
880
881 netagent_unregister_session_wrapper(session);
882
883 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id);
884 return;
885 fail:
886 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UNREGISTER, message_id, response_error);
887 }
888
889 static void
890 netagent_send_cellular_failed_event(struct netagent_wrapper *wrapper,
891 pid_t pid, uuid_t proc_uuid)
892 {
893 if (strncmp(wrapper->netagent.netagent_domain, "Cellular", NETAGENT_DOMAINSIZE) != 0) {
894 return;
895 }
896
897 struct kev_netpolicy_ifdenied ev_ifdenied;
898
899 bzero(&ev_ifdenied, sizeof(ev_ifdenied));
900
901 ev_ifdenied.ev_data.epid = pid;
902 uuid_copy(ev_ifdenied.ev_data.euuid, proc_uuid);
903 ev_ifdenied.ev_if_functional_type = IFRTYPE_FUNCTIONAL_CELLULAR;
904
905 netpolicy_post_msg(KEV_NETPOLICY_IFFAILED, &ev_ifdenied.ev_data, sizeof(ev_ifdenied));
906 }
907
908 static errno_t
909 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)
910 {
911 u_int32_t response_error = 0;
912
913 if (agent_changed == NULL) {
914 NETAGENTLOG0(LOG_ERR, "Invalid argument: agent_changed");
915 return EINVAL;
916 }
917
918 lck_rw_lock_exclusive(&netagent_lock);
919
920 if (uuid_compare(session->wrapper->netagent.netagent_uuid, new_wrapper->netagent.netagent_uuid) != 0 ||
921 memcmp(&session->wrapper->netagent.netagent_domain, &new_wrapper->netagent.netagent_domain,
922 sizeof(new_wrapper->netagent.netagent_domain)) != 0 ||
923 memcmp(&session->wrapper->netagent.netagent_type, &new_wrapper->netagent.netagent_type,
924 sizeof(new_wrapper->netagent.netagent_type)) != 0) {
925 lck_rw_done(&netagent_lock);
926 NETAGENTLOG0(LOG_ERR, "Basic agent parameters do not match, cannot update");
927 if (error_domain == kNetagentErrorDomainPOSIX) {
928 response_error = EINVAL;
929 } else if (error_domain == kNetagentErrorDomainUserDefined) {
930 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_UPDATE;
931 }
932 return response_error;
933 }
934
935 new_wrapper->netagent.netagent_flags |= NETAGENT_FLAG_REGISTERED;
936 if (session->wrapper->netagent.netagent_data_size == new_wrapper->netagent.netagent_data_size &&
937 memcmp(&session->wrapper->netagent, &new_wrapper->netagent, sizeof(struct netagent) + data_size) == 0) {
938 // Agent is exactly identical, don't increment the generation count
939
940 // Make a copy of the list of pending clients, and clear the current list
941 struct netagent_client_list_s pending_triggers_list_copy;
942 LIST_INIT(&pending_triggers_list_copy);
943 struct netagent_client *search_client = NULL;
944 struct netagent_client *temp_client = NULL;
945 LIST_FOREACH_SAFE(search_client, &session->wrapper->pending_triggers_list, client_chain, temp_client) {
946 LIST_REMOVE(search_client, client_chain);
947 LIST_INSERT_HEAD(&pending_triggers_list_copy, search_client, client_chain);
948 }
949 lck_rw_done(&netagent_lock);
950
951 // Update pending client triggers without holding a lock
952 search_client = NULL;
953 temp_client = NULL;
954 LIST_FOREACH_SAFE(search_client, &pending_triggers_list_copy, client_chain, temp_client) {
955 necp_force_update_client(search_client->client_id, session->wrapper->netagent.netagent_uuid);
956 netagent_send_cellular_failed_event(new_wrapper, search_client->client_pid, search_client->client_proc_uuid);
957 LIST_REMOVE(search_client, client_chain);
958 FREE(search_client, M_NETAGENT);
959 }
960 NETAGENTLOG0(LOG_DEBUG, "Updated agent (no changes)");
961 *agent_changed = FALSE;
962 return response_error;
963 }
964
965 new_wrapper->generation = g_next_generation++;
966 new_wrapper->use_count = session->wrapper->use_count;
967
968 if ((new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
969 !(session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
970 netagent_active_count++;
971 } else if (!(new_wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
972 (session->wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) &&
973 netagent_active_count > 0) {
974 netagent_active_count--;
975 }
976
977 LIST_REMOVE(session->wrapper, master_chain);
978 netagent_free_wrapper(session->wrapper);
979 session->wrapper = new_wrapper;
980 new_wrapper->control_unit = session->control_unit;
981 LIST_INSERT_HEAD(&master_netagent_list, new_wrapper, master_chain);
982 LIST_INIT(&new_wrapper->pending_triggers_list);
983
984 NETAGENTLOG0(LOG_DEBUG, "Updated agent");
985 *agent_changed = TRUE;
986
987 lck_rw_done(&netagent_lock);
988
989 return response_error;
990 }
991
992 static errno_t
993 netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payload, u_int32_t payload_length)
994 {
995 u_int32_t data_size = 0;
996 struct netagent_wrapper *new_wrapper = NULL;
997 errno_t response_error = 0;
998 struct netagent *update_netagent = (struct netagent *)(void *)payload;
999 u_int8_t agent_changed;
1000
1001 if (session == NULL) {
1002 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1003 response_error = EINVAL;
1004 goto done;
1005 }
1006
1007 if (payload == NULL) {
1008 NETAGENTLOG0(LOG_ERR, "No payload received");
1009 response_error = EINVAL;
1010 goto done;
1011 }
1012
1013 if (session->wrapper == NULL) {
1014 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1015 response_error = ENOENT;
1016 goto done;
1017 }
1018
1019 if (payload_length < sizeof(struct netagent)) {
1020 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)",
1021 payload_length, sizeof(struct netagent));
1022 response_error = EINVAL;
1023 goto done;
1024 }
1025
1026 data_size = update_netagent->netagent_data_size;
1027 if (data_size > NETAGENT_MAX_DATA_SIZE) {
1028 NETAGENTLOG(LOG_ERR, "Update message size (%u > %u) too large", data_size, NETAGENT_MAX_DATA_SIZE);
1029 response_error = EINVAL;
1030 goto done;
1031 }
1032
1033 if (payload_length != (sizeof(struct netagent) + data_size)) {
1034 NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent) + data_size), payload_length);
1035 response_error = EINVAL;
1036 goto done;
1037 }
1038
1039 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1040 if (new_wrapper == NULL) {
1041 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1042 response_error = ENOMEM;
1043 goto done;
1044 }
1045
1046 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1047 memcpy(&new_wrapper->netagent, update_netagent, sizeof(struct netagent) + data_size);
1048
1049 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed, kNetagentErrorDomainPOSIX);
1050 if (response_error == 0) {
1051 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed);
1052 if (agent_changed == FALSE) {
1053 // The session wrapper does not need the "new_wrapper" as nothing changed
1054 FREE(new_wrapper, M_NETAGENT);
1055 }
1056 } else {
1057 FREE(new_wrapper, M_NETAGENT);
1058 }
1059
1060 done:
1061 return response_error;
1062 }
1063
1064 static void
1065 netagent_handle_update_message(struct netagent_session *session, u_int32_t message_id,
1066 u_int32_t payload_length, mbuf_t packet, int offset)
1067 {
1068 int error;
1069 int data_size = 0;
1070 struct netagent_wrapper *new_wrapper = NULL;
1071 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1072 u_int8_t agent_changed;
1073
1074 if (session == NULL) {
1075 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1076 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1077 goto fail;
1078 }
1079
1080 if (session->wrapper == NULL) {
1081 NETAGENTLOG0(LOG_ERR, "Session has no agent to update");
1082 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1083 goto fail;
1084 }
1085
1086 if (payload_length < sizeof(struct netagent)) {
1087 NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)",
1088 payload_length, sizeof(struct netagent));
1089 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1090 goto fail;
1091 }
1092
1093 data_size = netagent_packet_get_netagent_data_size(packet, offset, &error);
1094 if (error || data_size < 0 || data_size > NETAGENT_MAX_DATA_SIZE) {
1095 NETAGENTLOG(LOG_ERR, "Update message size could not be read, error %d data_size %d",
1096 error, data_size);
1097 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1098 goto fail;
1099 }
1100
1101 MALLOC(new_wrapper, struct netagent_wrapper *, sizeof(*new_wrapper) + data_size, M_NETAGENT, M_WAITOK);
1102 if (new_wrapper == NULL) {
1103 NETAGENTLOG0(LOG_ERR, "Failed to allocate agent");
1104 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1105 goto fail;
1106 }
1107
1108 memset(new_wrapper, 0, sizeof(*new_wrapper) + data_size);
1109
1110 error = mbuf_copydata(packet, offset, sizeof(struct netagent) + data_size, &new_wrapper->netagent);
1111 if (error) {
1112 NETAGENTLOG(LOG_ERR, "Failed to read data into agent structure: %d", error);
1113 FREE(new_wrapper, M_NETAGENT);
1114 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1115 goto fail;
1116 }
1117
1118 response_error = netagent_handle_update_inner(session, new_wrapper, data_size, &agent_changed , kNetagentErrorDomainUserDefined);
1119 if (response_error != 0) {
1120 FREE(new_wrapper, M_NETAGENT);
1121 goto fail;
1122 }
1123
1124 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id);
1125 netagent_post_event(session->wrapper->netagent.netagent_uuid, KEV_NETAGENT_UPDATED, agent_changed);
1126
1127 if (agent_changed == FALSE) {
1128 // The session wrapper does not need the "new_wrapper" as nothing changed
1129 FREE(new_wrapper, M_NETAGENT);
1130 }
1131
1132 return;
1133 fail:
1134 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_UPDATE, message_id, response_error);
1135 }
1136
1137 static void
1138 netagent_handle_get(struct netagent_session *session, u_int32_t message_id,
1139 u_int32_t payload_length, mbuf_t packet, int offset)
1140 {
1141 #pragma unused(payload_length, packet, offset)
1142 u_int8_t *response = NULL;
1143 u_int8_t *cursor = NULL;
1144 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1145
1146 if (session == NULL) {
1147 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1148 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1149 goto fail;
1150 }
1151
1152 if (session->wrapper == NULL) {
1153 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1154 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1155 goto fail;
1156 }
1157
1158 lck_rw_lock_shared(&netagent_lock);
1159
1160 size_t response_size = sizeof(struct netagent_message_header) + sizeof(session->wrapper->netagent)
1161 + session->wrapper->netagent.netagent_data_size;
1162 MALLOC(response, u_int8_t *, response_size, M_NETAGENT, M_WAITOK);
1163 if (response == NULL) {
1164 goto fail;
1165 }
1166
1167 cursor = response;
1168 cursor = netagent_buffer_write_message_header(cursor, NETAGENT_MESSAGE_TYPE_GET,
1169 NETAGENT_MESSAGE_FLAGS_RESPONSE, message_id, 0,
1170 response_size - sizeof(struct netagent_message_header));
1171 memcpy(cursor, &session->wrapper->netagent, sizeof(session->wrapper->netagent) +
1172 session->wrapper->netagent.netagent_data_size);
1173
1174 lck_rw_done(&netagent_lock);
1175
1176 if (!netagent_send_ctl_data(session->control_unit, (u_int8_t *)response, response_size)) {
1177 NETAGENTLOG0(LOG_ERR, "Failed to send response");
1178 }
1179 FREE(response, M_NETAGENT);
1180 return;
1181 fail:
1182 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_GET, message_id, response_error);
1183 }
1184
1185 static errno_t
1186 netagent_handle_assign_nexus_setopt(struct netagent_session *session, u_int8_t *payload,
1187 u_int32_t payload_length)
1188 {
1189 errno_t response_error = 0;
1190 struct netagent_assign_nexus_message *assign_nexus_netagent = (struct netagent_assign_nexus_message *)(void *)payload;
1191 uuid_t client_id;
1192 u_int8_t *assigned_results = NULL;
1193
1194 if (session == NULL) {
1195 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1196 response_error = ENOENT;
1197 goto done;
1198 }
1199
1200 if (payload == NULL) {
1201 NETAGENTLOG0(LOG_ERR, "No payload received");
1202 response_error = EINVAL;
1203 goto done;
1204 }
1205
1206 if (session->wrapper == NULL) {
1207 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1208 response_error = ENOENT;
1209 goto done;
1210 }
1211
1212 if (payload_length < sizeof(uuid_t)) {
1213 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1214 response_error = EINVAL;
1215 goto done;
1216 }
1217
1218 memcpy(client_id, assign_nexus_netagent->assign_client_id, sizeof(client_id));
1219 size_t assigned_results_length = (payload_length - sizeof(client_id));
1220
1221 if (assigned_results_length > 0) {
1222 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1223 if (assigned_results == NULL) {
1224 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1225 response_error = ENOMEM;
1226 goto done;
1227 }
1228 memcpy(assigned_results, assign_nexus_netagent->assign_necp_results, assigned_results_length);
1229 }
1230
1231 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1232 response_error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1233 if (response_error) {
1234 // necp_assign_client_result returns POSIX errors
1235 if (assigned_results) {
1236 FREE(assigned_results, M_NETAGENT);
1237 }
1238 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", response_error);
1239 goto done;
1240 }
1241
1242 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1243 done:
1244 return response_error;
1245 }
1246
1247
1248 static void
1249 netagent_handle_assign_nexus_message(struct netagent_session *session, u_int32_t message_id,
1250 u_int32_t payload_length, mbuf_t packet, int offset)
1251 {
1252 int error = 0;
1253 u_int32_t response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1254 uuid_t client_id;
1255 u_int8_t *assigned_results = NULL;
1256
1257 if (session == NULL) {
1258 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1259 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1260 goto fail;
1261 }
1262
1263 if (session->wrapper == NULL) {
1264 NETAGENTLOG0(LOG_ERR, "Session has no agent to get");
1265 response_error = NETAGENT_MESSAGE_ERROR_NOT_REGISTERED;
1266 goto fail;
1267 }
1268
1269 if (payload_length < sizeof(uuid_t)) {
1270 NETAGENTLOG0(LOG_ERR, "Assign message is too short");
1271 response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA;
1272 goto fail;
1273 }
1274
1275 error = mbuf_copydata(packet, offset, sizeof(client_id), &client_id);
1276 if (error) {
1277 NETAGENTLOG(LOG_ERR, "Failed to read uuid for assign message: %d", error);
1278 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1279 goto fail;
1280 }
1281
1282 size_t assigned_results_length = (payload_length - sizeof(client_id));
1283 if (assigned_results_length > 0) {
1284 MALLOC(assigned_results, u_int8_t *, assigned_results_length, M_NETAGENT, M_WAITOK);
1285 if (assigned_results == NULL) {
1286 NETAGENTLOG(LOG_ERR, "Failed to allocate assign message (%lu bytes)", assigned_results_length);
1287 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1288 goto fail;
1289 }
1290
1291 error = mbuf_copydata(packet, offset + sizeof(client_id), assigned_results_length, assigned_results);
1292 if (error) {
1293 FREE(assigned_results, M_NETAGENT);
1294 NETAGENTLOG(LOG_ERR, "Failed to read assign message: %d", error);
1295 response_error = NETAGENT_MESSAGE_ERROR_INTERNAL;
1296 goto fail;
1297 }
1298 }
1299
1300 // Note that if the error is 0, NECP has taken over our malloc'ed buffer
1301 error = necp_assign_client_result(session->wrapper->netagent.netagent_uuid, client_id, assigned_results, assigned_results_length);
1302 if (error) {
1303 if (assigned_results) {
1304 FREE(assigned_results, M_NETAGENT);
1305 }
1306 NETAGENTLOG(LOG_ERR, "Client assignment failed: %d", error);
1307 response_error = NETAGENT_MESSAGE_ERROR_CANNOT_ASSIGN;
1308 goto fail;
1309 }
1310
1311 NETAGENTLOG0(LOG_DEBUG, "Agent assigned nexus properties to client");
1312 netagent_send_success_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id);
1313 return;
1314 fail:
1315 netagent_send_error_response(session, NETAGENT_MESSAGE_TYPE_ASSIGN_NEXUS, message_id, response_error);
1316 }
1317
1318 errno_t
1319 netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *payload, size_t payload_length)
1320 {
1321 errno_t response_error = 0;
1322 uint64_t use_count = 0;
1323
1324 if (session == NULL) {
1325 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1326 response_error = ENOENT;
1327 goto done;
1328 }
1329
1330 if (payload == NULL) {
1331 NETAGENTLOG0(LOG_ERR, "No payload received");
1332 response_error = EINVAL;
1333 goto done;
1334 }
1335
1336 if (payload_length != sizeof(use_count)) {
1337 NETAGENTLOG(LOG_ERR, "Payload length is invalid (%u)", payload_length);
1338 response_error = EINVAL;
1339 goto done;
1340 }
1341
1342 memcpy(&use_count, payload, sizeof(use_count));
1343
1344 lck_rw_lock_shared(&netagent_lock);
1345
1346 if (session->wrapper == NULL) {
1347 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1348 response_error = ENOENT;
1349 lck_rw_done(&netagent_lock);
1350 goto done;
1351 }
1352
1353 session->wrapper->use_count = use_count;
1354
1355 lck_rw_done(&netagent_lock);
1356
1357 done:
1358 return response_error;
1359 }
1360
1361 errno_t
1362 netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buffer, size_t *buffer_length)
1363 {
1364 errno_t response_error = 0;
1365 uint64_t use_count = 0;
1366
1367 if (session == NULL) {
1368 NETAGENTLOG0(LOG_ERR, "Failed to find session");
1369 response_error = ENOENT;
1370 goto done;
1371 }
1372
1373 if (buffer == NULL) {
1374 NETAGENTLOG0(LOG_ERR, "No payload received");
1375 response_error = EINVAL;
1376 goto done;
1377 }
1378
1379 if (*buffer_length != sizeof(use_count)) {
1380 NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%u)", buffer_length);
1381 response_error = EINVAL;
1382 goto done;
1383 }
1384
1385 lck_rw_lock_shared(&netagent_lock);
1386
1387 if (session->wrapper == NULL) {
1388 NETAGENTLOG0(LOG_ERR, "Session has no agent registered");
1389 response_error = ENOENT;
1390 lck_rw_done(&netagent_lock);
1391 goto done;
1392 }
1393
1394 use_count = session->wrapper->use_count;
1395 lck_rw_done(&netagent_lock);
1396
1397 memcpy(buffer, &use_count, sizeof(use_count));
1398 *buffer_length = sizeof(use_count);
1399
1400 done:
1401 return response_error;
1402 }
1403
1404 static struct netagent_wrapper *
1405 netagent_find_agent_with_uuid(uuid_t uuid)
1406 {
1407 struct netagent_wrapper *search_netagent = NULL;
1408
1409 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1410 if (uuid_compare(search_netagent->netagent.netagent_uuid, uuid) == 0) {
1411 return (search_netagent);
1412 }
1413 }
1414
1415 return (NULL);
1416 }
1417
1418 void
1419 netagent_post_updated_interfaces(uuid_t uuid)
1420 {
1421 struct netagent_wrapper *wrapper = NULL;
1422 lck_rw_lock_shared(&netagent_lock);
1423 wrapper = netagent_find_agent_with_uuid(uuid);
1424 lck_rw_done(&netagent_lock);
1425
1426 if (wrapper != NULL) {
1427 netagent_post_event(uuid, KEV_NETAGENT_UPDATED_INTERFACES, TRUE);
1428 } else {
1429 NETAGENTLOG0(LOG_DEBUG, "Interface event with no associated agent");
1430 }
1431
1432 return;
1433 }
1434
1435 static u_int32_t
1436 netagent_dump_get_data_size_locked()
1437 {
1438 struct netagent_wrapper *search_netagent = NULL;
1439 u_int32_t total_netagent_data_size = 0;
1440 // Traverse the master list to know how much data the client needs to allocate to get the list of agent UUIDs
1441 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1442 total_netagent_data_size += sizeof(search_netagent->netagent.netagent_uuid);
1443 }
1444 return total_netagent_data_size;
1445 }
1446
1447 static void
1448 netagent_dump_copy_data_locked(u_int8_t *buffer, u_int32_t buffer_length)
1449 {
1450 size_t response_size = 0;
1451 u_int8_t *cursor = NULL;
1452 struct netagent_wrapper *search_netagent = NULL;
1453
1454 response_size = buffer_length; // We already know that buffer_length is the same as total_netagent_data_size.
1455 cursor = buffer;
1456 LIST_FOREACH(search_netagent, &master_netagent_list, master_chain) {
1457 memcpy(cursor, search_netagent->netagent.netagent_uuid, sizeof(search_netagent->netagent.netagent_uuid));
1458 cursor += sizeof(search_netagent->netagent.netagent_uuid);
1459 }
1460 }
1461
1462 int
1463 netagent_ioctl(u_long cmd, caddr_t data)
1464 {
1465 int error = 0;
1466
1467 switch (cmd) {
1468 case SIOCGIFAGENTLIST32:
1469 case SIOCGIFAGENTLIST64: {
1470 /* Check entitlement if the client requests agent dump */
1471 errno_t cred_result = priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NECP_POLICIES, 0);
1472 if (cred_result != 0) {
1473 NETAGENTLOG0(LOG_ERR, "Client does not hold the necessary entitlement to get netagent information");
1474 return EINVAL;
1475 }
1476 break;
1477 }
1478 default:
1479 break;
1480 }
1481
1482 lck_rw_lock_shared(&netagent_lock);
1483 switch (cmd) {
1484 case SIOCGIFAGENTDATA32: {
1485 struct netagent_req32 *ifsir32 = (struct netagent_req32 *)(void *)data;
1486 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir32->netagent_uuid);
1487 if (wrapper == NULL) {
1488 error = ENOENT;
1489 break;
1490 }
1491 uuid_copy(ifsir32->netagent_uuid, wrapper->netagent.netagent_uuid);
1492 memcpy(ifsir32->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir32->netagent_domain));
1493 memcpy(ifsir32->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir32->netagent_type));
1494 memcpy(ifsir32->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir32->netagent_desc));
1495 ifsir32->netagent_flags = wrapper->netagent.netagent_flags;
1496 if (ifsir32->netagent_data_size == 0) {
1497 // First pass, client wants data size
1498 ifsir32->netagent_data_size = wrapper->netagent.netagent_data_size;
1499 } else if (ifsir32->netagent_data != USER_ADDR_NULL &&
1500 ifsir32->netagent_data_size == wrapper->netagent.netagent_data_size) {
1501 // Second pass, client wants data buffer filled out
1502 error = copyout(wrapper->netagent.netagent_data, ifsir32->netagent_data, wrapper->netagent.netagent_data_size);
1503 } else {
1504 error = EINVAL;
1505 }
1506 break;
1507 }
1508 case SIOCGIFAGENTDATA64: {
1509 struct netagent_req64 *ifsir64 = (struct netagent_req64 *)(void *)data;
1510 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(ifsir64->netagent_uuid);
1511 if (wrapper == NULL) {
1512 error = ENOENT;
1513 break;
1514 }
1515 uuid_copy(ifsir64->netagent_uuid, wrapper->netagent.netagent_uuid);
1516 memcpy(ifsir64->netagent_domain, wrapper->netagent.netagent_domain, sizeof(ifsir64->netagent_domain));
1517 memcpy(ifsir64->netagent_type, wrapper->netagent.netagent_type, sizeof(ifsir64->netagent_type));
1518 memcpy(ifsir64->netagent_desc, wrapper->netagent.netagent_desc, sizeof(ifsir64->netagent_desc));
1519 ifsir64->netagent_flags = wrapper->netagent.netagent_flags;
1520 if (ifsir64->netagent_data_size == 0) {
1521 // First pass, client wants data size
1522 ifsir64->netagent_data_size = wrapper->netagent.netagent_data_size;
1523 } else if (ifsir64->netagent_data != USER_ADDR_NULL &&
1524 ifsir64->netagent_data_size == wrapper->netagent.netagent_data_size) {
1525 // Second pass, client wants data buffer filled out
1526 error = copyout(wrapper->netagent.netagent_data, ifsir64->netagent_data, wrapper->netagent.netagent_data_size);
1527 } else {
1528 error = EINVAL;
1529 }
1530 break;
1531 }
1532 case SIOCGIFAGENTLIST32: {
1533 struct netagentlist_req32 *ifsir32 = (struct netagentlist_req32 *)(void *)data;
1534 if (ifsir32->data_size == 0) {
1535 // First pass, client wants data size
1536 ifsir32->data_size = netagent_dump_get_data_size_locked();
1537 } else if (ifsir32->data != USER_ADDR_NULL &&
1538 ifsir32->data_size > 0 &&
1539 ifsir32->data_size == netagent_dump_get_data_size_locked()) {
1540 // Second pass, client wants data buffer filled out
1541 u_int8_t *response = NULL;
1542 MALLOC(response, u_int8_t *, ifsir32->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1543 if (response == NULL) {
1544 error = ENOMEM;
1545 break;
1546 }
1547
1548 netagent_dump_copy_data_locked(response, ifsir32->data_size);
1549 error = copyout(response, ifsir32->data, ifsir32->data_size);
1550 FREE(response, M_NETAGENT);
1551 } else {
1552 error = EINVAL;
1553 }
1554 break;
1555 }
1556 case SIOCGIFAGENTLIST64: {
1557 struct netagentlist_req64 *ifsir64 = (struct netagentlist_req64 *)(void *)data;
1558 if (ifsir64->data_size == 0) {
1559 // First pass, client wants data size
1560 ifsir64->data_size = netagent_dump_get_data_size_locked();
1561 } else if (ifsir64->data != USER_ADDR_NULL &&
1562 ifsir64->data_size > 0 &&
1563 ifsir64->data_size == netagent_dump_get_data_size_locked()) {
1564 // Second pass, client wants data buffer filled out
1565 u_int8_t *response = NULL;
1566 MALLOC(response, u_int8_t *, ifsir64->data_size, M_NETAGENT, M_NOWAIT | M_ZERO);
1567 if (response == NULL) {
1568 error = ENOMEM;
1569 break;
1570 }
1571
1572 netagent_dump_copy_data_locked(response, ifsir64->data_size);
1573 error = copyout(response, ifsir64->data, ifsir64->data_size);
1574 FREE(response, M_NETAGENT);
1575 } else {
1576 error = EINVAL;
1577 }
1578 break;
1579 }
1580 default: {
1581 error = EINVAL;
1582 break;
1583 }
1584 }
1585 lck_rw_done(&netagent_lock);
1586 return (error);
1587 }
1588
1589 u_int32_t
1590 netagent_get_flags(uuid_t uuid)
1591 {
1592 u_int32_t flags = 0;
1593 lck_rw_lock_shared(&netagent_lock);
1594 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1595 if (wrapper != NULL) {
1596 flags = wrapper->netagent.netagent_flags;
1597 } else {
1598 NETAGENTLOG0(LOG_DEBUG, "Flags requested for invalid netagent");
1599 }
1600 lck_rw_done(&netagent_lock);
1601
1602 return (flags);
1603 }
1604
1605 u_int32_t
1606 netagent_get_generation(uuid_t uuid)
1607 {
1608 u_int32_t generation = 0;
1609 lck_rw_lock_shared(&netagent_lock);
1610 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1611 if (wrapper != NULL) {
1612 generation = wrapper->generation;
1613 } else {
1614 NETAGENTLOG0(LOG_DEBUG, "Generation requested for invalid netagent");
1615 }
1616 lck_rw_done(&netagent_lock);
1617
1618 return (generation);
1619 }
1620
1621 bool
1622 netagent_get_agent_domain_and_type(uuid_t uuid, char *domain, char *type)
1623 {
1624 bool found = FALSE;
1625 if (domain == NULL || type == NULL) {
1626 NETAGENTLOG(LOG_ERR, "Invalid arguments for netagent_get_agent_domain_and_type %p %p", domain, type);
1627 return (FALSE);
1628 }
1629
1630 lck_rw_lock_shared(&netagent_lock);
1631 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1632 if (wrapper != NULL) {
1633 found = TRUE;
1634 memcpy(domain, wrapper->netagent.netagent_domain, NETAGENT_DOMAINSIZE);
1635 memcpy(type, wrapper->netagent.netagent_type, NETAGENT_TYPESIZE);
1636 } else {
1637 NETAGENTLOG0(LOG_DEBUG, "Type requested for invalid netagent");
1638 }
1639 lck_rw_done(&netagent_lock);
1640
1641 return (found);
1642 }
1643
1644 int
1645 netagent_kernel_trigger(uuid_t uuid)
1646 {
1647 int error = 0;
1648
1649 lck_rw_lock_shared(&netagent_lock);
1650 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(uuid);
1651 if (wrapper == NULL) {
1652 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger could not be found");
1653 error = ENOENT;
1654 goto done;
1655 }
1656
1657 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_KERNEL_ACTIVATED) == 0) {
1658 NETAGENTLOG0(LOG_ERR, "Requested netagent for kernel trigger is not kernel activated");
1659 // Agent does not accept kernel triggers
1660 error = EINVAL;
1661 goto done;
1662 }
1663
1664 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1665 // Agent already active
1666 NETAGENTLOG0(LOG_INFO, "Requested netagent for kernel trigger is already active");
1667 error = 0;
1668 goto done;
1669 }
1670
1671 error = netagent_send_trigger(wrapper, current_proc(), NETAGENT_TRIGGER_FLAG_KERNEL, NETAGENT_MESSAGE_TYPE_TRIGGER);
1672 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent from kernel (error %d)", error);
1673 done:
1674 lck_rw_done(&netagent_lock);
1675 return (error);
1676 }
1677
1678 int
1679 netagent_client_message(uuid_t agent_uuid, uuid_t necp_client_uuid, u_int8_t message_type)
1680 {
1681 int error = 0;
1682
1683 if (message_type != NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER &&
1684 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT &&
1685 message_type != NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT &&
1686 message_type != NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS &&
1687 message_type != NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS) {
1688 NETAGENTLOG(LOG_ERR, "Client netagent message type (%d) is invalid", message_type);
1689 return(EINVAL);
1690 }
1691
1692 lck_rw_lock_shared(&netagent_lock);
1693 bool should_unlock = TRUE;
1694 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1695 if (wrapper == NULL) {
1696 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance could not be found");
1697 error = ENOENT;
1698 goto done;
1699 }
1700
1701 if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1702 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1703 // Agent does not accept user triggers
1704 // Don't log, since this is a common case used to trigger events that cellular data is blocked, etc.
1705 error = ENOTSUP;
1706
1707 struct proc *p = current_proc();
1708 pid_t current_pid = 0;
1709 uuid_t current_proc_uuid;
1710 uuid_clear(current_proc_uuid);
1711 if (p != NULL) {
1712 current_pid = proc_pid(p);
1713 proc_getexecutableuuid(p, current_proc_uuid, sizeof(current_proc_uuid));
1714 }
1715 netagent_send_cellular_failed_event(wrapper, current_pid, current_proc_uuid);
1716 goto done;
1717 }
1718 } else if (message_type == NETAGENT_MESSAGE_TYPE_REQUEST_NEXUS ||
1719 message_type == NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS) {
1720 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_NEXUS_PROVIDER) == 0) {
1721 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance is not a nexus provider");
1722 // Agent is not a nexus provider
1723 error = EINVAL;
1724 goto done;
1725 }
1726
1727 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE) == 0) {
1728 // Agent not active
1729 NETAGENTLOG0(LOG_INFO, "Requested netagent for nexus instance is not active");
1730 error = EINVAL;
1731 goto done;
1732 }
1733 }
1734
1735 error = netagent_send_client_message(wrapper, necp_client_uuid, message_type);
1736 if (error == 0 && message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) {
1737 if (lck_rw_lock_shared_to_exclusive(&netagent_lock)) {
1738 // Grab the lock exclusively to add a pending client to the list
1739 struct netagent_client *new_pending_client = NULL;
1740 MALLOC(new_pending_client, struct netagent_client *, sizeof(*new_pending_client), M_NETAGENT, M_WAITOK);
1741 if (new_pending_client == NULL) {
1742 NETAGENTLOG0(LOG_ERR, "Failed to allocate client for trigger");
1743 } else {
1744 uuid_copy(new_pending_client->client_id, necp_client_uuid);
1745 struct proc *p = current_proc();
1746 if (p != NULL) {
1747 new_pending_client->client_pid = proc_pid(p);
1748 proc_getexecutableuuid(p, new_pending_client->client_proc_uuid, sizeof(new_pending_client->client_proc_uuid));
1749 }
1750 LIST_INSERT_HEAD(&wrapper->pending_triggers_list, new_pending_client, client_chain);
1751 }
1752 } else {
1753 // If lck_rw_lock_shared_to_exclusive fails, it unlocks automatically
1754 should_unlock = FALSE;
1755 }
1756 }
1757 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error);
1758 done:
1759 if (should_unlock) {
1760 lck_rw_done(&netagent_lock);
1761 }
1762 return (error);
1763 }
1764
1765 int
1766 netagent_use(uuid_t agent_uuid, uint64_t *out_use_count)
1767 {
1768 int error = 0;
1769
1770 lck_rw_lock_exclusive(&netagent_lock);
1771 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1772 if (wrapper == NULL) {
1773 NETAGENTLOG0(LOG_ERR, "netagent_assert: Requested netagent UUID is not registered");
1774 error = ENOENT;
1775 goto done;
1776 }
1777
1778 uint64_t current_count = wrapper->use_count;
1779 wrapper->use_count++;
1780
1781 if (out_use_count != NULL) {
1782 *out_use_count = current_count;
1783 }
1784
1785 done:
1786 lck_rw_done(&netagent_lock);
1787 return (error);
1788 }
1789
1790 int
1791 netagent_copyout(uuid_t agent_uuid, user_addr_t user_addr, u_int32_t user_size)
1792 {
1793 int error = 0;
1794
1795 lck_rw_lock_shared(&netagent_lock);
1796 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1797 if (wrapper == NULL) {
1798 NETAGENTLOG0(LOG_ERR, "Requested netagent for nexus instance could not be found");
1799 error = ENOENT;
1800 goto done;
1801 }
1802
1803 u_int32_t total_size = (sizeof(struct netagent) + wrapper->netagent.netagent_data_size);
1804 if (user_size < total_size) {
1805 NETAGENTLOG(LOG_ERR, "Provided user buffer is too small (%u < %u)", user_size, total_size);
1806 error = EINVAL;
1807 goto done;
1808 }
1809
1810 error = copyout(&wrapper->netagent, user_addr, total_size);
1811
1812 NETAGENTLOG((error ? LOG_ERR : LOG_DEBUG), "Copied agent content (error %d)", error);
1813 done:
1814 lck_rw_done(&netagent_lock);
1815 return (error);
1816 }
1817
1818 int
1819 netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *retval)
1820 {
1821 #pragma unused(p, retval)
1822 uuid_t agent_uuid;
1823 int error = 0;
1824
1825 if (uap == NULL) {
1826 NETAGENTLOG0(LOG_ERR, "uap == NULL");
1827 return (EINVAL);
1828 }
1829
1830 if (uap->agent_uuid) {
1831 if (uap->agent_uuidlen != sizeof(uuid_t)) {
1832 NETAGENTLOG(LOG_ERR, "Incorrect length (got %d, expected %d)",
1833 uap->agent_uuidlen, sizeof(uuid_t));
1834 return (ERANGE);
1835 }
1836
1837 error = copyin(uap->agent_uuid, agent_uuid, sizeof(uuid_t));
1838 if (error) {
1839 NETAGENTLOG(LOG_ERR, "copyin error (%d)", error);
1840 return (error);
1841 }
1842 }
1843
1844 if (uuid_is_null(agent_uuid)) {
1845 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is empty");
1846 return (EINVAL);
1847 }
1848
1849 lck_rw_lock_shared(&netagent_lock);
1850 struct netagent_wrapper *wrapper = netagent_find_agent_with_uuid(agent_uuid);
1851 if (wrapper == NULL) {
1852 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not registered");
1853 error = ENOENT;
1854 goto done;
1855 }
1856
1857 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_USER_ACTIVATED) == 0) {
1858 // Agent does not accept triggers
1859 NETAGENTLOG0(LOG_ERR, "Requested netagent UUID is not eligible for triggering");
1860 error = ENOTSUP;
1861 goto done;
1862 }
1863
1864 if ((wrapper->netagent.netagent_flags & NETAGENT_FLAG_ACTIVE)) {
1865 // Agent already active
1866 NETAGENTLOG0(LOG_INFO, "Requested netagent UUID is already active");
1867 error = 0;
1868 goto done;
1869 }
1870
1871 error = netagent_send_trigger(wrapper, p, NETAGENT_TRIGGER_FLAG_USER, NETAGENT_MESSAGE_TYPE_TRIGGER);
1872 NETAGENTLOG((error ? LOG_ERR : LOG_INFO), "Triggered netagent (error %d)", error);
1873 done:
1874 lck_rw_done(&netagent_lock);
1875 return (error);
1876 }