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