]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/necp_client.c
xnu-4570.51.1.tar.gz
[apple/xnu.git] / bsd / net / necp_client.c
1 /*
2 * Copyright (c) 2015-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
31 #include <kern/thread_call.h>
32 #include <kern/zalloc.h>
33
34 #include <libkern/OSMalloc.h>
35
36 #include <net/if.h>
37 #include <net/if_var.h>
38 #include <net/net_api_stats.h>
39 #include <net/necp.h>
40 #include <net/network_agent.h>
41 #include <net/ntstat.h>
42
43 #include <netinet/in_pcb.h>
44 #include <netinet/ip.h>
45 #include <netinet/ip6.h>
46 #include <netinet/mp_pcb.h>
47 #include <netinet/tcp_cc.h>
48 #include <netinet/tcp_fsm.h>
49 #include <netinet/tcp_cache.h>
50 #include <netinet6/in6_var.h>
51
52 #include <sys/domain.h>
53 #include <sys/file_internal.h>
54 #include <sys/kauth.h>
55 #include <sys/kernel.h>
56 #include <sys/malloc.h>
57 #include <sys/poll.h>
58 #include <sys/priv.h>
59 #include <sys/protosw.h>
60 #include <sys/queue.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/sysproto.h>
64 #include <sys/systm.h>
65 #include <sys/types.h>
66 #include <sys/codesign.h>
67 #include <libkern/section_keywords.h>
68
69
70 /*
71 * NECP Client Architecture
72 * ------------------------------------------------
73 * See <net/necp.c> for a discussion on NECP database architecture.
74 *
75 * Each client of NECP provides a set of parameters for a connection or network state
76 * evaluation, on which NECP policy evaluation is run. This produces a policy result
77 * which can be accessed by the originating process, along with events for when policies
78 * results have changed.
79 *
80 * ------------------------------------------------
81 * NECP Client FD
82 * ------------------------------------------------
83 * A process opens an NECP file descriptor using necp_open(). This is a very simple
84 * file descriptor, upon which the process may do the following operations:
85 * - necp_client_action(...), to add/remove/query clients
86 * - kqueue, to watch for readable events
87 * - close(), to close the client session and release all clients
88 *
89 * Client objects are allocated structures that hang off of the file descriptor. Each
90 * client contains:
91 * - Client ID, a UUID that references the client across the system
92 * - Parameters, a buffer of TLVs that describe the client's connection parameters,
93 * such as the remote and local endpoints, interface requirements, etc.
94 * - Result, a buffer of TLVs containing the current policy evaluation for the client.
95 * This result will be updated whenever a network change occurs that impacts the
96 * policy result for that client.
97 *
98 * +--------------+
99 * | NECP fd |
100 * +--------------+
101 * ||
102 * ==================================
103 * || || ||
104 * +--------------+ +--------------+ +--------------+
105 * | Client ID | | Client ID | | Client ID |
106 * | ---- | | ---- | | ---- |
107 * | Parameters | | Parameters | | Parameters |
108 * | ---- | | ---- | | ---- |
109 * | Result | | Result | | Result |
110 * +--------------+ +--------------+ +--------------+
111 *
112 * ------------------------------------------------
113 * Client Actions
114 * ------------------------------------------------
115 * - Add. Input parameters as a buffer of TLVs, and output a client ID. Allocates a
116 * new client structure on the file descriptor.
117 * - Remove. Input a client ID. Removes a client structure from the file descriptor.
118 * - Copy Parameters. Input a client ID, and output parameter TLVs.
119 * - Copy Result. Input a client ID, and output result TLVs. Alternatively, input empty
120 * client ID and get next unread client result.
121 * - Copy List. List all client IDs.
122 *
123 * ------------------------------------------------
124 * Client Policy Evaluation
125 * ------------------------------------------------
126 * Policies are evaluated for clients upon client creation, and upon update events,
127 * which are network/agent/policy changes coalesced by a timer.
128 *
129 * The policy evaluation goes through the following steps:
130 * 1. Parse client parameters.
131 * 2. Select a scoped interface if applicable. This involves using require/prohibit
132 * parameters, along with the local address, to select the most appropriate interface
133 * if not explicitly set by the client parameters.
134 * 3. Run NECP application-level policy evalution
135 * 4. Set policy result into client result buffer.
136 *
137 * ------------------------------------------------
138 * Client Observers
139 * ------------------------------------------------
140 * If necp_open() is called with the NECP_OPEN_FLAG_OBSERVER flag, and the process
141 * passes the necessary privilege check, the fd is allowed to use necp_client_action()
142 * to copy client state attached to the file descriptors of other processes, and to
143 * list all client IDs on the system.
144 */
145
146 extern u_int32_t necp_debug;
147
148 // proc_best_name() is declared here in advance of it landing in a header file.
149 // See comment in kern_proc.c
150 extern char *proc_best_name(proc_t p);
151
152 static int noop_read(struct fileproc *, struct uio *, int, vfs_context_t);
153 static int noop_write(struct fileproc *, struct uio *, int, vfs_context_t);
154 static int noop_ioctl(struct fileproc *, unsigned long, caddr_t,
155 vfs_context_t);
156 static int necpop_select(struct fileproc *, int, void *, vfs_context_t);
157 static int necpop_close(struct fileglob *, vfs_context_t);
158 static int necpop_kqfilter(struct fileproc *, struct knote *,
159 struct kevent_internal_s *kev, vfs_context_t);
160
161 // Timer functions
162 static int necp_timeout_microseconds = 1000 * 100; // 100ms
163 static int necp_timeout_leeway_microseconds = 1000 * 500; // 500ms
164
165 static int necp_client_fd_count = 0;
166 static int necp_observer_fd_count = 0;
167 static int necp_client_count = 0;
168 static int necp_socket_flow_count = 0;
169 static int necp_if_flow_count = 0;
170 static int necp_observer_message_limit = 256;
171
172 SYSCTL_INT(_net_necp, NECPCTL_CLIENT_FD_COUNT, client_fd_count, CTLFLAG_LOCKED | CTLFLAG_RD, &necp_client_fd_count, 0, "");
173 SYSCTL_INT(_net_necp, NECPCTL_OBSERVER_FD_COUNT, observer_fd_count, CTLFLAG_LOCKED | CTLFLAG_RD, &necp_observer_fd_count, 0, "");
174 SYSCTL_INT(_net_necp, NECPCTL_CLIENT_COUNT, client_count, CTLFLAG_LOCKED | CTLFLAG_RD, &necp_client_count, 0, "");
175 SYSCTL_INT(_net_necp, NECPCTL_SOCKET_FLOW_COUNT, socket_flow_count, CTLFLAG_LOCKED | CTLFLAG_RD, &necp_socket_flow_count, 0, "");
176 SYSCTL_INT(_net_necp, NECPCTL_IF_FLOW_COUNT, if_flow_count, CTLFLAG_LOCKED | CTLFLAG_RD, &necp_if_flow_count, 0, "");
177 SYSCTL_INT(_net_necp, NECPCTL_OBSERVER_MESSAGE_LIMIT, observer_message_limit, CTLFLAG_LOCKED | CTLFLAG_RW, &necp_observer_message_limit, 256, "");
178
179 #define NECP_MAX_CLIENT_LIST_SIZE 1024 * 1024 // 1MB
180
181 extern int tvtohz(struct timeval *);
182 extern unsigned int get_maxmtu(struct rtentry *);
183
184 // Parsed parameters
185 #define NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR 0x00001
186 #define NECP_PARSED_PARAMETERS_FIELD_REMOTE_ADDR 0x00002
187 #define NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IF 0x00004
188 #define NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IF 0x00008
189 #define NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE 0x00010
190 #define NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IFTYPE 0x00020
191 #define NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT 0x00040
192 #define NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT 0x00080
193 #define NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT 0x00100
194 #define NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT_TYPE 0x00200
195 #define NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT_TYPE 0x00400
196 #define NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE 0x00800
197 #define NECP_PARSED_PARAMETERS_FIELD_FLAGS 0x01000
198 #define NECP_PARSED_PARAMETERS_FIELD_IP_PROTOCOL 0x02000
199 #define NECP_PARSED_PARAMETERS_FIELD_EFFECTIVE_PID 0x04000
200 #define NECP_PARSED_PARAMETERS_FIELD_EFFECTIVE_UUID 0x08000
201 #define NECP_PARSED_PARAMETERS_FIELD_TRAFFIC_CLASS 0x10000
202 #define NECP_PARSED_PARAMETERS_FIELD_LOCAL_PORT 0x20000
203
204 #define NECP_MAX_PARSED_PARAMETERS 16
205 struct necp_client_parsed_parameters {
206 u_int32_t valid_fields;
207 u_int32_t flags;
208 union necp_sockaddr_union local_addr;
209 union necp_sockaddr_union remote_addr;
210 u_int32_t required_interface_index;
211 char prohibited_interfaces[IFXNAMSIZ][NECP_MAX_PARSED_PARAMETERS];
212 u_int8_t required_interface_type;
213 u_int8_t prohibited_interface_types[NECP_MAX_PARSED_PARAMETERS];
214 struct necp_client_parameter_netagent_type required_netagent_types[NECP_MAX_PARSED_PARAMETERS];
215 struct necp_client_parameter_netagent_type prohibited_netagent_types[NECP_MAX_PARSED_PARAMETERS];
216 struct necp_client_parameter_netagent_type preferred_netagent_types[NECP_MAX_PARSED_PARAMETERS];
217 uuid_t required_netagents[NECP_MAX_PARSED_PARAMETERS];
218 uuid_t prohibited_netagents[NECP_MAX_PARSED_PARAMETERS];
219 uuid_t preferred_netagents[NECP_MAX_PARSED_PARAMETERS];
220 u_int16_t ip_protocol;
221 pid_t effective_pid;
222 uuid_t effective_uuid;
223 u_int32_t traffic_class;
224 };
225
226 static bool
227 necp_find_matching_interface_index(struct necp_client_parsed_parameters *parsed_parameters,
228 u_int *return_ifindex);
229
230 static bool
231 necp_ifnet_matches_local_address(struct ifnet *ifp, struct sockaddr *sa);
232
233 static bool
234 necp_ifnet_matches_parameters(struct ifnet *ifp,
235 struct necp_client_parsed_parameters *parsed_parameters,
236 u_int32_t *preferred_count, bool ignore_require_if);
237
238 static const struct fileops necp_fd_ops = {
239 .fo_type = DTYPE_NETPOLICY,
240 .fo_read = noop_read,
241 .fo_write = noop_write,
242 .fo_ioctl = noop_ioctl,
243 .fo_select = necpop_select,
244 .fo_close = necpop_close,
245 .fo_kqfilter = necpop_kqfilter,
246 .fo_drain = NULL,
247 };
248
249 struct necp_client_assertion {
250 LIST_ENTRY(necp_client_assertion) assertion_chain;
251 uuid_t asserted_netagent;
252 };
253
254 struct necp_client_flow_header {
255 struct necp_tlv_header outer_header;
256 struct necp_tlv_header flags_tlv_header;
257 u_int32_t flags_value;
258 struct necp_tlv_header interface_tlv_header;
259 struct necp_client_result_interface interface_value;
260 } __attribute__((__packed__));
261
262 struct necp_client_flow_protoctl_event_header {
263 struct necp_tlv_header protoctl_tlv_header;
264 struct necp_client_flow_protoctl_event protoctl_event;
265 } __attribute__((__packed__));
266
267 struct necp_client_nexus_flow_header {
268 struct necp_client_flow_header flow_header;
269 struct necp_tlv_header agent_tlv_header;
270 struct necp_client_result_netagent agent_value;
271 struct necp_tlv_header tfo_cookie_tlv_header;
272 u_int8_t tfo_cookie_value[NECP_TFO_COOKIE_LEN_MAX];
273 } __attribute__((__packed__));
274
275
276 struct necp_client {
277 RB_ENTRY(necp_client) link;
278 RB_ENTRY(necp_client) global_link;
279 LIST_ENTRY(necp_client) collect_stats_chain;
280
281 decl_lck_mtx_data(, lock);
282 decl_lck_mtx_data(, route_lock);
283 uint32_t reference_count;
284
285 uuid_t client_id;
286 unsigned result_read : 1;
287 unsigned flow_result_read : 1;
288 unsigned allow_multiple_flows : 1;
289
290 unsigned defunct : 1;
291 unsigned background : 1;
292 unsigned background_update : 1;
293 unsigned platform_binary : 1;
294
295 size_t result_length;
296 u_int8_t result[NECP_MAX_CLIENT_RESULT_SIZE];
297
298 necp_policy_id policy_id;
299
300 u_int16_t ip_protocol;
301 int proc_pid;
302
303 LIST_HEAD(_necp_client_flow_list, necp_client_flow) flow_list;
304 LIST_HEAD(_necp_client_assertion_list, necp_client_assertion) assertion_list;
305
306 struct rtentry *current_route;
307
308 void *interface_handle;
309 void (*interface_cb)(void *handle, int action, struct necp_client_flow *flow);
310
311 size_t parameters_length;
312 u_int8_t parameters[0];
313 };
314
315 #define NECP_CLIENT_LOCK(_c) lck_mtx_lock(&_c->lock)
316 #define NECP_CLIENT_UNLOCK(_c) lck_mtx_unlock(&_c->lock)
317 #define NECP_CLIENT_ASSERT_LOCKED(_c) LCK_MTX_ASSERT(&_c->lock, LCK_MTX_ASSERT_OWNED)
318 #define NECP_CLIENT_ASSERT_UNLOCKED(_c) LCK_MTX_ASSERT(&_c->lock, LCK_MTX_ASSERT_NOTOWNED)
319
320 #define NECP_CLIENT_ROUTE_LOCK(_c) lck_mtx_lock(&_c->route_lock)
321 #define NECP_CLIENT_ROUTE_UNLOCK(_c) lck_mtx_unlock(&_c->route_lock)
322
323 static void necp_client_retain_locked(struct necp_client *client);
324 static void necp_client_retain(struct necp_client *client);
325 static bool necp_client_release_locked(struct necp_client *client);
326
327 static void
328 necp_client_add_assertion(struct necp_client *client, uuid_t netagent_uuid);
329
330 static bool
331 necp_client_remove_assertion(struct necp_client *client, uuid_t netagent_uuid);
332
333 LIST_HEAD(_necp_client_list, necp_client);
334 static struct _necp_client_list necp_collect_stats_client_list;
335
336 struct necp_client_defunct {
337 LIST_ENTRY(necp_client_defunct) chain;
338
339 uuid_t client_id;
340 uuid_t nexus_agent;
341 int proc_pid;
342 };
343
344 LIST_HEAD(_necp_client_defunct_list, necp_client_defunct);
345
346 static int necp_client_id_cmp(struct necp_client *client0, struct necp_client *client1);
347
348 RB_HEAD(_necp_client_tree, necp_client);
349 RB_PROTOTYPE_PREV(_necp_client_tree, necp_client, link, necp_client_id_cmp);
350 RB_GENERATE_PREV(_necp_client_tree, necp_client, link, necp_client_id_cmp);
351
352 RB_HEAD(_necp_client_global_tree, necp_client);
353 RB_PROTOTYPE_PREV(_necp_client_global_tree, necp_client, global_link, necp_client_id_cmp);
354 RB_GENERATE_PREV(_necp_client_global_tree, necp_client, global_link, necp_client_id_cmp);
355
356 static struct _necp_client_global_tree necp_client_global_tree;
357
358 struct necp_client_update {
359 TAILQ_ENTRY(necp_client_update) chain;
360
361 uuid_t client_id;
362
363 size_t update_length;
364 struct necp_client_observer_update update;
365 };
366
367
368 struct necp_fd_data {
369 u_int8_t necp_fd_type;
370 LIST_ENTRY(necp_fd_data) chain;
371 struct _necp_client_tree clients;
372 TAILQ_HEAD(_necp_client_update_list, necp_client_update) update_list;
373 int update_count;
374 int flags;
375 int proc_pid;
376 decl_lck_mtx_data(, fd_lock);
377 struct selinfo si;
378 };
379
380 #define NECP_FD_LOCK(_f) lck_mtx_lock(&_f->fd_lock)
381 #define NECP_FD_UNLOCK(_f) lck_mtx_unlock(&_f->fd_lock)
382 #define NECP_FD_ASSERT_LOCKED(_f) LCK_MTX_ASSERT(&_f->fd_lock, LCK_MTX_ASSERT_OWNED)
383 #define NECP_FD_ASSERT_UNLOCKED(_f) LCK_MTX_ASSERT(&_f->fd_lock, LCK_MTX_ASSERT_NOTOWNED)
384
385 static LIST_HEAD(_necp_fd_list, necp_fd_data) necp_fd_list;
386 static LIST_HEAD(_necp_fd_observer_list, necp_fd_data) necp_fd_observer_list;
387
388 #define NECP_CLIENT_FD_ZONE_MAX 128
389 #define NECP_CLIENT_FD_ZONE_NAME "necp.clientfd"
390
391 static unsigned int necp_client_fd_size; /* size of zone element */
392 static struct zone *necp_client_fd_zone; /* zone for necp_fd_data */
393
394 #define NECP_FLOW_ZONE_MAX 512
395 #define NECP_FLOW_ZONE_NAME "necp.flow"
396
397 static unsigned int necp_flow_size; /* size of necp_client_flow */
398 static struct mcache *necp_flow_cache; /* cache for necp_client_flow */
399
400
401 static lck_grp_attr_t *necp_fd_grp_attr = NULL;
402 static lck_attr_t *necp_fd_mtx_attr = NULL;
403 static lck_grp_t *necp_fd_mtx_grp = NULL;
404
405 decl_lck_rw_data(static, necp_fd_lock);
406 decl_lck_rw_data(static, necp_observer_lock);
407 decl_lck_rw_data(static, necp_client_tree_lock);
408 decl_lck_rw_data(static, necp_collect_stats_list_lock);
409
410 #define NECP_STATS_LIST_LOCK_EXCLUSIVE() lck_rw_lock_exclusive(&necp_collect_stats_list_lock)
411 #define NECP_STATS_LIST_LOCK_SHARED() lck_rw_lock_shared(&necp_collect_stats_list_lock)
412 #define NECP_STATS_LIST_UNLOCK() lck_rw_done(&necp_collect_stats_list_lock)
413
414 #define NECP_CLIENT_TREE_LOCK_EXCLUSIVE() lck_rw_lock_exclusive(&necp_client_tree_lock)
415 #define NECP_CLIENT_TREE_LOCK_SHARED() lck_rw_lock_shared(&necp_client_tree_lock)
416 #define NECP_CLIENT_TREE_UNLOCK() lck_rw_done(&necp_client_tree_lock)
417
418 #define NECP_FD_LIST_LOCK_EXCLUSIVE() lck_rw_lock_exclusive(&necp_fd_lock)
419 #define NECP_FD_LIST_LOCK_SHARED() lck_rw_lock_shared(&necp_fd_lock)
420 #define NECP_FD_LIST_UNLOCK() lck_rw_done(&necp_fd_lock)
421
422 #define NECP_OBSERVER_LIST_LOCK_EXCLUSIVE() lck_rw_lock_exclusive(&necp_observer_lock)
423 #define NECP_OBSERVER_LIST_LOCK_SHARED() lck_rw_lock_shared(&necp_observer_lock)
424 #define NECP_OBSERVER_LIST_UNLOCK() lck_rw_done(&necp_observer_lock)
425
426 // Locking Notes
427
428 // Take NECP_FD_LIST_LOCK when accessing or modifying the necp_fd_list
429 // Take NECP_CLIENT_TREE_LOCK when accessing or modifying the necp_client_global_tree
430 // Take NECP_STATS_LIST_LOCK when accessing or modifying the necp_collect_stats_client_list
431 // Take NECP_FD_LOCK when accessing or modifying an necp_fd_data entry
432 // Take NECP_CLIENT_LOCK when accessing or modifying a single necp_client
433 // Take NECP_CLIENT_ROUTE_LOCK when accessing or modifying a client's route
434
435 // Precedence, where 1 is the first lock that must be taken
436 // 1. NECP_FD_LIST_LOCK
437 // 2. NECP_FD_LOCK (any)
438 // 3. NECP_CLIENT_TREE_LOCK
439 // 4. NECP_CLIENT_LOCK (any)
440 // 5. NECP_STATS_LIST_LOCK
441 // 6. NECP_CLIENT_ROUTE_LOCK (any)
442
443 static thread_call_t necp_client_update_tcall;
444
445
446 /// NECP file descriptor functions
447
448 static int
449 noop_read(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
450 {
451 #pragma unused(fp, uio, flags, ctx)
452 return (ENXIO);
453 }
454
455 static int
456 noop_write(struct fileproc *fp, struct uio *uio, int flags,
457 vfs_context_t ctx)
458 {
459 #pragma unused(fp, uio, flags, ctx)
460 return (ENXIO);
461 }
462
463 static int
464 noop_ioctl(struct fileproc *fp, unsigned long com, caddr_t data,
465 vfs_context_t ctx)
466 {
467 #pragma unused(fp, com, data, ctx)
468 return (ENOTTY);
469 }
470
471 static void
472 necp_fd_notify(struct necp_fd_data *fd_data, bool locked)
473 {
474 struct selinfo *si = &fd_data->si;
475
476 if (!locked) {
477 NECP_FD_LOCK(fd_data);
478 }
479
480 selwakeup(si);
481
482 // use a non-zero hint to tell the notification from the
483 // call done in kqueue_scan() which uses 0
484 KNOTE(&si->si_note, 1); // notification
485
486 if (!locked) {
487 NECP_FD_UNLOCK(fd_data);
488 }
489 }
490
491 static int
492 necp_fd_poll(struct necp_fd_data *fd_data, int events, void *wql, struct proc *p, int is_kevent)
493 {
494 #pragma unused(wql, p, is_kevent)
495 u_int revents = 0;
496
497 u_int want_rx = events & (POLLIN | POLLRDNORM);
498 if (want_rx) {
499 if (fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER) {
500 // Push-mode observers are readable when they have a new update
501 if (!TAILQ_EMPTY(&fd_data->update_list)) {
502 revents |= want_rx;
503 }
504 } else {
505 // Standard fds are readable when some client is unread
506 struct necp_client *client = NULL;
507 bool has_unread_clients = FALSE;
508 RB_FOREACH(client, _necp_client_tree, &fd_data->clients) {
509 NECP_CLIENT_LOCK(client);
510 if (!client->result_read || !client->flow_result_read) {
511 has_unread_clients = TRUE;
512 }
513 NECP_CLIENT_UNLOCK(client);
514 if (has_unread_clients) {
515 break;
516 }
517 }
518
519 if (has_unread_clients) {
520 revents |= want_rx;
521 }
522 }
523 }
524
525 return (revents);
526 }
527
528 static struct necp_client *
529 necp_client_fd_find_client_and_lock(struct necp_fd_data *client_fd, uuid_t client_id)
530 {
531 struct necp_client find;
532 NECP_FD_ASSERT_LOCKED(client_fd);
533 uuid_copy(find.client_id, client_id);
534 struct necp_client *client = RB_FIND(_necp_client_tree, &client_fd->clients, &find);
535
536 if (client != NULL) {
537 NECP_CLIENT_LOCK(client);
538 }
539
540 return (client);
541 }
542
543 static inline int
544 necp_client_id_cmp(struct necp_client *client0, struct necp_client *client1)
545 {
546 return (uuid_compare(client0->client_id, client1->client_id));
547 }
548
549 static int
550 necpop_select(struct fileproc *fp, int which, void *wql, vfs_context_t ctx)
551 {
552 #pragma unused(fp, which, wql, ctx)
553 return (0);
554 struct necp_fd_data *fd_data = NULL;
555 int revents = 0;
556 int events = 0;
557 proc_t procp;
558
559 fd_data = (struct necp_fd_data *)fp->f_fglob->fg_data;
560 if (fd_data == NULL) {
561 return (0);
562 }
563
564 procp = vfs_context_proc(ctx);
565
566 switch (which) {
567 case FREAD: {
568 events = POLLIN;
569 break;
570 }
571
572 default: {
573 return (1);
574 }
575 }
576
577 NECP_FD_LOCK(fd_data);
578 revents = necp_fd_poll(fd_data, events, wql, procp, 0);
579 NECP_FD_UNLOCK(fd_data);
580
581 return ((events & revents) ? 1 : 0);
582 }
583
584 static void
585 necp_fd_knrdetach(struct knote *kn)
586 {
587 struct necp_fd_data *fd_data = (struct necp_fd_data *)kn->kn_hook;
588 struct selinfo *si = &fd_data->si;
589
590 NECP_FD_LOCK(fd_data);
591 KNOTE_DETACH(&si->si_note, kn);
592 NECP_FD_UNLOCK(fd_data);
593 }
594
595 static int
596 necp_fd_knread(struct knote *kn, long hint)
597 {
598 #pragma unused(kn, hint)
599 return 1; /* assume we are ready */
600 }
601
602 static int
603 necp_fd_knrprocess(struct knote *kn, struct filt_process_s *data, struct kevent_internal_s *kev)
604 {
605 #pragma unused(data)
606 struct necp_fd_data *fd_data;
607 int revents;
608 int res;
609
610 fd_data = (struct necp_fd_data *)kn->kn_hook;
611
612 NECP_FD_LOCK(fd_data);
613 revents = necp_fd_poll(fd_data, POLLIN, NULL, current_proc(), 1);
614 res = ((revents & POLLIN) != 0);
615 if (res) {
616 *kev = kn->kn_kevent;
617 }
618 NECP_FD_UNLOCK(fd_data);
619 return (res);
620 }
621
622 static int
623 necp_fd_knrtouch(struct knote *kn, struct kevent_internal_s *kev)
624 {
625 #pragma unused(kev)
626 struct necp_fd_data *fd_data;
627 int revents;
628
629 fd_data = (struct necp_fd_data *)kn->kn_hook;
630
631 NECP_FD_LOCK(fd_data);
632 if ((kn->kn_status & KN_UDATA_SPECIFIC) == 0)
633 kn->kn_udata = kev->udata;
634 revents = necp_fd_poll(fd_data, POLLIN, NULL, current_proc(), 1);
635 NECP_FD_UNLOCK(fd_data);
636
637 return ((revents & POLLIN) != 0);
638 }
639
640 SECURITY_READ_ONLY_EARLY(struct filterops) necp_fd_rfiltops = {
641 .f_isfd = 1,
642 .f_detach = necp_fd_knrdetach,
643 .f_event = necp_fd_knread,
644 .f_touch = necp_fd_knrtouch,
645 .f_process = necp_fd_knrprocess,
646 };
647
648 static int
649 necpop_kqfilter(struct fileproc *fp, struct knote *kn,
650 __unused struct kevent_internal_s *kev, vfs_context_t ctx)
651 {
652 #pragma unused(fp, ctx)
653 struct necp_fd_data *fd_data = NULL;
654 int revents;
655
656 if (kn->kn_filter != EVFILT_READ) {
657 NECPLOG(LOG_ERR, "bad filter request %d", kn->kn_filter);
658 kn->kn_flags = EV_ERROR;
659 kn->kn_data = EINVAL;
660 return (0);
661 }
662
663 fd_data = (struct necp_fd_data *)kn->kn_fp->f_fglob->fg_data;
664 if (fd_data == NULL) {
665 NECPLOG0(LOG_ERR, "No channel for kqfilter");
666 kn->kn_flags = EV_ERROR;
667 kn->kn_data = ENOENT;
668 return (0);
669 }
670
671 NECP_FD_LOCK(fd_data);
672 kn->kn_filtid = EVFILTID_NECP_FD;
673 kn->kn_hook = fd_data;
674 KNOTE_ATTACH(&fd_data->si.si_note, kn);
675
676 revents = necp_fd_poll(fd_data, POLLIN, NULL, current_proc(), 1);
677
678 NECP_FD_UNLOCK(fd_data);
679
680 return ((revents & POLLIN) != 0);
681 }
682
683
684 static bool
685 necp_set_client_defunct(struct necp_client *client)
686 {
687 bool updated = FALSE;
688 u_int32_t flags = 0;
689 u_int32_t value_size = 0;
690
691 client->defunct = TRUE;
692
693 u_int8_t *flags_pointer = necp_buffer_get_tlv_value(client->result, 0, &value_size);
694 if (flags_pointer && value_size == sizeof(flags)) {
695 memcpy(&flags, flags_pointer, value_size);
696
697 flags |= NECP_CLIENT_RESULT_FLAG_DEFUNCT;
698
699 (void)necp_buffer_write_tlv_if_different(client->result, NECP_CLIENT_RESULT_FLAGS,
700 sizeof(flags), &flags, &updated, client->result, sizeof(client->result));
701
702 if (updated) {
703 client->result_read = FALSE;
704 }
705 }
706
707 return (updated);
708 }
709
710 static void
711 necp_defunct_client_for_policy(struct necp_client *client,
712 struct _necp_client_defunct_list *defunct_list)
713 {
714 NECP_CLIENT_ASSERT_LOCKED(client);
715
716 if (!client->defunct) {
717 bool needs_defunct = false;
718 struct necp_client_flow *search_flow = NULL;
719 LIST_FOREACH(search_flow, &client->flow_list, flow_chain) {
720 if (search_flow->nexus &&
721 !uuid_is_null(search_flow->u.nexus_agent) &&
722 search_flow->requested_nexus) {
723
724 // Save defunct values for the nexus
725 if (defunct_list != NULL) {
726 // Sleeping alloc won't fail; copy only what's necessary
727 struct necp_client_defunct *client_defunct = _MALLOC(sizeof (struct necp_client_defunct),
728 M_NECP, M_WAITOK | M_ZERO);
729 uuid_copy(client_defunct->nexus_agent, search_flow->u.nexus_agent);
730 uuid_copy(client_defunct->client_id, client->client_id);
731 client_defunct->proc_pid = client->proc_pid;
732
733 // Add to the list provided by caller
734 LIST_INSERT_HEAD(defunct_list, client_defunct, chain);
735 }
736
737 needs_defunct = true;
738 }
739 }
740
741 if (needs_defunct) {
742 // Only set defunct if there was some assigned flow
743 client->defunct = true;
744 }
745 }
746 }
747
748 static void
749 necp_client_free(struct necp_client *client)
750 {
751 NECP_CLIENT_ASSERT_LOCKED(client);
752
753 NECP_CLIENT_UNLOCK(client);
754
755 lck_mtx_destroy(&client->route_lock, necp_fd_mtx_grp);
756 lck_mtx_destroy(&client->lock, necp_fd_mtx_grp);
757
758 FREE(client, M_NECP);
759 }
760
761 static void
762 necp_client_retain_locked(struct necp_client *client)
763 {
764 NECP_CLIENT_ASSERT_LOCKED(client);
765
766 client->reference_count++;
767 ASSERT(client->reference_count != 0);
768 }
769
770 static void
771 necp_client_retain(struct necp_client *client)
772 {
773 NECP_CLIENT_LOCK(client);
774 necp_client_retain_locked(client);
775 NECP_CLIENT_UNLOCK(client);
776 }
777
778 static bool
779 necp_client_release_locked(struct necp_client *client)
780 {
781 NECP_CLIENT_ASSERT_LOCKED(client);
782
783 uint32_t old_ref = client->reference_count;
784
785 ASSERT(client->reference_count != 0);
786 if (--client->reference_count == 0) {
787 necp_client_free(client);
788 }
789
790 return (old_ref == 1);
791 }
792
793
794 static void
795 necp_client_update_observer_add_internal(struct necp_fd_data *observer_fd, struct necp_client *client)
796 {
797 NECP_FD_LOCK(observer_fd);
798
799 if (observer_fd->update_count >= necp_observer_message_limit) {
800 NECP_FD_UNLOCK(observer_fd);
801 return;
802 }
803
804 struct necp_client_update *client_update = _MALLOC(sizeof(struct necp_client_update) + client->parameters_length,
805 M_NECP, M_WAITOK | M_ZERO);
806 if (client_update != NULL) {
807 client_update->update_length = sizeof(struct necp_client_observer_update) + client->parameters_length;
808 uuid_copy(client_update->client_id, client->client_id);
809 client_update->update.update_type = NECP_CLIENT_UPDATE_TYPE_PARAMETERS;
810 memcpy(client_update->update.tlv_buffer, client->parameters, client->parameters_length);
811 TAILQ_INSERT_TAIL(&observer_fd->update_list, client_update, chain);
812 observer_fd->update_count++;
813
814 necp_fd_notify(observer_fd, true);
815 }
816
817 NECP_FD_UNLOCK(observer_fd);
818 }
819
820 static void
821 necp_client_update_observer_update_internal(struct necp_fd_data *observer_fd, struct necp_client *client)
822 {
823 NECP_FD_LOCK(observer_fd);
824
825 if (observer_fd->update_count >= necp_observer_message_limit) {
826 NECP_FD_UNLOCK(observer_fd);
827 return;
828 }
829
830 struct necp_client_update *client_update = _MALLOC(sizeof(struct necp_client_update) + client->result_length,
831 M_NECP, M_WAITOK | M_ZERO);
832 if (client_update != NULL) {
833 client_update->update_length = sizeof(struct necp_client_observer_update) + client->result_length;
834 uuid_copy(client_update->client_id, client->client_id);
835 client_update->update.update_type = NECP_CLIENT_UPDATE_TYPE_RESULT;
836 memcpy(client_update->update.tlv_buffer, client->result, client->result_length);
837 TAILQ_INSERT_TAIL(&observer_fd->update_list, client_update, chain);
838 observer_fd->update_count++;
839
840 necp_fd_notify(observer_fd, true);
841 }
842
843 NECP_FD_UNLOCK(observer_fd);
844 }
845
846 static void
847 necp_client_update_observer_remove_internal(struct necp_fd_data *observer_fd, struct necp_client *client)
848 {
849 NECP_FD_LOCK(observer_fd);
850
851 if (observer_fd->update_count >= necp_observer_message_limit) {
852 NECP_FD_UNLOCK(observer_fd);
853 return;
854 }
855
856 struct necp_client_update *client_update = _MALLOC(sizeof(struct necp_client_update),
857 M_NECP, M_WAITOK | M_ZERO);
858 if (client_update != NULL) {
859 client_update->update_length = sizeof(struct necp_client_observer_update);
860 uuid_copy(client_update->client_id, client->client_id);
861 client_update->update.update_type = NECP_CLIENT_UPDATE_TYPE_REMOVE;
862 TAILQ_INSERT_TAIL(&observer_fd->update_list, client_update, chain);
863 observer_fd->update_count++;
864
865 necp_fd_notify(observer_fd, true);
866 }
867
868 NECP_FD_UNLOCK(observer_fd);
869 }
870
871 static void
872 necp_client_update_observer_add(struct necp_client *client)
873 {
874 NECP_OBSERVER_LIST_LOCK_SHARED();
875
876 if (LIST_EMPTY(&necp_fd_observer_list)) {
877 // No observers, bail
878 NECP_OBSERVER_LIST_UNLOCK();
879 return;
880 }
881
882 struct necp_fd_data *observer_fd = NULL;
883 LIST_FOREACH(observer_fd, &necp_fd_observer_list, chain) {
884 necp_client_update_observer_add_internal(observer_fd, client);
885 }
886
887 NECP_OBSERVER_LIST_UNLOCK();
888 }
889
890 static void
891 necp_client_update_observer_update(struct necp_client *client)
892 {
893 NECP_OBSERVER_LIST_LOCK_SHARED();
894
895 if (LIST_EMPTY(&necp_fd_observer_list)) {
896 // No observers, bail
897 NECP_OBSERVER_LIST_UNLOCK();
898 return;
899 }
900
901 struct necp_fd_data *observer_fd = NULL;
902 LIST_FOREACH(observer_fd, &necp_fd_observer_list, chain) {
903 necp_client_update_observer_update_internal(observer_fd, client);
904 }
905
906 NECP_OBSERVER_LIST_UNLOCK();
907 }
908
909 static void
910 necp_client_update_observer_remove(struct necp_client *client)
911 {
912 NECP_OBSERVER_LIST_LOCK_SHARED();
913
914 if (LIST_EMPTY(&necp_fd_observer_list)) {
915 // No observers, bail
916 NECP_OBSERVER_LIST_UNLOCK();
917 return;
918 }
919
920 struct necp_fd_data *observer_fd = NULL;
921 LIST_FOREACH(observer_fd, &necp_fd_observer_list, chain) {
922 necp_client_update_observer_remove_internal(observer_fd, client);
923 }
924
925 NECP_OBSERVER_LIST_UNLOCK();
926 }
927
928 static void
929 necp_destroy_client(struct necp_client *client, pid_t pid, bool abort)
930 {
931 NECP_CLIENT_ASSERT_UNLOCKED(client);
932
933 necp_client_update_observer_remove(client);
934
935 NECP_CLIENT_LOCK(client);
936
937 // Free route
938 NECP_CLIENT_ROUTE_LOCK(client);
939 if (client->current_route != NULL) {
940 rtfree(client->current_route);
941 client->current_route = NULL;
942 }
943 NECP_CLIENT_ROUTE_UNLOCK(client);
944
945 // Remove flow assignments
946 struct necp_client_flow *search_flow = NULL;
947 struct necp_client_flow *temp_flow = NULL;
948 LIST_FOREACH_SAFE(search_flow, &client->flow_list, flow_chain, temp_flow) {
949 if (search_flow->nexus &&
950 !uuid_is_null(search_flow->u.nexus_agent) &&
951 search_flow->requested_nexus) {
952 // Note that if we had defuncted the client earlier, this would result in a harmless ENOENT
953 int netagent_error = netagent_client_message(search_flow->u.nexus_agent, client->client_id, pid,
954 abort ? NETAGENT_MESSAGE_TYPE_ABORT_NEXUS : NETAGENT_MESSAGE_TYPE_CLOSE_NEXUS);
955 if (netagent_error != 0 && netagent_error != ENOENT) {
956 NECPLOG(LOG_ERR, "necp_client_remove close nexus error (%d)", netagent_error);
957 }
958 uuid_clear(search_flow->u.nexus_agent);
959 }
960 if (search_flow->assigned_results != NULL) {
961 FREE(search_flow->assigned_results, M_NETAGENT);
962 search_flow->assigned_results = NULL;
963 }
964 LIST_REMOVE(search_flow, flow_chain);
965 if (search_flow->socket) {
966 OSDecrementAtomic(&necp_socket_flow_count);
967 } else {
968 OSDecrementAtomic(&necp_if_flow_count);
969 }
970 mcache_free(necp_flow_cache, search_flow);
971 }
972
973 // Remove agent assertions
974 struct necp_client_assertion *search_assertion = NULL;
975 struct necp_client_assertion *temp_assertion = NULL;
976 LIST_FOREACH_SAFE(search_assertion, &client->assertion_list, assertion_chain, temp_assertion) {
977 int netagent_error = netagent_client_message(search_assertion->asserted_netagent, client->client_id, pid, NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT);
978 if (netagent_error != 0) {
979 NECPLOG((netagent_error == ENOENT ? LOG_DEBUG : LOG_ERR),
980 "necp_client_remove unassert agent error (%d)", netagent_error);
981 }
982 LIST_REMOVE(search_assertion, assertion_chain);
983 FREE(search_assertion, M_NECP);
984 }
985
986 if (!necp_client_release_locked(client)) {
987 NECP_CLIENT_UNLOCK(client);
988 }
989
990 OSDecrementAtomic(&necp_client_count);
991 }
992
993 static int
994 necpop_close(struct fileglob *fg, vfs_context_t ctx)
995 {
996 #pragma unused(ctx)
997 struct necp_fd_data *fd_data = NULL;
998 int error = 0;
999
1000 fd_data = (struct necp_fd_data *)fg->fg_data;
1001 fg->fg_data = NULL;
1002
1003 if (fd_data != NULL) {
1004 struct _necp_client_tree clients_to_close;
1005 RB_INIT(&clients_to_close);
1006
1007 // Remove from list quickly
1008 if (fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER) {
1009 NECP_OBSERVER_LIST_LOCK_EXCLUSIVE();
1010 LIST_REMOVE(fd_data, chain);
1011 NECP_OBSERVER_LIST_UNLOCK();
1012 } else {
1013 NECP_FD_LIST_LOCK_EXCLUSIVE();
1014 LIST_REMOVE(fd_data, chain);
1015 NECP_FD_LIST_UNLOCK();
1016 }
1017
1018 NECP_FD_LOCK(fd_data);
1019 pid_t pid = fd_data->proc_pid;
1020 struct necp_client *client = NULL;
1021 struct necp_client *temp_client = NULL;
1022 RB_FOREACH_SAFE(client, _necp_client_tree, &fd_data->clients, temp_client) {
1023 NECP_CLIENT_TREE_LOCK_EXCLUSIVE();
1024 RB_REMOVE(_necp_client_global_tree, &necp_client_global_tree, client);
1025 NECP_CLIENT_TREE_UNLOCK();
1026 RB_REMOVE(_necp_client_tree, &fd_data->clients, client);
1027 RB_INSERT(_necp_client_tree, &clients_to_close, client);
1028 }
1029
1030 struct necp_client_update *client_update = NULL;
1031 struct necp_client_update *temp_update = NULL;
1032 TAILQ_FOREACH_SAFE(client_update, &fd_data->update_list, chain, temp_update) {
1033 // Flush pending updates
1034 TAILQ_REMOVE(&fd_data->update_list, client_update, chain);
1035 FREE(client_update, M_NECP);
1036 }
1037 fd_data->update_count = 0;
1038
1039
1040 NECP_FD_UNLOCK(fd_data);
1041
1042 selthreadclear(&fd_data->si);
1043
1044 lck_mtx_destroy(&fd_data->fd_lock, necp_fd_mtx_grp);
1045
1046 if (fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER) {
1047 OSDecrementAtomic(&necp_observer_fd_count);
1048 } else {
1049 OSDecrementAtomic(&necp_client_fd_count);
1050 }
1051
1052 zfree(necp_client_fd_zone, fd_data);
1053 fd_data = NULL;
1054
1055 RB_FOREACH_SAFE(client, _necp_client_tree, &clients_to_close, temp_client) {
1056 RB_REMOVE(_necp_client_tree, &clients_to_close, client);
1057 necp_destroy_client(client, pid, true);
1058 }
1059 }
1060
1061 return (error);
1062 }
1063
1064 /// NECP client utilities
1065
1066 static inline bool
1067 necp_address_is_wildcard(const union necp_sockaddr_union * const addr)
1068 {
1069 return ((addr->sa.sa_family == AF_INET && addr->sin.sin_addr.s_addr == INADDR_ANY) ||
1070 (addr->sa.sa_family == AF_INET6 && IN6_IS_ADDR_UNSPECIFIED(&addr->sin6.sin6_addr)));
1071 }
1072
1073 static int
1074 necp_find_fd_data(int fd, struct necp_fd_data **fd_data)
1075 {
1076 proc_t p = current_proc();
1077 struct fileproc *fp = NULL;
1078 int error = 0;
1079
1080 proc_fdlock_spin(p);
1081 if ((error = fp_lookup(p, fd, &fp, 1)) != 0) {
1082 goto done;
1083 }
1084 if (fp->f_fglob->fg_ops->fo_type != DTYPE_NETPOLICY) {
1085 fp_drop(p, fd, fp, 1);
1086 error = ENODEV;
1087 goto done;
1088 }
1089 *fd_data = (struct necp_fd_data *)fp->f_fglob->fg_data;
1090
1091 done:
1092 proc_fdunlock(p);
1093 return (error);
1094 }
1095
1096
1097 static void
1098 necp_client_add_socket_flow(struct necp_client *client, struct inpcb *inp)
1099 {
1100 struct necp_client_flow *new_flow = mcache_alloc(necp_flow_cache, MCR_SLEEP);
1101 if (new_flow == NULL) {
1102 NECPLOG0(LOG_ERR, "Failed to allocate socket flow");
1103 return;
1104 }
1105
1106 memset(new_flow, 0, sizeof(*new_flow));
1107
1108 new_flow->socket = TRUE;
1109 new_flow->u.socket_handle = inp;
1110 new_flow->u.cb = inp->necp_cb;
1111
1112 OSIncrementAtomic(&necp_socket_flow_count);
1113
1114 LIST_INSERT_HEAD(&client->flow_list, new_flow, flow_chain);
1115 }
1116
1117 static void
1118 necp_client_add_interface_flow(struct necp_client *client, uint32_t interface_index)
1119 {
1120 struct necp_client_flow *new_flow = mcache_alloc(necp_flow_cache, MCR_SLEEP);
1121 if (new_flow == NULL) {
1122 NECPLOG0(LOG_ERR, "Failed to allocate interface flow");
1123 return;
1124 }
1125
1126 memset(new_flow, 0, sizeof(*new_flow));
1127
1128 // Neither nexus nor socket
1129 new_flow->interface_index = interface_index;
1130 new_flow->u.socket_handle = client->interface_handle;
1131 new_flow->u.cb = client->interface_cb;
1132
1133 OSIncrementAtomic(&necp_if_flow_count);
1134
1135 LIST_INSERT_HEAD(&client->flow_list, new_flow, flow_chain);
1136 }
1137
1138 static void
1139 necp_client_add_interface_flow_if_needed(struct necp_client *client, uint32_t interface_index)
1140 {
1141 if (!client->allow_multiple_flows ||
1142 interface_index == IFSCOPE_NONE) {
1143 // Interface not set, or client not allowed to use this mode
1144 return;
1145 }
1146
1147 struct necp_client_flow *flow = NULL;
1148 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
1149 if (!flow->nexus && !flow->socket && flow->interface_index == interface_index) {
1150 // Already have the flow
1151 flow->invalid = FALSE;
1152
1153 flow->u.socket_handle = client->interface_handle;
1154 flow->u.cb = client->interface_cb;
1155 return;
1156 }
1157 }
1158
1159 necp_client_add_interface_flow(client, interface_index);
1160 }
1161
1162 static bool
1163 necp_client_flow_is_viable(proc_t proc, struct necp_client *client,
1164 struct necp_client_flow *flow)
1165 {
1166 struct necp_aggregate_result result;
1167 bool ignore_address = (client->allow_multiple_flows && !flow->nexus && !flow->socket);
1168
1169 flow->necp_flow_flags = 0;
1170 int error = necp_application_find_policy_match_internal(proc, client->parameters,
1171 (u_int32_t)client->parameters_length,
1172 &result, &flow->necp_flow_flags,
1173 flow->interface_index,
1174 &flow->local_addr, &flow->remote_addr, NULL, ignore_address);
1175
1176 return (error == 0 &&
1177 result.routed_interface_index != IFSCOPE_NONE &&
1178 result.routing_result != NECP_KERNEL_POLICY_RESULT_DROP);
1179 }
1180
1181 static bool
1182 necp_client_update_flows(proc_t proc,
1183 struct necp_client *client,
1184 struct _necp_client_defunct_list *defunct_list,
1185 bool *defuncted_by_flow)
1186 {
1187 NECP_CLIENT_ASSERT_LOCKED(client);
1188
1189 bool client_updated = FALSE;
1190 struct necp_client_flow *flow = NULL;
1191 struct necp_client_flow *temp_flow = NULL;
1192 LIST_FOREACH_SAFE(flow, &client->flow_list, flow_chain, temp_flow) {
1193 // Check policy result for flow
1194 int old_flags = flow->necp_flow_flags;
1195 bool viable = necp_client_flow_is_viable(proc, client, flow);
1196
1197 // TODO: Defunct nexus flows that are blocked by policy
1198
1199 if (flow->viable != viable) {
1200 flow->viable = viable;
1201 client_updated = TRUE;
1202 }
1203
1204 if ((old_flags & (NECP_CLIENT_RESULT_FLAG_HAS_IPV4 | NECP_CLIENT_RESULT_FLAG_HAS_IPV6)) !=
1205 (flow->necp_flow_flags & (NECP_CLIENT_RESULT_FLAG_HAS_IPV4 | NECP_CLIENT_RESULT_FLAG_HAS_IPV6))) {
1206 client_updated = TRUE;
1207 }
1208
1209 if (flow->viable && client_updated && (flow->socket || (!flow->socket && !flow->nexus)) && flow->u.cb) {
1210 flow->u.cb(flow->u.socket_handle, NECP_CLIENT_CBACTION_VIABLE, flow);
1211 }
1212
1213 if (!flow->viable || flow->invalid) {
1214 if (client_updated && (flow->socket || (!flow->socket && !flow->nexus)) && flow->u.cb) {
1215 flow->u.cb(flow->u.socket_handle, NECP_CLIENT_CBACTION_NONVIABLE, flow);
1216 }
1217 // The callback might change the viable-flag of the
1218 // flow depending on its policy. Thus, we need to
1219 // check again the flags after the callback.
1220 }
1221
1222 (void)defunct_list;
1223 (void)defuncted_by_flow;
1224
1225 // Handle flows that no longer match
1226 if (!flow->viable || flow->invalid) {
1227 // Drop them as long as they aren't assigned data
1228 if (!flow->requested_nexus && !flow->assigned) {
1229 if (flow->assigned_results != NULL) {
1230 FREE(flow->assigned_results, M_NETAGENT);
1231 flow->assigned_results = NULL;
1232 client_updated = TRUE;
1233 }
1234 LIST_REMOVE(flow, flow_chain);
1235 if (flow->socket) {
1236 OSDecrementAtomic(&necp_socket_flow_count);
1237 } else {
1238 OSDecrementAtomic(&necp_if_flow_count);
1239 }
1240 mcache_free(necp_flow_cache, flow);
1241 }
1242 }
1243 }
1244
1245 return (client_updated);
1246 }
1247
1248 static void
1249 necp_client_mark_all_nonsocket_flows_as_invalid(struct necp_client *client)
1250 {
1251 struct necp_client_flow *flow = NULL;
1252 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
1253 if (!flow->socket) { // Socket flows are not marked as invalid
1254 flow->invalid = TRUE;
1255 }
1256 }
1257 }
1258
1259 static bool
1260 necp_netagent_applies_to_client(__unused struct necp_client *client,
1261 const struct necp_client_parsed_parameters *parameters,
1262 uuid_t netagent_uuid, bool allow_nexus,
1263 uint32_t interface_index, u_int16_t interface_flags)
1264 {
1265 #pragma unused(interface_index, interface_flags)
1266 bool applies = FALSE;
1267 u_int32_t flags = netagent_get_flags(netagent_uuid);
1268 if (!(flags & NETAGENT_FLAG_REGISTERED)) {
1269 // Unregistered agents never apply
1270 return (applies);
1271 }
1272
1273 if (!allow_nexus &&
1274 (flags & NETAGENT_FLAG_NEXUS_PROVIDER)) {
1275 // Hide nexus providers unless allowed
1276 // Direct interfaces and direct policies are allowed to use a nexus
1277 // Delegate interfaces or re-scoped interfaces are not allowed
1278 return (applies);
1279 }
1280
1281 if (flags & NETAGENT_FLAG_SPECIFIC_USE_ONLY) {
1282 // Specific use agents only apply when required
1283 bool required = FALSE;
1284 if (parameters != NULL) {
1285 // Check required agent UUIDs
1286 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
1287 if (uuid_is_null(parameters->required_netagents[i])) {
1288 break;
1289 }
1290 if (uuid_compare(parameters->required_netagents[i], netagent_uuid) == 0) {
1291 required = TRUE;
1292 break;
1293 }
1294 }
1295
1296 if (!required) {
1297 // Check required agent types
1298 bool fetched_type = FALSE;
1299 char netagent_domain[NETAGENT_DOMAINSIZE];
1300 char netagent_type[NETAGENT_TYPESIZE];
1301 memset(&netagent_domain, 0, NETAGENT_DOMAINSIZE);
1302 memset(&netagent_type, 0, NETAGENT_TYPESIZE);
1303
1304 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
1305 if (strlen(parameters->required_netagent_types[i].netagent_domain) == 0 ||
1306 strlen(parameters->required_netagent_types[i].netagent_type) == 0) {
1307 break;
1308 }
1309
1310 if (!fetched_type) {
1311 if (netagent_get_agent_domain_and_type(netagent_uuid, netagent_domain, netagent_type)) {
1312 fetched_type = TRUE;
1313 } else {
1314 break;
1315 }
1316 }
1317
1318 if ((strlen(parameters->required_netagent_types[i].netagent_domain) == 0 ||
1319 strncmp(netagent_domain, parameters->required_netagent_types[i].netagent_domain, NETAGENT_DOMAINSIZE) == 0) &&
1320 (strlen(parameters->required_netagent_types[i].netagent_type) == 0 ||
1321 strncmp(netagent_type, parameters->required_netagent_types[i].netagent_type, NETAGENT_TYPESIZE) == 0)) {
1322 required = TRUE;
1323 break;
1324 }
1325 }
1326 }
1327 }
1328
1329 applies = required;
1330 } else {
1331 applies = TRUE;
1332 }
1333
1334
1335 return (applies);
1336 }
1337
1338 static void
1339 necp_client_add_agent_flows_for_interface(struct necp_client *client,
1340 const struct necp_client_parsed_parameters *parsed_parameters,
1341 ifnet_t ifp)
1342 {
1343 if (ifp != NULL && ifp->if_agentids != NULL) {
1344 for (u_int32_t i = 0; i < ifp->if_agentcount; i++) {
1345 if (uuid_is_null(ifp->if_agentids[i])) {
1346 continue;
1347 }
1348 u_int16_t if_flags = nstat_ifnet_to_flags(ifp);
1349 // Relies on the side effect that nexus agents that apply will create flows
1350 (void)necp_netagent_applies_to_client(client, parsed_parameters, ifp->if_agentids[i], TRUE, ifp->if_index, if_flags);
1351 }
1352 }
1353 }
1354
1355 static inline bool
1356 necp_client_address_is_valid(struct sockaddr *address)
1357 {
1358 if (address->sa_family == AF_INET) {
1359 return (address->sa_len == sizeof(struct sockaddr_in));
1360 } else if (address->sa_family == AF_INET6) {
1361 return (address->sa_len == sizeof(struct sockaddr_in6));
1362 } else {
1363 return (FALSE);
1364 }
1365 }
1366
1367 static int
1368 necp_client_parse_parameters(u_int8_t *parameters,
1369 u_int32_t parameters_size,
1370 struct necp_client_parsed_parameters *parsed_parameters)
1371 {
1372 int error = 0;
1373 size_t offset = 0;
1374
1375 u_int32_t num_prohibited_interfaces = 0;
1376 u_int32_t num_prohibited_interface_types = 0;
1377 u_int32_t num_required_agents = 0;
1378 u_int32_t num_prohibited_agents = 0;
1379 u_int32_t num_preferred_agents = 0;
1380 u_int32_t num_required_agent_types = 0;
1381 u_int32_t num_prohibited_agent_types = 0;
1382 u_int32_t num_preferred_agent_types = 0;
1383
1384 if (parsed_parameters == NULL) {
1385 return (EINVAL);
1386 }
1387
1388 memset(parsed_parameters, 0, sizeof(struct necp_client_parsed_parameters));
1389
1390 while ((offset + sizeof(struct necp_tlv_header)) <= parameters_size) {
1391 u_int8_t type = necp_buffer_get_tlv_type(parameters, offset);
1392 u_int32_t length = necp_buffer_get_tlv_length(parameters, offset);
1393
1394 if (length > (parameters_size - (offset + sizeof(struct necp_tlv_header)))) {
1395 // If the length is larger than what can fit in the remaining parameters size, bail
1396 NECPLOG(LOG_ERR, "Invalid TLV length (%u)", length);
1397 break;
1398 }
1399
1400 if (length > 0) {
1401 u_int8_t *value = necp_buffer_get_tlv_value(parameters, offset, NULL);
1402 if (value != NULL) {
1403 switch (type) {
1404 case NECP_CLIENT_PARAMETER_BOUND_INTERFACE: {
1405 if (length <= IFXNAMSIZ && length > 0) {
1406 ifnet_t bound_interface = NULL;
1407 char interface_name[IFXNAMSIZ];
1408 memcpy(interface_name, value, length);
1409 interface_name[length - 1] = 0; // Make sure the string is NULL terminated
1410 if (ifnet_find_by_name(interface_name, &bound_interface) == 0) {
1411 parsed_parameters->required_interface_index = bound_interface->if_index;
1412 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IF;
1413 ifnet_release(bound_interface);
1414 }
1415 }
1416 break;
1417 }
1418 case NECP_CLIENT_PARAMETER_LOCAL_ADDRESS: {
1419 if (length >= sizeof(struct necp_policy_condition_addr)) {
1420 struct necp_policy_condition_addr *address_struct = (struct necp_policy_condition_addr *)(void *)value;
1421 if (necp_client_address_is_valid(&address_struct->address.sa)) {
1422 memcpy(&parsed_parameters->local_addr, &address_struct->address, sizeof(address_struct->address));
1423 if (!necp_address_is_wildcard(&parsed_parameters->local_addr)) {
1424 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR;
1425 }
1426 if ((parsed_parameters->local_addr.sa.sa_family == AF_INET && parsed_parameters->local_addr.sin.sin_port) ||
1427 (parsed_parameters->local_addr.sa.sa_family == AF_INET6 && parsed_parameters->local_addr.sin6.sin6_port)) {
1428 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_LOCAL_PORT;
1429 }
1430 }
1431 }
1432 break;
1433 }
1434 case NECP_CLIENT_PARAMETER_LOCAL_ENDPOINT: {
1435 if (length >= sizeof(struct necp_client_endpoint)) {
1436 struct necp_client_endpoint *endpoint = (struct necp_client_endpoint *)(void *)value;
1437 if (necp_client_address_is_valid(&endpoint->u.sa)) {
1438 memcpy(&parsed_parameters->local_addr, &endpoint->u.sa, sizeof(union necp_sockaddr_union));
1439 if (!necp_address_is_wildcard(&parsed_parameters->local_addr)) {
1440 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR;
1441 }
1442 if ((parsed_parameters->local_addr.sa.sa_family == AF_INET && parsed_parameters->local_addr.sin.sin_port) ||
1443 (parsed_parameters->local_addr.sa.sa_family == AF_INET6 && parsed_parameters->local_addr.sin6.sin6_port)) {
1444 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_LOCAL_PORT;
1445 }
1446 }
1447 }
1448 break;
1449 }
1450 case NECP_CLIENT_PARAMETER_REMOTE_ADDRESS: {
1451 if (length >= sizeof(struct necp_policy_condition_addr)) {
1452 struct necp_policy_condition_addr *address_struct = (struct necp_policy_condition_addr *)(void *)value;
1453 if (necp_client_address_is_valid(&address_struct->address.sa)) {
1454 memcpy(&parsed_parameters->remote_addr, &address_struct->address, sizeof(address_struct->address));
1455 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REMOTE_ADDR;
1456 }
1457 }
1458 break;
1459 }
1460 case NECP_CLIENT_PARAMETER_REMOTE_ENDPOINT: {
1461 if (length >= sizeof(struct necp_client_endpoint)) {
1462 struct necp_client_endpoint *endpoint = (struct necp_client_endpoint *)(void *)value;
1463 if (necp_client_address_is_valid(&endpoint->u.sa)) {
1464 memcpy(&parsed_parameters->remote_addr, &endpoint->u.sa, sizeof(union necp_sockaddr_union));
1465 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REMOTE_ADDR;
1466 }
1467 }
1468 break;
1469 }
1470 case NECP_CLIENT_PARAMETER_PROHIBIT_INTERFACE: {
1471 if (num_prohibited_interfaces >= NECP_MAX_PARSED_PARAMETERS) {
1472 break;
1473 }
1474 if (length <= IFXNAMSIZ && length > 0) {
1475 memcpy(parsed_parameters->prohibited_interfaces[num_prohibited_interfaces], value, length);
1476 parsed_parameters->prohibited_interfaces[num_prohibited_interfaces][length - 1] = 0; // Make sure the string is NULL terminated
1477 num_prohibited_interfaces++;
1478 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IF;
1479 }
1480 break;
1481 }
1482 case NECP_CLIENT_PARAMETER_REQUIRE_IF_TYPE: {
1483 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE) {
1484 break;
1485 }
1486 if (length >= sizeof(u_int8_t)) {
1487 memcpy(&parsed_parameters->required_interface_type, value, sizeof(u_int8_t));
1488 if (parsed_parameters->required_interface_type) {
1489 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE;
1490 }
1491 }
1492 break;
1493 }
1494 case NECP_CLIENT_PARAMETER_PROHIBIT_IF_TYPE: {
1495 if (num_prohibited_interface_types >= NECP_MAX_PARSED_PARAMETERS) {
1496 break;
1497 }
1498 if (length >= sizeof(u_int8_t)) {
1499 memcpy(&parsed_parameters->prohibited_interface_types[num_prohibited_interface_types], value, sizeof(u_int8_t));
1500 num_prohibited_interface_types++;
1501 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IFTYPE;
1502 }
1503 break;
1504 }
1505 case NECP_CLIENT_PARAMETER_REQUIRE_AGENT: {
1506 if (num_required_agents >= NECP_MAX_PARSED_PARAMETERS) {
1507 break;
1508 }
1509 if (length >= sizeof(uuid_t)) {
1510 memcpy(&parsed_parameters->required_netagents[num_required_agents], value, sizeof(uuid_t));
1511 num_required_agents++;
1512 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT;
1513 }
1514 break;
1515 }
1516 case NECP_CLIENT_PARAMETER_PROHIBIT_AGENT: {
1517 if (num_prohibited_agents >= NECP_MAX_PARSED_PARAMETERS) {
1518 break;
1519 }
1520 if (length >= sizeof(uuid_t)) {
1521 memcpy(&parsed_parameters->prohibited_netagents[num_prohibited_agents], value, sizeof(uuid_t));
1522 num_prohibited_agents++;
1523 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT;
1524 }
1525 break;
1526 }
1527 case NECP_CLIENT_PARAMETER_PREFER_AGENT: {
1528 if (num_preferred_agents >= NECP_MAX_PARSED_PARAMETERS) {
1529 break;
1530 }
1531 if (length >= sizeof(uuid_t)) {
1532 memcpy(&parsed_parameters->preferred_netagents[num_preferred_agents], value, sizeof(uuid_t));
1533 num_preferred_agents++;
1534 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT;
1535 }
1536 break;
1537 }
1538 case NECP_CLIENT_PARAMETER_REQUIRE_AGENT_TYPE: {
1539 if (num_required_agent_types >= NECP_MAX_PARSED_PARAMETERS) {
1540 break;
1541 }
1542 if (length >= sizeof(struct necp_client_parameter_netagent_type)) {
1543 memcpy(&parsed_parameters->required_netagent_types[num_required_agent_types], value, sizeof(struct necp_client_parameter_netagent_type));
1544 num_required_agent_types++;
1545 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT_TYPE;
1546 }
1547 break;
1548 }
1549 case NECP_CLIENT_PARAMETER_PROHIBIT_AGENT_TYPE: {
1550 if (num_prohibited_agent_types >= NECP_MAX_PARSED_PARAMETERS) {
1551 break;
1552 }
1553 if (length >= sizeof(struct necp_client_parameter_netagent_type)) {
1554 memcpy(&parsed_parameters->prohibited_netagent_types[num_prohibited_agent_types], value, sizeof(struct necp_client_parameter_netagent_type));
1555 num_prohibited_agent_types++;
1556 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT_TYPE;
1557 }
1558 break;
1559 }
1560 case NECP_CLIENT_PARAMETER_PREFER_AGENT_TYPE: {
1561 if (num_preferred_agent_types >= NECP_MAX_PARSED_PARAMETERS) {
1562 break;
1563 }
1564 if (length >= sizeof(struct necp_client_parameter_netagent_type)) {
1565 memcpy(&parsed_parameters->preferred_netagent_types[num_preferred_agent_types], value, sizeof(struct necp_client_parameter_netagent_type));
1566 num_preferred_agent_types++;
1567 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE;
1568 }
1569 break;
1570 }
1571 case NECP_CLIENT_PARAMETER_FLAGS: {
1572 if (length >= sizeof(u_int32_t)) {
1573 memcpy(&parsed_parameters->flags, value, sizeof(parsed_parameters->flags));
1574 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_FLAGS;
1575 }
1576 break;
1577 }
1578 case NECP_CLIENT_PARAMETER_IP_PROTOCOL: {
1579 if (length >= sizeof(parsed_parameters->ip_protocol)) {
1580 memcpy(&parsed_parameters->ip_protocol, value, sizeof(parsed_parameters->ip_protocol));
1581 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_IP_PROTOCOL;
1582 }
1583 break;
1584 }
1585 case NECP_CLIENT_PARAMETER_PID: {
1586 if (length >= sizeof(parsed_parameters->effective_pid)) {
1587 memcpy(&parsed_parameters->effective_pid, value, sizeof(parsed_parameters->effective_pid));
1588 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_EFFECTIVE_PID;
1589 }
1590 break;
1591 }
1592 case NECP_CLIENT_PARAMETER_APPLICATION: {
1593 if (length >= sizeof(parsed_parameters->effective_uuid)) {
1594 memcpy(&parsed_parameters->effective_uuid, value, sizeof(parsed_parameters->effective_uuid));
1595 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_EFFECTIVE_UUID;
1596 }
1597 break;
1598 }
1599 case NECP_CLIENT_PARAMETER_TRAFFIC_CLASS: {
1600 if (length >= sizeof(parsed_parameters->traffic_class)) {
1601 memcpy(&parsed_parameters->traffic_class, value, sizeof(parsed_parameters->traffic_class));
1602 parsed_parameters->valid_fields |= NECP_PARSED_PARAMETERS_FIELD_TRAFFIC_CLASS;
1603 }
1604 break;
1605 }
1606 default: {
1607 break;
1608 }
1609 }
1610 }
1611 }
1612
1613 offset += sizeof(struct necp_tlv_header) + length;
1614 }
1615
1616 return (error);
1617 }
1618
1619 static int
1620 necp_client_parse_result(u_int8_t *result,
1621 u_int32_t result_size,
1622 union necp_sockaddr_union *local_address,
1623 union necp_sockaddr_union *remote_address)
1624 {
1625 int error = 0;
1626 size_t offset = 0;
1627
1628 while ((offset + sizeof(struct necp_tlv_header)) <= result_size) {
1629 u_int8_t type = necp_buffer_get_tlv_type(result, offset);
1630 u_int32_t length = necp_buffer_get_tlv_length(result, offset);
1631
1632 if (length > 0 && (offset + sizeof(struct necp_tlv_header) + length) <= result_size) {
1633 u_int8_t *value = necp_buffer_get_tlv_value(result, offset, NULL);
1634 if (value != NULL) {
1635 switch (type) {
1636 case NECP_CLIENT_RESULT_LOCAL_ENDPOINT: {
1637 if (length >= sizeof(struct necp_client_endpoint)) {
1638 struct necp_client_endpoint *endpoint = (struct necp_client_endpoint *)(void *)value;
1639 if (local_address != NULL && necp_client_address_is_valid(&endpoint->u.sa)) {
1640 memcpy(local_address, &endpoint->u.sa, endpoint->u.sa.sa_len);
1641 }
1642 }
1643 break;
1644 }
1645 case NECP_CLIENT_RESULT_REMOTE_ENDPOINT: {
1646 if (length >= sizeof(struct necp_client_endpoint)) {
1647 struct necp_client_endpoint *endpoint = (struct necp_client_endpoint *)(void *)value;
1648 if (remote_address != NULL && necp_client_address_is_valid(&endpoint->u.sa)) {
1649 memcpy(remote_address, &endpoint->u.sa, endpoint->u.sa.sa_len);
1650 }
1651 }
1652 break;
1653 }
1654 default: {
1655 break;
1656 }
1657 }
1658 }
1659 }
1660
1661 offset += sizeof(struct necp_tlv_header) + length;
1662 }
1663
1664 return (error);
1665 }
1666
1667 int
1668 necp_client_register_socket_flow(pid_t pid, uuid_t client_id, struct inpcb *inp)
1669 {
1670 int error = 0;
1671 bool found_client = FALSE;
1672
1673 NECP_CLIENT_TREE_LOCK_SHARED();
1674
1675 struct necp_client find;
1676 uuid_copy(find.client_id, client_id);
1677 struct necp_client *client = RB_FIND(_necp_client_global_tree, &necp_client_global_tree, &find);
1678 if (client != NULL) {
1679 NECP_CLIENT_LOCK(client);
1680
1681 if (!pid || client->proc_pid == pid) {
1682 // Found the right client!
1683 found_client = TRUE;
1684 necp_client_add_socket_flow(client, inp);
1685 }
1686
1687 NECP_CLIENT_UNLOCK(client);
1688 }
1689
1690 NECP_CLIENT_TREE_UNLOCK();
1691
1692 if (!found_client) {
1693 error = ENOENT;
1694 } else {
1695 /*
1696 * Count the sockets that have the NECP client UUID set
1697 */
1698 struct socket *so = inp->inp_socket;
1699 if (!(so->so_flags1 & SOF1_HAS_NECP_CLIENT_UUID)) {
1700 so->so_flags1 |= SOF1_HAS_NECP_CLIENT_UUID;
1701 INC_ATOMIC_INT64_LIM(net_api_stats.nas_socket_necp_clientuuid_total);
1702 }
1703 }
1704
1705 return (error);
1706 }
1707
1708 static void
1709 necp_client_add_multipath_cb(struct necp_client *client, struct mppcb *mpp)
1710 {
1711 struct necp_client_flow *flow = NULL;
1712
1713 client->interface_handle = mpp;
1714 client->interface_cb = mpp->necp_cb;
1715
1716 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
1717 if (flow->nexus || flow->socket) {
1718 continue;
1719 }
1720
1721 flow->u.socket_handle = mpp;
1722 flow->u.cb = mpp->necp_cb;
1723
1724 if (flow->viable && flow->u.cb) {
1725 flow->u.cb(mpp, NECP_CLIENT_CBACTION_INITIAL, flow);
1726 }
1727 }
1728 }
1729
1730 int
1731 necp_client_register_multipath_cb(pid_t pid, uuid_t client_id, struct mppcb *mpp)
1732 {
1733 int error = 0;
1734 bool found_client = FALSE;
1735
1736 NECP_CLIENT_TREE_LOCK_SHARED();
1737
1738 struct necp_client find;
1739 uuid_copy(find.client_id, client_id);
1740 struct necp_client *client = RB_FIND(_necp_client_global_tree, &necp_client_global_tree, &find);
1741 if (client != NULL) {
1742 NECP_CLIENT_LOCK(client);
1743
1744 if (!pid || client->proc_pid == pid) {
1745 // Found the right client!
1746 found_client = TRUE;
1747 necp_client_add_multipath_cb(client, mpp);
1748 }
1749
1750 NECP_CLIENT_UNLOCK(client);
1751 }
1752
1753 NECP_CLIENT_TREE_UNLOCK();
1754
1755 if (!found_client) {
1756 error = ENOENT;
1757 }
1758
1759 return (error);
1760 }
1761
1762 #define NETAGENT_DOMAIN_NETEXT "NetworkExtension"
1763 #define NETAGENT_TYPE_PATHCTRL "PathController"
1764
1765 static int
1766 necp_client_unregister_socket_flow(uuid_t client_id, void *handle)
1767 {
1768 int error = 0;
1769 struct necp_fd_data *client_fd = NULL;
1770 bool found_client = FALSE;
1771 bool client_updated = FALSE;
1772
1773 NECP_FD_LIST_LOCK_SHARED();
1774 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
1775 NECP_FD_LOCK(client_fd);
1776
1777 struct necp_client *client = necp_client_fd_find_client_and_lock(client_fd, client_id);
1778 if (client != NULL) {
1779 // Found the right client!
1780 found_client = TRUE;
1781
1782 // Remove flow assignment
1783 struct necp_client_flow *search_flow = NULL;
1784 struct necp_client_flow *temp_flow = NULL;
1785 LIST_FOREACH_SAFE(search_flow, &client->flow_list, flow_chain, temp_flow) {
1786 if (search_flow->socket && search_flow->u.socket_handle == handle) {
1787 if (search_flow->assigned_results != NULL) {
1788 FREE(search_flow->assigned_results, M_NETAGENT);
1789 search_flow->assigned_results = NULL;
1790 }
1791 client_updated = TRUE;
1792 LIST_REMOVE(search_flow, flow_chain);
1793 OSDecrementAtomic(&necp_socket_flow_count);
1794 mcache_free(necp_flow_cache, search_flow);
1795 }
1796 }
1797
1798 NECP_CLIENT_UNLOCK(client);
1799 }
1800
1801 if (client_updated) {
1802 client->flow_result_read = FALSE;
1803 necp_fd_notify(client_fd, true);
1804 }
1805 NECP_FD_UNLOCK(client_fd);
1806
1807 if (found_client) {
1808 break;
1809 }
1810 }
1811 NECP_FD_LIST_UNLOCK();
1812
1813 if (!found_client) {
1814 error = ENOENT;
1815 }
1816
1817 return (error);
1818 }
1819
1820 static int
1821 necp_client_unregister_multipath_cb(uuid_t client_id, void *handle)
1822 {
1823 int error = 0;
1824 bool found_client = FALSE;
1825
1826 NECP_CLIENT_TREE_LOCK_SHARED();
1827
1828 struct necp_client find;
1829 uuid_copy(find.client_id, client_id);
1830 struct necp_client *client = RB_FIND(_necp_client_global_tree, &necp_client_global_tree, &find);
1831 if (client != NULL) {
1832 NECP_CLIENT_LOCK(client);
1833
1834 // Found the right client!
1835 found_client = TRUE;
1836
1837 // Remove flow assignment
1838 struct necp_client_flow *search_flow = NULL;
1839 struct necp_client_flow *temp_flow = NULL;
1840 LIST_FOREACH_SAFE(search_flow, &client->flow_list, flow_chain, temp_flow) {
1841 if (!search_flow->socket && !search_flow->nexus &&
1842 search_flow->u.socket_handle == handle) {
1843 search_flow->u.socket_handle = NULL;
1844 search_flow->u.cb = NULL;
1845 }
1846 }
1847
1848 client->interface_handle = NULL;
1849 client->interface_cb = NULL;
1850
1851 NECP_CLIENT_UNLOCK(client);
1852 }
1853
1854 NECP_CLIENT_TREE_UNLOCK();
1855
1856 if (!found_client) {
1857 error = ENOENT;
1858 }
1859
1860 return (error);
1861 }
1862
1863 int
1864 necp_client_assign_from_socket(pid_t pid, uuid_t client_id, struct inpcb *inp)
1865 {
1866 int error = 0;
1867 struct necp_fd_data *client_fd = NULL;
1868 bool found_client = FALSE;
1869 bool client_updated = FALSE;
1870
1871 NECP_FD_LIST_LOCK_SHARED();
1872 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
1873 if (pid && client_fd->proc_pid != pid) {
1874 continue;
1875 }
1876
1877 proc_t proc = proc_find(client_fd->proc_pid);
1878 if (proc == PROC_NULL) {
1879 continue;
1880 }
1881
1882 NECP_FD_LOCK(client_fd);
1883
1884 struct necp_client *client = necp_client_fd_find_client_and_lock(client_fd, client_id);
1885 if (client != NULL) {
1886 // Found the right client!
1887 found_client = TRUE;
1888
1889 struct necp_client_flow *flow = NULL;
1890 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
1891 if (flow->socket && flow->u.socket_handle == inp) {
1892 // Release prior results and route
1893 if (flow->assigned_results != NULL) {
1894 FREE(flow->assigned_results, M_NETAGENT);
1895 flow->assigned_results = NULL;
1896 }
1897
1898 ifnet_t ifp = NULL;
1899 if ((inp->inp_flags & INP_BOUND_IF) && inp->inp_boundifp) {
1900 ifp = inp->inp_boundifp;
1901 } else {
1902 ifp = inp->inp_last_outifp;
1903 }
1904
1905 if (ifp != NULL) {
1906 flow->interface_index = ifp->if_index;
1907 } else {
1908 flow->interface_index = IFSCOPE_NONE;
1909 }
1910
1911 if (inp->inp_vflag & INP_IPV4) {
1912 flow->local_addr.sin.sin_family = AF_INET;
1913 flow->local_addr.sin.sin_len = sizeof(struct sockaddr_in);
1914 flow->local_addr.sin.sin_port = inp->inp_lport;
1915 memcpy(&flow->local_addr.sin.sin_addr, &inp->inp_laddr, sizeof(struct in_addr));
1916
1917 flow->remote_addr.sin.sin_family = AF_INET;
1918 flow->remote_addr.sin.sin_len = sizeof(struct sockaddr_in);
1919 flow->remote_addr.sin.sin_port = inp->inp_fport;
1920 memcpy(&flow->remote_addr.sin.sin_addr, &inp->inp_faddr, sizeof(struct in_addr));
1921 } else if (inp->inp_vflag & INP_IPV6) {
1922 in6_ip6_to_sockaddr(&inp->in6p_laddr, inp->inp_lport, &flow->local_addr.sin6, sizeof(flow->local_addr));
1923 in6_ip6_to_sockaddr(&inp->in6p_faddr, inp->inp_fport, &flow->remote_addr.sin6, sizeof(flow->remote_addr));
1924 }
1925
1926 flow->viable = necp_client_flow_is_viable(proc, client, flow);
1927
1928 uuid_t empty_uuid;
1929 uuid_clear(empty_uuid);
1930 flow->assigned = TRUE;
1931 flow->assigned_results = necp_create_nexus_assign_message(empty_uuid, 0, NULL, 0,
1932 (struct necp_client_endpoint *)&flow->local_addr,
1933 (struct necp_client_endpoint *)&flow->remote_addr,
1934 0, &flow->assigned_results_length);
1935 client->flow_result_read = FALSE;
1936 client_updated = TRUE;
1937 break;
1938 }
1939 }
1940
1941 NECP_CLIENT_UNLOCK(client);
1942 }
1943 if (client_updated) {
1944 necp_fd_notify(client_fd, true);
1945 }
1946 NECP_FD_UNLOCK(client_fd);
1947
1948 proc_rele(proc);
1949 proc = PROC_NULL;
1950
1951 if (found_client) {
1952 break;
1953 }
1954 }
1955 NECP_FD_LIST_UNLOCK();
1956
1957 if (!found_client) {
1958 error = ENOENT;
1959 } else if (!client_updated) {
1960 error = EINVAL;
1961 }
1962
1963 return (error);
1964 }
1965
1966 int
1967 necp_update_flow_protoctl_event(uuid_t netagent_uuid, uuid_t client_id,
1968 uint32_t protoctl_event_code, uint32_t protoctl_event_val,
1969 uint32_t protoctl_event_tcp_seq_number)
1970 {
1971 int error = 0;
1972 struct necp_fd_data *client_fd = NULL;
1973 bool found_client = FALSE;
1974 bool client_updated = FALSE;
1975
1976 NECP_FD_LIST_LOCK_SHARED();
1977 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
1978 proc_t proc = proc_find(client_fd->proc_pid);
1979 if (proc == PROC_NULL) {
1980 continue;
1981 }
1982
1983 NECP_FD_LOCK(client_fd);
1984
1985 struct necp_client *client = necp_client_fd_find_client_and_lock(client_fd, client_id);
1986 if (client != NULL) {
1987 /* Found the right client! */
1988 found_client = TRUE;
1989
1990 struct necp_client_flow *flow = NULL;
1991 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
1992 // Verify that the client nexus agent matches
1993 if (flow->nexus &&
1994 uuid_compare(flow->u.nexus_agent,
1995 netagent_uuid) == 0) {
1996 flow->has_protoctl_event = TRUE;
1997 flow->protoctl_event.protoctl_event_code = protoctl_event_code;
1998 flow->protoctl_event.protoctl_event_val = protoctl_event_val;
1999 flow->protoctl_event.protoctl_event_tcp_seq_num = protoctl_event_tcp_seq_number;
2000 client->flow_result_read = FALSE;
2001 client_updated = TRUE;
2002 break;
2003 }
2004 }
2005
2006 NECP_CLIENT_UNLOCK(client);
2007 }
2008
2009 if (client_updated) {
2010 necp_fd_notify(client_fd, true);
2011 }
2012
2013 NECP_FD_UNLOCK(client_fd);
2014 proc_rele(proc);
2015 proc = PROC_NULL;
2016
2017 if (found_client) {
2018 break;
2019 }
2020 }
2021 NECP_FD_LIST_UNLOCK();
2022
2023 if (!found_client) {
2024 error = ENOENT;
2025 } else if (!client_updated) {
2026 error = EINVAL;
2027 }
2028 return (error);
2029 }
2030
2031 static bool
2032 necp_assign_client_result_locked(struct proc *proc,
2033 struct necp_fd_data *client_fd,
2034 struct necp_client *client,
2035 uuid_t netagent_uuid,
2036 u_int8_t *assigned_results,
2037 size_t assigned_results_length,
2038 bool notify_fd)
2039 {
2040 bool client_updated = FALSE;
2041
2042 NECP_FD_ASSERT_LOCKED(client_fd);
2043 NECP_CLIENT_ASSERT_LOCKED(client);
2044
2045 struct necp_client_flow *flow = NULL;
2046 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
2047 // Verify that the client nexus agent matches
2048 if (flow->nexus &&
2049 uuid_compare(flow->u.nexus_agent, netagent_uuid) == 0) {
2050 // Release prior results and route
2051 if (flow->assigned_results != NULL) {
2052 FREE(flow->assigned_results, M_NETAGENT);
2053 flow->assigned_results = NULL;
2054 }
2055
2056 if (assigned_results != NULL && assigned_results_length > 0) {
2057 int error = necp_client_parse_result(assigned_results, (u_int32_t)assigned_results_length,
2058 &flow->local_addr, &flow->remote_addr);
2059 VERIFY(error == 0);
2060 }
2061
2062 flow->viable = necp_client_flow_is_viable(proc, client, flow);
2063
2064 flow->assigned = TRUE;
2065 flow->assigned_results = assigned_results;
2066 flow->assigned_results_length = assigned_results_length;
2067 client->flow_result_read = FALSE;
2068 client_updated = TRUE;
2069 break;
2070 }
2071 }
2072
2073 if (client_updated && notify_fd) {
2074 necp_fd_notify(client_fd, true);
2075 }
2076
2077 // if not updated, client must free assigned_results
2078 return (client_updated);
2079 }
2080
2081 int
2082 necp_assign_client_result(uuid_t netagent_uuid, uuid_t client_id,
2083 u_int8_t *assigned_results, size_t assigned_results_length)
2084 {
2085 int error = 0;
2086 struct necp_fd_data *client_fd = NULL;
2087 bool found_client = FALSE;
2088 bool client_updated = FALSE;
2089
2090 NECP_FD_LIST_LOCK_SHARED();
2091
2092 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
2093 proc_t proc = proc_find(client_fd->proc_pid);
2094 if (proc == PROC_NULL) {
2095 continue;
2096 }
2097
2098 NECP_FD_LOCK(client_fd);
2099 struct necp_client *client = necp_client_fd_find_client_and_lock(client_fd, client_id);
2100 if (client != NULL) {
2101 // Found the right client!
2102 found_client = TRUE;
2103
2104 if (necp_assign_client_result_locked(proc, client_fd, client, netagent_uuid,
2105 assigned_results, assigned_results_length, true)) {
2106 client_updated = TRUE;
2107 }
2108
2109 NECP_CLIENT_UNLOCK(client);
2110 }
2111 NECP_FD_UNLOCK(client_fd);
2112
2113 proc_rele(proc);
2114 proc = PROC_NULL;
2115
2116 if (found_client) {
2117 break;
2118 }
2119 }
2120
2121 NECP_FD_LIST_UNLOCK();
2122
2123 // upon error, client must free assigned_results
2124 if (!found_client) {
2125 error = ENOENT;
2126 } else if (!client_updated) {
2127 error = EINVAL;
2128 }
2129
2130 return (error);
2131 }
2132
2133 /// Client updating
2134
2135 static bool
2136 necp_update_client_result(proc_t proc,
2137 struct necp_fd_data *client_fd,
2138 struct necp_client *client,
2139 struct _necp_client_defunct_list *defunct_list)
2140 {
2141 struct necp_client_result_netagent netagent;
2142 struct necp_aggregate_result result;
2143 struct necp_client_parsed_parameters *parsed_parameters = NULL;
2144 u_int32_t flags = 0;
2145 struct rtentry *route = NULL;
2146
2147 NECP_CLIENT_ASSERT_LOCKED(client);
2148
2149 MALLOC(parsed_parameters, struct necp_client_parsed_parameters *, sizeof(*parsed_parameters), M_NECP, (M_WAITOK | M_ZERO));
2150 if (parsed_parameters == NULL) {
2151 NECPLOG0(LOG_ERR, "Failed to allocate parsed parameters");
2152 return (FALSE);
2153 }
2154
2155 // Nexus flows will be brought back if they are still valid
2156 necp_client_mark_all_nonsocket_flows_as_invalid(client);
2157
2158 int error = necp_client_parse_parameters(client->parameters, (u_int32_t)client->parameters_length, parsed_parameters);
2159 if (error != 0) {
2160 FREE(parsed_parameters, M_NECP);
2161 return (FALSE);
2162 }
2163
2164 // Update saved IP protocol
2165 client->ip_protocol = parsed_parameters->ip_protocol;
2166
2167 // Check parameters to find best interface
2168 u_int matching_if_index = 0;
2169 if (necp_find_matching_interface_index(parsed_parameters, &matching_if_index)) {
2170 if (matching_if_index != 0) {
2171 parsed_parameters->required_interface_index = matching_if_index;
2172 }
2173 // Interface found or not needed, match policy.
2174 error = necp_application_find_policy_match_internal(proc, client->parameters,
2175 (u_int32_t)client->parameters_length,
2176 &result, &flags, matching_if_index,
2177 NULL, NULL, &route, false);
2178 if (error != 0) {
2179 if (route != NULL) {
2180 rtfree(route);
2181 }
2182 FREE(parsed_parameters, M_NECP);
2183 return (FALSE);
2184 }
2185
2186 // Reset current route
2187 NECP_CLIENT_ROUTE_LOCK(client);
2188 if (client->current_route != NULL) {
2189 rtfree(client->current_route);
2190 }
2191 client->current_route = route;
2192 NECP_CLIENT_ROUTE_UNLOCK(client);
2193 } else {
2194 // Interface not found. Clear out the whole result, make everything fail.
2195 memset(&result, 0, sizeof(result));
2196 }
2197
2198 // Save the last policy id on the client
2199 client->policy_id = result.policy_id;
2200
2201 if ((parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_MULTIPATH) ||
2202 ((parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_LISTENER) &&
2203 result.routing_result != NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED)) {
2204 client->allow_multiple_flows = TRUE;
2205 } else {
2206 client->allow_multiple_flows = FALSE;
2207 }
2208
2209 // If the original request was scoped, and the policy result matches, make sure the result is scoped
2210 if ((result.routing_result == NECP_KERNEL_POLICY_RESULT_NONE ||
2211 result.routing_result == NECP_KERNEL_POLICY_RESULT_PASS) &&
2212 result.routed_interface_index != IFSCOPE_NONE &&
2213 parsed_parameters->required_interface_index == result.routed_interface_index) {
2214 result.routing_result = NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED;
2215 result.routing_result_parameter.scoped_interface_index = result.routed_interface_index;
2216 }
2217
2218 if (defunct_list != NULL &&
2219 result.routing_result == NECP_KERNEL_POLICY_RESULT_DROP) {
2220 // If we are forced to drop the client, defunct it if it has flows
2221 necp_defunct_client_for_policy(client, defunct_list);
2222 }
2223
2224 // Recalculate flags
2225 if (client->defunct) {
2226 flags |= NECP_CLIENT_RESULT_FLAG_DEFUNCT;
2227 }
2228 if (parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_LISTENER) {
2229 // Listeners are valid as long as they aren't dropped
2230 if (result.routing_result != NECP_KERNEL_POLICY_RESULT_DROP) {
2231 flags |= NECP_CLIENT_RESULT_FLAG_SATISFIED;
2232 }
2233 } else if (result.routed_interface_index != 0) {
2234 // Clients without flows determine viability based on having some routable interface
2235 flags |= NECP_CLIENT_RESULT_FLAG_SATISFIED;
2236 }
2237
2238 bool updated = FALSE;
2239 u_int8_t *cursor = client->result;
2240 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_FLAGS, sizeof(flags), &flags, &updated, client->result, sizeof(client->result));
2241 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_CLIENT_ID, sizeof(uuid_t), client->client_id, &updated,
2242 client->result, sizeof(client->result));
2243 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_POLICY_RESULT, sizeof(result.routing_result), &result.routing_result, &updated,
2244 client->result, sizeof(client->result));
2245 if (result.routing_result_parameter.tunnel_interface_index != 0) {
2246 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_POLICY_RESULT_PARAMETER,
2247 sizeof(result.routing_result_parameter), &result.routing_result_parameter, &updated,
2248 client->result, sizeof(client->result));
2249 }
2250 if (result.filter_control_unit != 0) {
2251 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_FILTER_CONTROL_UNIT,
2252 sizeof(result.filter_control_unit), &result.filter_control_unit, &updated,
2253 client->result, sizeof(client->result));
2254 }
2255 if (result.routed_interface_index != 0) {
2256 u_int routed_interface_index = result.routed_interface_index;
2257 if (result.routing_result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL &&
2258 parsed_parameters->required_interface_index != IFSCOPE_NONE &&
2259 parsed_parameters->required_interface_index != result.routed_interface_index) {
2260 routed_interface_index = parsed_parameters->required_interface_index;
2261 }
2262
2263 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_INTERFACE_INDEX,
2264 sizeof(routed_interface_index), &routed_interface_index, &updated,
2265 client->result, sizeof(client->result));
2266 }
2267 if (client_fd && client_fd->flags & NECP_OPEN_FLAG_BACKGROUND) {
2268 u_int32_t effective_traffic_class = SO_TC_BK_SYS;
2269 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_EFFECTIVE_TRAFFIC_CLASS,
2270 sizeof(effective_traffic_class), &effective_traffic_class, &updated,
2271 client->result, sizeof(client->result));
2272 }
2273 if (client->background_update) {
2274 u_int32_t background = client->background;
2275 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_TRAFFIC_MGMT_BG,
2276 sizeof(background), &background, &updated,
2277 client->result, sizeof(client->result));
2278 if (updated) {
2279 client->background_update = 0;
2280 }
2281 }
2282 NECP_CLIENT_ROUTE_LOCK(client);
2283 if (client->current_route != NULL) {
2284 const u_int32_t route_mtu = get_maxmtu(client->current_route);
2285 if (route_mtu != 0) {
2286 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_EFFECTIVE_MTU,
2287 sizeof(route_mtu), &route_mtu, &updated,
2288 client->result, sizeof(client->result));
2289 }
2290 }
2291 NECP_CLIENT_ROUTE_UNLOCK(client);
2292
2293 if (result.mss_recommended != 0) {
2294 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_RECOMMENDED_MSS,
2295 sizeof(result.mss_recommended), &result.mss_recommended, &updated,
2296 client->result, sizeof(client->result));
2297 }
2298
2299 for (int i = 0; i < NECP_MAX_NETAGENTS; i++) {
2300 if (uuid_is_null(result.netagents[i])) {
2301 break;
2302 }
2303 uuid_copy(netagent.netagent_uuid, result.netagents[i]);
2304 netagent.generation = netagent_get_generation(netagent.netagent_uuid);
2305 if (necp_netagent_applies_to_client(client, parsed_parameters, netagent.netagent_uuid, TRUE, 0, 0)) {
2306 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_NETAGENT, sizeof(netagent), &netagent, &updated,
2307 client->result, sizeof(client->result));
2308 }
2309 }
2310
2311 ifnet_head_lock_shared();
2312 ifnet_t direct_interface = NULL;
2313 ifnet_t delegate_interface = NULL;
2314 ifnet_t original_scoped_interface = NULL;
2315
2316 if (result.routed_interface_index != IFSCOPE_NONE && result.routed_interface_index <= (u_int32_t)if_index) {
2317 direct_interface = ifindex2ifnet[result.routed_interface_index];
2318 } else if (parsed_parameters->required_interface_index != IFSCOPE_NONE &&
2319 parsed_parameters->required_interface_index <= (u_int32_t)if_index) {
2320 // If the request was scoped, but the route didn't match, still grab the agents
2321 direct_interface = ifindex2ifnet[parsed_parameters->required_interface_index];
2322 } else if (result.routed_interface_index == IFSCOPE_NONE &&
2323 result.routing_result == NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED &&
2324 result.routing_result_parameter.scoped_interface_index != IFSCOPE_NONE) {
2325 direct_interface = ifindex2ifnet[result.routing_result_parameter.scoped_interface_index];
2326 }
2327 if (direct_interface != NULL) {
2328 delegate_interface = direct_interface->if_delegated.ifp;
2329 }
2330 if (result.routing_result == NECP_KERNEL_POLICY_RESULT_IP_TUNNEL &&
2331 parsed_parameters->required_interface_index != IFSCOPE_NONE &&
2332 parsed_parameters->required_interface_index != result.routing_result_parameter.tunnel_interface_index &&
2333 parsed_parameters->required_interface_index <= (u_int32_t)if_index) {
2334 original_scoped_interface = ifindex2ifnet[parsed_parameters->required_interface_index];
2335 }
2336 // Add interfaces
2337 if (original_scoped_interface != NULL) {
2338 struct necp_client_result_interface interface_struct;
2339 interface_struct.index = original_scoped_interface->if_index;
2340 interface_struct.generation = ifnet_get_generation(original_scoped_interface);
2341 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_INTERFACE, sizeof(interface_struct), &interface_struct, &updated,
2342 client->result, sizeof(client->result));
2343 }
2344 if (direct_interface != NULL) {
2345 struct necp_client_result_interface interface_struct;
2346 interface_struct.index = direct_interface->if_index;
2347 interface_struct.generation = ifnet_get_generation(direct_interface);
2348 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_INTERFACE, sizeof(interface_struct), &interface_struct, &updated,
2349 client->result, sizeof(client->result));
2350 }
2351 if (delegate_interface != NULL) {
2352 struct necp_client_result_interface interface_struct;
2353 interface_struct.index = delegate_interface->if_index;
2354 interface_struct.generation = ifnet_get_generation(delegate_interface);
2355 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_INTERFACE, sizeof(interface_struct), &interface_struct, &updated,
2356 client->result, sizeof(client->result));
2357 }
2358
2359 // Update multipath/listener interface flows
2360 if (parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_MULTIPATH) {
2361 // Get multipath interface options from ordered list
2362 struct ifnet *multi_interface = NULL;
2363 TAILQ_FOREACH(multi_interface, &ifnet_ordered_head, if_ordered_link) {
2364 if (necp_ifnet_matches_parameters(multi_interface, parsed_parameters, NULL, true)) {
2365 // Add multipath interface flows for kernel MPTCP
2366 necp_client_add_interface_flow_if_needed(client, multi_interface->if_index);
2367
2368 // Add nexus agents for multipath
2369 necp_client_add_agent_flows_for_interface(client, parsed_parameters, multi_interface);
2370 }
2371 }
2372 } else if ((parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_LISTENER) &&
2373 result.routing_result != NECP_KERNEL_POLICY_RESULT_SOCKET_SCOPED) {
2374 // Get listener interface options from global list
2375 struct ifnet *listen_interface = NULL;
2376 TAILQ_FOREACH(listen_interface, &ifnet_head, if_link) {
2377 if (necp_ifnet_matches_parameters(listen_interface, parsed_parameters, NULL, false)) {
2378 // Add nexus agents for listeners
2379 necp_client_add_agent_flows_for_interface(client, parsed_parameters, listen_interface);
2380 }
2381 }
2382 }
2383
2384 // Add agents
2385 if (original_scoped_interface != NULL) {
2386 ifnet_lock_shared(original_scoped_interface);
2387 if (original_scoped_interface->if_agentids != NULL) {
2388 for (u_int32_t i = 0; i < original_scoped_interface->if_agentcount; i++) {
2389 if (uuid_is_null(original_scoped_interface->if_agentids[i])) {
2390 continue;
2391 }
2392 u_int16_t if_flags = nstat_ifnet_to_flags(original_scoped_interface);
2393 uuid_copy(netagent.netagent_uuid, original_scoped_interface->if_agentids[i]);
2394 netagent.generation = netagent_get_generation(netagent.netagent_uuid);
2395 if (necp_netagent_applies_to_client(client, parsed_parameters, netagent.netagent_uuid, FALSE, original_scoped_interface->if_index, if_flags)) {
2396 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_NETAGENT, sizeof(netagent), &netagent, &updated,
2397 client->result, sizeof(client->result));
2398 }
2399 }
2400 }
2401 ifnet_lock_done(original_scoped_interface);
2402 }
2403 if (direct_interface != NULL) {
2404 ifnet_lock_shared(direct_interface);
2405 if (direct_interface->if_agentids != NULL) {
2406 for (u_int32_t i = 0; i < direct_interface->if_agentcount; i++) {
2407 if (uuid_is_null(direct_interface->if_agentids[i])) {
2408 continue;
2409 }
2410 u_int16_t if_flags = nstat_ifnet_to_flags(direct_interface);
2411 uuid_copy(netagent.netagent_uuid, direct_interface->if_agentids[i]);
2412 netagent.generation = netagent_get_generation(netagent.netagent_uuid);
2413 if (necp_netagent_applies_to_client(client, parsed_parameters, netagent.netagent_uuid, TRUE, direct_interface->if_index, if_flags)) {
2414 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_NETAGENT, sizeof(netagent), &netagent, &updated,
2415 client->result, sizeof(client->result));
2416 }
2417 }
2418 }
2419 ifnet_lock_done(direct_interface);
2420 }
2421 if (delegate_interface != NULL) {
2422 ifnet_lock_shared(delegate_interface);
2423 if (delegate_interface->if_agentids != NULL) {
2424 for (u_int32_t i = 0; i < delegate_interface->if_agentcount; i++) {
2425 if (uuid_is_null(delegate_interface->if_agentids[i])) {
2426 continue;
2427 }
2428 u_int16_t if_flags = nstat_ifnet_to_flags(delegate_interface);
2429 uuid_copy(netagent.netagent_uuid, delegate_interface->if_agentids[i]);
2430 netagent.generation = netagent_get_generation(netagent.netagent_uuid);
2431 if (necp_netagent_applies_to_client(client, parsed_parameters, netagent.netagent_uuid, FALSE, delegate_interface->if_index, if_flags)) {
2432 cursor = necp_buffer_write_tlv_if_different(cursor, NECP_CLIENT_RESULT_NETAGENT, sizeof(netagent), &netagent, &updated,
2433 client->result, sizeof(client->result));
2434 }
2435 }
2436 }
2437 ifnet_lock_done(delegate_interface);
2438 }
2439 ifnet_head_done();
2440
2441 size_t new_result_length = (cursor - client->result);
2442 if (new_result_length != client->result_length) {
2443 client->result_length = new_result_length;
2444 updated = TRUE;
2445 }
2446
2447 // Update flow viability/flags
2448 bool defuncted_by_flow = FALSE;
2449 if (necp_client_update_flows(proc, client, defunct_list, &defuncted_by_flow)) {
2450 updated = TRUE;
2451 if (defuncted_by_flow && client->defunct) {
2452 // Reset initial TLV
2453 flags |= NECP_CLIENT_RESULT_FLAG_DEFUNCT;
2454 (void)necp_buffer_write_tlv_if_different(client->result, NECP_CLIENT_RESULT_FLAGS, sizeof(flags), &flags, &updated, client->result, sizeof(client->result));
2455 }
2456 }
2457
2458 if (updated) {
2459 client->result_read = FALSE;
2460 necp_client_update_observer_update(client);
2461 }
2462
2463 FREE(parsed_parameters, M_NECP);
2464 return (updated);
2465 }
2466
2467 static inline void
2468 necp_defunct_client_fd_locked(struct necp_fd_data *client_fd, struct _necp_client_defunct_list *defunct_list, struct proc *proc)
2469 {
2470 #pragma unused(proc)
2471 bool updated_result = FALSE;
2472 struct necp_client *client = NULL;
2473
2474 NECP_FD_ASSERT_LOCKED(client_fd);
2475
2476 RB_FOREACH(client, _necp_client_tree, &client_fd->clients) {
2477 NECP_CLIENT_LOCK(client);
2478 if (!client->defunct) {
2479 updated_result = necp_set_client_defunct(client);
2480
2481 // Prepare close events to be sent to the nexus to effectively remove the flows
2482 struct necp_client_flow *search_flow = NULL;
2483 LIST_FOREACH(search_flow, &client->flow_list, flow_chain) {
2484 if (search_flow->nexus &&
2485 !uuid_is_null(search_flow->u.nexus_agent) &&
2486 search_flow->requested_nexus) {
2487
2488 struct necp_client_defunct *client_defunct;
2489
2490 // Sleeping alloc won't fail; copy only what's necessary
2491 client_defunct = _MALLOC(sizeof (struct necp_client_defunct), M_NECP, M_WAITOK | M_ZERO);
2492 uuid_copy(client_defunct->nexus_agent, search_flow->u.nexus_agent);
2493 uuid_copy(client_defunct->client_id, client->client_id);
2494 client_defunct->proc_pid = client->proc_pid;
2495
2496 // Add to the list provided by caller
2497 LIST_INSERT_HEAD(defunct_list, client_defunct, chain);
2498 }
2499 }
2500 }
2501 NECP_CLIENT_UNLOCK(client);
2502 }
2503
2504
2505 if (updated_result) {
2506 necp_fd_notify(client_fd, true);
2507 }
2508 }
2509
2510 static inline void
2511 necp_update_client_fd_locked(struct necp_fd_data *client_fd,
2512 proc_t proc,
2513 struct _necp_client_defunct_list *defunct_list)
2514 {
2515 struct necp_client *client = NULL;
2516 bool updated_result = FALSE;
2517 NECP_FD_ASSERT_LOCKED(client_fd);
2518 RB_FOREACH(client, _necp_client_tree, &client_fd->clients) {
2519 NECP_CLIENT_LOCK(client);
2520 if (necp_update_client_result(proc, client_fd, client, defunct_list)) {
2521 updated_result = TRUE;
2522 }
2523 NECP_CLIENT_UNLOCK(client);
2524 }
2525 if (updated_result) {
2526 necp_fd_notify(client_fd, true);
2527 }
2528 }
2529
2530
2531 static void
2532 necp_update_all_clients_callout(__unused thread_call_param_t dummy,
2533 __unused thread_call_param_t arg)
2534 {
2535 struct necp_fd_data *client_fd = NULL;
2536
2537 struct _necp_client_defunct_list defunct_list;
2538 LIST_INIT(&defunct_list);
2539
2540 NECP_FD_LIST_LOCK_SHARED();
2541
2542 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
2543 proc_t proc = proc_find(client_fd->proc_pid);
2544 if (proc == PROC_NULL) {
2545 continue;
2546 }
2547
2548 // Update all clients on one fd
2549 NECP_FD_LOCK(client_fd);
2550 necp_update_client_fd_locked(client_fd, proc, &defunct_list);
2551 NECP_FD_UNLOCK(client_fd);
2552
2553 proc_rele(proc);
2554 proc = PROC_NULL;
2555 }
2556
2557 NECP_FD_LIST_UNLOCK();
2558
2559 // Handle the case in which some clients became newly defunct
2560 if (!LIST_EMPTY(&defunct_list)) {
2561 struct necp_client_defunct *client_defunct = NULL;
2562 struct necp_client_defunct *temp_client_defunct = NULL;
2563
2564 // For each newly defunct client, send a message to the nexus to remove the flow
2565 LIST_FOREACH_SAFE(client_defunct, &defunct_list, chain, temp_client_defunct) {
2566 if (!uuid_is_null(client_defunct->nexus_agent)) {
2567 int netagent_error = netagent_client_message(client_defunct->nexus_agent,
2568 client_defunct->client_id,
2569 client_defunct->proc_pid,
2570 NETAGENT_MESSAGE_TYPE_ABORT_NEXUS);
2571 if (netagent_error != 0) {
2572 char namebuf[MAXCOMLEN+1];
2573 (void) strlcpy(namebuf, "unknown", sizeof (namebuf));
2574 proc_name(client_defunct->proc_pid, namebuf, sizeof (namebuf));
2575 NECPLOG((netagent_error == ENOENT ? LOG_DEBUG : LOG_ERR), "necp_update_client abort nexus error (%d) for pid %d %s", netagent_error, client_defunct->proc_pid, namebuf);
2576 }
2577 }
2578 LIST_REMOVE(client_defunct, chain);
2579 FREE(client_defunct, M_NECP);
2580 }
2581 }
2582 ASSERT(LIST_EMPTY(&defunct_list));
2583 }
2584
2585 void
2586 necp_update_all_clients(void)
2587 {
2588 if (necp_client_update_tcall == NULL) {
2589 // Don't try to update clients if the module is not initialized
2590 return;
2591 }
2592
2593 uint64_t deadline = 0;
2594 uint64_t leeway = 0;
2595 clock_interval_to_deadline(necp_timeout_microseconds, NSEC_PER_USEC, &deadline);
2596 clock_interval_to_absolutetime_interval(necp_timeout_leeway_microseconds, NSEC_PER_USEC, &leeway);
2597
2598 thread_call_enter_delayed_with_leeway(necp_client_update_tcall, NULL,
2599 deadline, leeway, THREAD_CALL_DELAY_LEEWAY);
2600 }
2601
2602 void
2603 necp_set_client_as_background(proc_t proc,
2604 struct fileproc *fp,
2605 bool background)
2606 {
2607 bool updated_result = FALSE;
2608 struct necp_client *client = NULL;
2609
2610 if (proc == PROC_NULL) {
2611 NECPLOG0(LOG_ERR, "NULL proc");
2612 return;
2613 }
2614
2615 if (fp == NULL) {
2616 NECPLOG0(LOG_ERR, "NULL fp");
2617 return;
2618 }
2619
2620 struct necp_fd_data *client_fd = (struct necp_fd_data *)fp->f_fglob->fg_data;
2621 if (client_fd == NULL) {
2622 NECPLOG0(LOG_ERR, "Could not find client structure for backgrounded client");
2623 return;
2624 }
2625
2626 if (client_fd->necp_fd_type != necp_fd_type_client) {
2627 // Not a client fd, ignore
2628 NECPLOG0(LOG_ERR, "Not a client fd, ignore");
2629 return;
2630 }
2631
2632 NECP_FD_LOCK(client_fd);
2633
2634 RB_FOREACH(client, _necp_client_tree, &client_fd->clients) {
2635 NECP_CLIENT_LOCK(client);
2636
2637 bool has_assigned_flow = FALSE;
2638 struct necp_client_flow *search_flow = NULL;
2639 LIST_FOREACH(search_flow, &client->flow_list, flow_chain) {
2640 if (search_flow->assigned) {
2641 has_assigned_flow = TRUE;
2642 break;
2643 }
2644 }
2645
2646 if (has_assigned_flow) {
2647 client->background = background;
2648 client->background_update = TRUE;
2649 updated_result = TRUE;
2650 }
2651
2652 NECP_CLIENT_UNLOCK(client);
2653 }
2654 if (updated_result) {
2655 necp_update_client_fd_locked(client_fd, proc, NULL);
2656 }
2657 NECP_FD_UNLOCK(client_fd);
2658 }
2659
2660 void
2661 necp_fd_memstatus(proc_t proc, uint32_t status,
2662 struct necp_fd_data *client_fd)
2663 {
2664 #pragma unused(proc, status, client_fd)
2665 ASSERT(proc != PROC_NULL);
2666 ASSERT(client_fd != NULL);
2667
2668 // Nothing to reap for the process or client for now,
2669 // but this is where we would trigger that in future.
2670 }
2671
2672 void
2673 necp_fd_defunct(proc_t proc, struct necp_fd_data *client_fd)
2674 {
2675 struct _necp_client_defunct_list defunct_list;
2676
2677 ASSERT(proc != PROC_NULL);
2678 ASSERT(client_fd != NULL);
2679
2680 if (client_fd->necp_fd_type != necp_fd_type_client) {
2681 // Not a client fd, ignore
2682 return;
2683 }
2684
2685 // Our local temporary list
2686 LIST_INIT(&defunct_list);
2687
2688 // Need to hold lock so ntstats defunct the same set of clients
2689 NECP_FD_LOCK(client_fd);
2690 necp_defunct_client_fd_locked(client_fd, &defunct_list, proc);
2691 NECP_FD_UNLOCK(client_fd);
2692
2693 if (!LIST_EMPTY(&defunct_list)) {
2694 struct necp_client_defunct *client_defunct = NULL;
2695 struct necp_client_defunct *temp_client_defunct = NULL;
2696
2697 // For each defunct client, remove flow from the nexus
2698 LIST_FOREACH_SAFE(client_defunct, &defunct_list, chain, temp_client_defunct) {
2699 if (!uuid_is_null(client_defunct->nexus_agent)) {
2700 int netagent_error = netagent_client_message(client_defunct->nexus_agent,
2701 client_defunct->client_id,
2702 client_defunct->proc_pid,
2703 NETAGENT_MESSAGE_TYPE_ABORT_NEXUS);
2704 if (netagent_error != 0) {
2705 NECPLOG((netagent_error == ENOENT ? LOG_DEBUG : LOG_ERR), "necp_defunct_client abort nexus error (%d)", netagent_error);
2706 }
2707 }
2708 LIST_REMOVE(client_defunct, chain);
2709 FREE(client_defunct, M_NECP);
2710 }
2711 }
2712 ASSERT(LIST_EMPTY(&defunct_list));
2713 }
2714
2715 static void
2716 necp_client_remove_agent_from_result(struct necp_client *client, uuid_t netagent_uuid)
2717 {
2718 size_t offset = 0;
2719
2720 u_int8_t *result_buffer = client->result;
2721 while ((offset + sizeof(struct necp_tlv_header)) <= client->result_length) {
2722 u_int8_t type = necp_buffer_get_tlv_type(result_buffer, offset);
2723 u_int32_t length = necp_buffer_get_tlv_length(result_buffer, offset);
2724
2725 size_t tlv_total_length = (sizeof(struct necp_tlv_header) + length);
2726 if (type == NECP_CLIENT_RESULT_NETAGENT &&
2727 length == sizeof(struct necp_client_result_netagent) &&
2728 (offset + tlv_total_length) <= client->result_length) {
2729 struct necp_client_result_netagent *value = ((struct necp_client_result_netagent *)(void *)
2730 necp_buffer_get_tlv_value(result_buffer, offset, NULL));
2731 if (uuid_compare(value->netagent_uuid, netagent_uuid) == 0) {
2732 // Found a netagent to remove
2733 // Shift bytes down to remove the tlv, and adjust total length
2734 // Don't adjust the current offset
2735 memmove(result_buffer + offset,
2736 result_buffer + offset + tlv_total_length,
2737 client->result_length - (offset + tlv_total_length));
2738 client->result_length -= tlv_total_length;
2739 memset(result_buffer + client->result_length, 0, sizeof(client->result) - client->result_length);
2740 continue;
2741 }
2742 }
2743
2744 offset += tlv_total_length;
2745 }
2746 }
2747
2748 void
2749 necp_force_update_client(uuid_t client_id, uuid_t remove_netagent_uuid)
2750 {
2751 struct necp_fd_data *client_fd = NULL;
2752
2753 NECP_FD_LIST_LOCK_SHARED();
2754
2755 LIST_FOREACH(client_fd, &necp_fd_list, chain) {
2756 bool updated_result = FALSE;
2757 NECP_FD_LOCK(client_fd);
2758 struct necp_client *client = necp_client_fd_find_client_and_lock(client_fd, client_id);
2759 if (client != NULL) {
2760 if (!uuid_is_null(remove_netagent_uuid)) {
2761 necp_client_remove_agent_from_result(client, remove_netagent_uuid);
2762 }
2763 client->flow_result_read = FALSE;
2764 // Found the client, break
2765 updated_result = TRUE;
2766 NECP_CLIENT_UNLOCK(client);
2767 }
2768 if (updated_result) {
2769 necp_fd_notify(client_fd, true);
2770 }
2771 NECP_FD_UNLOCK(client_fd);
2772 if (updated_result) {
2773 // Found the client, break
2774 break;
2775 }
2776 }
2777
2778 NECP_FD_LIST_UNLOCK();
2779 }
2780
2781
2782 /// Interface matching
2783
2784 #define NECP_PARSED_PARAMETERS_INTERESTING_IFNET_FIELDS (NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR | \
2785 NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IF | \
2786 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE | \
2787 NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IFTYPE | \
2788 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT | \
2789 NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT | \
2790 NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT | \
2791 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT_TYPE | \
2792 NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT_TYPE | \
2793 NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE)
2794
2795 #define NECP_PARSED_PARAMETERS_SCOPED_IFNET_FIELDS (NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR | \
2796 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE | \
2797 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT | \
2798 NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT | \
2799 NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT_TYPE | \
2800 NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE)
2801
2802 #define NECP_PARSED_PARAMETERS_PREFERRED_IFNET_FIELDS (NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT | \
2803 NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE)
2804
2805 static bool
2806 necp_ifnet_matches_type(struct ifnet *ifp, u_int8_t interface_type, bool check_delegates)
2807 {
2808 struct ifnet *check_ifp = ifp;
2809 while (check_ifp) {
2810 if (if_functional_type(check_ifp, TRUE) == interface_type) {
2811 return (TRUE);
2812 }
2813 if (!check_delegates) {
2814 break;
2815 }
2816 check_ifp = check_ifp->if_delegated.ifp;
2817
2818 }
2819 return (FALSE);
2820 }
2821
2822 static bool
2823 necp_ifnet_matches_name(struct ifnet *ifp, const char *interface_name, bool check_delegates)
2824 {
2825 struct ifnet *check_ifp = ifp;
2826 while (check_ifp) {
2827 if (strncmp(check_ifp->if_xname, interface_name, IFXNAMSIZ) == 0) {
2828 return (TRUE);
2829 }
2830 if (!check_delegates) {
2831 break;
2832 }
2833 check_ifp = check_ifp->if_delegated.ifp;
2834 }
2835 return (FALSE);
2836 }
2837
2838 static bool
2839 necp_ifnet_matches_agent(struct ifnet *ifp, uuid_t *agent_uuid, bool check_delegates)
2840 {
2841 struct ifnet *check_ifp = ifp;
2842
2843 while (check_ifp != NULL) {
2844 ifnet_lock_shared(check_ifp);
2845 if (check_ifp->if_agentids != NULL) {
2846 for (u_int32_t index = 0; index < check_ifp->if_agentcount; index++) {
2847 if (uuid_compare(check_ifp->if_agentids[index], *agent_uuid) == 0) {
2848 ifnet_lock_done(check_ifp);
2849 return (TRUE);
2850 }
2851 }
2852 }
2853 ifnet_lock_done(check_ifp);
2854
2855 if (!check_delegates) {
2856 break;
2857 }
2858 check_ifp = check_ifp->if_delegated.ifp;
2859 }
2860 return (FALSE);
2861 }
2862
2863 static bool
2864 necp_necp_ifnet_matches_agent_type(struct ifnet *ifp, const char *agent_domain, const char *agent_type, bool check_delegates)
2865 {
2866 struct ifnet *check_ifp = ifp;
2867
2868 while (check_ifp != NULL) {
2869 ifnet_lock_shared(check_ifp);
2870 if (check_ifp->if_agentids != NULL) {
2871 for (u_int32_t index = 0; index < check_ifp->if_agentcount; index++) {
2872 if (uuid_is_null(check_ifp->if_agentids[index])) {
2873 continue;
2874 }
2875
2876 char if_agent_domain[NETAGENT_DOMAINSIZE] = { 0 };
2877 char if_agent_type[NETAGENT_TYPESIZE] = { 0 };
2878
2879 if (netagent_get_agent_domain_and_type(check_ifp->if_agentids[index], if_agent_domain, if_agent_type)) {
2880 if ((strlen(agent_domain) == 0 ||
2881 strncmp(if_agent_domain, agent_domain, NETAGENT_DOMAINSIZE) == 0) &&
2882 (strlen(agent_type) == 0 ||
2883 strncmp(if_agent_type, agent_type, NETAGENT_TYPESIZE) == 0)) {
2884 ifnet_lock_done(check_ifp);
2885 return (TRUE);
2886 }
2887 }
2888 }
2889 }
2890 ifnet_lock_done(check_ifp);
2891
2892 if (!check_delegates) {
2893 break;
2894 }
2895 check_ifp = check_ifp->if_delegated.ifp;
2896 }
2897 return (FALSE);
2898 }
2899
2900 static bool
2901 necp_ifnet_matches_local_address(struct ifnet *ifp, struct sockaddr *sa)
2902 {
2903 struct ifaddr *ifa = NULL;
2904 bool matched_local_address = FALSE;
2905
2906 // Transform sa into the ifaddr form
2907 // IPv6 Scope IDs are always embedded in the ifaddr list
2908 struct sockaddr_storage address;
2909 u_int ifscope = IFSCOPE_NONE;
2910 (void)sa_copy(sa, &address, &ifscope);
2911 SIN(&address)->sin_port = 0;
2912 if (address.ss_family == AF_INET6) {
2913 SIN6(&address)->sin6_scope_id = 0;
2914 }
2915
2916 ifa = ifa_ifwithaddr_scoped_locked((struct sockaddr *)&address, ifp->if_index);
2917 matched_local_address = (ifa != NULL);
2918
2919 if (ifa) {
2920 ifaddr_release(ifa);
2921 }
2922
2923 return (matched_local_address);
2924 }
2925
2926 static bool
2927 necp_interface_type_is_primary_eligible(u_int8_t interface_type)
2928 {
2929 switch (interface_type) {
2930 // These types can never be primary, so a client requesting these types is allowed
2931 // to match an interface that isn't currently eligible to be primary (has default
2932 // route, dns, etc)
2933 case IFRTYPE_FUNCTIONAL_WIFI_AWDL:
2934 case IFRTYPE_FUNCTIONAL_INTCOPROC:
2935 return false;
2936 default:
2937 break;
2938 }
2939 return true;
2940 }
2941
2942 #define NECP_IFP_IS_ON_ORDERED_LIST(_ifp) ((_ifp)->if_ordered_link.tqe_next != NULL || (_ifp)->if_ordered_link.tqe_prev != NULL)
2943
2944 static bool
2945 necp_ifnet_matches_parameters(struct ifnet *ifp,
2946 struct necp_client_parsed_parameters *parsed_parameters,
2947 u_int32_t *preferred_count, bool ignore_require_if)
2948 {
2949 if (preferred_count) {
2950 *preferred_count = 0;
2951 }
2952
2953 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_LOCAL_ADDR) {
2954 if (!necp_ifnet_matches_local_address(ifp, &parsed_parameters->local_addr.sa)) {
2955 return (FALSE);
2956 }
2957 }
2958
2959 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_FLAGS) {
2960 if ((parsed_parameters->flags & NECP_CLIENT_PARAMETER_FLAG_PROHIBIT_EXPENSIVE) &&
2961 IFNET_IS_EXPENSIVE(ifp)) {
2962 return (FALSE);
2963 }
2964 }
2965
2966 if (!ignore_require_if &&
2967 (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE) &&
2968 !necp_ifnet_matches_type(ifp, parsed_parameters->required_interface_type, FALSE)) {
2969 return (FALSE);
2970 }
2971
2972 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IFTYPE) {
2973 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
2974 if (parsed_parameters->prohibited_interface_types[i] == 0) {
2975 break;
2976 }
2977
2978 if (necp_ifnet_matches_type(ifp, parsed_parameters->prohibited_interface_types[i], TRUE)) {
2979 return (FALSE);
2980 }
2981 }
2982 }
2983
2984 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_IF) {
2985 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
2986 if (strlen(parsed_parameters->prohibited_interfaces[i]) == 0) {
2987 break;
2988 }
2989
2990 if (necp_ifnet_matches_name(ifp, parsed_parameters->prohibited_interfaces[i], TRUE)) {
2991 return (FALSE);
2992 }
2993 }
2994 }
2995
2996 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT) {
2997 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
2998 if (uuid_is_null(parsed_parameters->required_netagents[i])) {
2999 break;
3000 }
3001
3002 if (!necp_ifnet_matches_agent(ifp, &parsed_parameters->required_netagents[i], FALSE)) {
3003 return (FALSE);
3004 }
3005 }
3006 }
3007
3008 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT) {
3009 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
3010 if (uuid_is_null(parsed_parameters->prohibited_netagents[i])) {
3011 break;
3012 }
3013
3014 if (necp_ifnet_matches_agent(ifp, &parsed_parameters->prohibited_netagents[i], TRUE)) {
3015 return (FALSE);
3016 }
3017 }
3018 }
3019
3020 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_REQUIRED_AGENT_TYPE) {
3021 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
3022 if (strlen(parsed_parameters->required_netagent_types[i].netagent_domain) == 0 &&
3023 strlen(parsed_parameters->required_netagent_types[i].netagent_type) == 0) {
3024 break;
3025 }
3026
3027 if (!necp_necp_ifnet_matches_agent_type(ifp, parsed_parameters->required_netagent_types[i].netagent_domain, parsed_parameters->required_netagent_types[i].netagent_type, FALSE)) {
3028 return (FALSE);
3029 }
3030 }
3031 }
3032
3033 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PROHIBITED_AGENT_TYPE) {
3034 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
3035 if (strlen(parsed_parameters->prohibited_netagent_types[i].netagent_domain) == 0 &&
3036 strlen(parsed_parameters->prohibited_netagent_types[i].netagent_type) == 0) {
3037 break;
3038 }
3039
3040 if (necp_necp_ifnet_matches_agent_type(ifp, parsed_parameters->prohibited_netagent_types[i].netagent_domain, parsed_parameters->prohibited_netagent_types[i].netagent_type, TRUE)) {
3041 return (FALSE);
3042 }
3043 }
3044 }
3045
3046 // Checked preferred properties
3047 if (preferred_count) {
3048 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT) {
3049 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
3050 if (uuid_is_null(parsed_parameters->preferred_netagents[i])) {
3051 break;
3052 }
3053
3054 if (necp_ifnet_matches_agent(ifp, &parsed_parameters->preferred_netagents[i], TRUE)) {
3055 (*preferred_count)++;
3056 }
3057 }
3058 }
3059
3060 if (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_PREFERRED_AGENT_TYPE) {
3061 for (int i = 0; i < NECP_MAX_PARSED_PARAMETERS; i++) {
3062 if (strlen(parsed_parameters->preferred_netagent_types[i].netagent_domain) == 0 &&
3063 strlen(parsed_parameters->preferred_netagent_types[i].netagent_type) == 0) {
3064 break;
3065 }
3066
3067 if (necp_necp_ifnet_matches_agent_type(ifp, parsed_parameters->preferred_netagent_types[i].netagent_domain, parsed_parameters->preferred_netagent_types[i].netagent_type, TRUE)) {
3068 (*preferred_count)++;
3069 }
3070 }
3071 }
3072 }
3073
3074 return (TRUE);
3075 }
3076
3077 static bool
3078 necp_find_matching_interface_index(struct necp_client_parsed_parameters *parsed_parameters, u_int *return_ifindex)
3079 {
3080 struct ifnet *ifp = NULL;
3081 u_int32_t best_preferred_count = 0;
3082 bool has_preferred_fields = FALSE;
3083 *return_ifindex = 0;
3084
3085 if (parsed_parameters->required_interface_index != 0) {
3086 *return_ifindex = parsed_parameters->required_interface_index;
3087 return (TRUE);
3088 }
3089
3090 if (!(parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_INTERESTING_IFNET_FIELDS)) {
3091 return (TRUE);
3092 }
3093
3094 has_preferred_fields = (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_PREFERRED_IFNET_FIELDS);
3095
3096 // We have interesting parameters to parse and find a matching interface
3097 ifnet_head_lock_shared();
3098
3099 if (!(parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_SCOPED_IFNET_FIELDS)) {
3100 // We do have fields to match, but they are only prohibitory
3101 // If the first interface in the list matches, or there are no ordered interfaces, we don't need to scope
3102 ifp = TAILQ_FIRST(&ifnet_ordered_head);
3103 if (ifp == NULL || necp_ifnet_matches_parameters(ifp, parsed_parameters, NULL, false)) {
3104 // Don't set return_ifindex, so the client doesn't need to scope
3105 ifnet_head_done();
3106 return (TRUE);
3107 }
3108 }
3109
3110 // First check the ordered interface list
3111 TAILQ_FOREACH(ifp, &ifnet_ordered_head, if_ordered_link) {
3112 u_int32_t preferred_count = 0;
3113 if (necp_ifnet_matches_parameters(ifp, parsed_parameters, &preferred_count, false)) {
3114 if (preferred_count > best_preferred_count ||
3115 *return_ifindex == 0) {
3116
3117 // Everything matched, and is most preferred. Return this interface.
3118 *return_ifindex = ifp->if_index;
3119 best_preferred_count = preferred_count;
3120
3121 if (!has_preferred_fields) {
3122 break;
3123 }
3124 }
3125 }
3126 }
3127
3128 // Then check the remaining interfaces
3129 if ((parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_SCOPED_IFNET_FIELDS) &&
3130 ((!(parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_FIELD_REQUIRED_IFTYPE)) ||
3131 !necp_interface_type_is_primary_eligible(parsed_parameters->required_interface_type)) &&
3132 *return_ifindex == 0) {
3133 TAILQ_FOREACH(ifp, &ifnet_head, if_link) {
3134 u_int32_t preferred_count = 0;
3135 if (NECP_IFP_IS_ON_ORDERED_LIST(ifp)) {
3136 // This interface was in the ordered list, skip
3137 continue;
3138 }
3139 if (necp_ifnet_matches_parameters(ifp, parsed_parameters, &preferred_count, false)) {
3140 if (preferred_count > best_preferred_count ||
3141 *return_ifindex == 0) {
3142
3143 // Everything matched, and is most preferred. Return this interface.
3144 *return_ifindex = ifp->if_index;
3145 best_preferred_count = preferred_count;
3146
3147 if (!has_preferred_fields) {
3148 break;
3149 }
3150 }
3151 }
3152 }
3153 }
3154
3155 ifnet_head_done();
3156
3157 if ((parsed_parameters->valid_fields == (parsed_parameters->valid_fields & NECP_PARSED_PARAMETERS_PREFERRED_IFNET_FIELDS)) &&
3158 best_preferred_count == 0) {
3159 // If only has preferred fields, and nothing was found, clear the interface index and return TRUE
3160 *return_ifindex = 0;
3161 return (TRUE);
3162 }
3163
3164 return (*return_ifindex != 0);
3165 }
3166
3167
3168 static int
3169 necp_skywalk_priv_check_cred(proc_t p, kauth_cred_t cred)
3170 {
3171 #pragma unused(p, cred)
3172 return (0);
3173 }
3174
3175 /// System calls
3176
3177 int
3178 necp_open(struct proc *p, struct necp_open_args *uap, int *retval)
3179 {
3180 #pragma unused(retval)
3181 int error = 0;
3182 struct necp_fd_data *fd_data = NULL;
3183 struct fileproc *fp = NULL;
3184 int fd = -1;
3185
3186 if (uap->flags & NECP_OPEN_FLAG_OBSERVER) {
3187 if (necp_skywalk_priv_check_cred(p, kauth_cred_get()) != 0 &&
3188 priv_check_cred(kauth_cred_get(), PRIV_NET_PRIVILEGED_NETWORK_STATISTICS, 0) != 0) {
3189 NECPLOG0(LOG_ERR, "Client does not hold necessary entitlement to observe other NECP clients");
3190 error = EACCES;
3191 goto done;
3192 }
3193 }
3194
3195 error = falloc(p, &fp, &fd, vfs_context_current());
3196 if (error != 0) {
3197 goto done;
3198 }
3199
3200 if ((fd_data = zalloc(necp_client_fd_zone)) == NULL) {
3201 error = ENOMEM;
3202 goto done;
3203 }
3204
3205 memset(fd_data, 0, sizeof(*fd_data));
3206
3207 fd_data->necp_fd_type = necp_fd_type_client;
3208 fd_data->flags = uap->flags;
3209 RB_INIT(&fd_data->clients);
3210 TAILQ_INIT(&fd_data->update_list);
3211 lck_mtx_init(&fd_data->fd_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
3212 klist_init(&fd_data->si.si_note);
3213 fd_data->proc_pid = proc_pid(p);
3214
3215 fp->f_fglob->fg_flag = FREAD;
3216 fp->f_fglob->fg_ops = &necp_fd_ops;
3217 fp->f_fglob->fg_data = fd_data;
3218
3219 proc_fdlock(p);
3220
3221 *fdflags(p, fd) |= (UF_EXCLOSE | UF_FORKCLOSE);
3222 procfdtbl_releasefd(p, fd, NULL);
3223 fp_drop(p, fd, fp, 1);
3224
3225 *retval = fd;
3226
3227 if (fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER) {
3228 NECP_OBSERVER_LIST_LOCK_EXCLUSIVE();
3229 LIST_INSERT_HEAD(&necp_fd_observer_list, fd_data, chain);
3230 OSIncrementAtomic(&necp_observer_fd_count);
3231 NECP_OBSERVER_LIST_UNLOCK();
3232
3233 // Walk all existing clients and add them
3234 NECP_CLIENT_TREE_LOCK_SHARED();
3235 struct necp_client *existing_client = NULL;
3236 RB_FOREACH(existing_client, _necp_client_global_tree, &necp_client_global_tree) {
3237 NECP_CLIENT_LOCK(existing_client);
3238 necp_client_update_observer_add_internal(fd_data, existing_client);
3239 necp_client_update_observer_update_internal(fd_data, existing_client);
3240 NECP_CLIENT_UNLOCK(existing_client);
3241 }
3242 NECP_CLIENT_TREE_UNLOCK();
3243 } else {
3244 NECP_FD_LIST_LOCK_EXCLUSIVE();
3245 LIST_INSERT_HEAD(&necp_fd_list, fd_data, chain);
3246 OSIncrementAtomic(&necp_client_fd_count);
3247 NECP_FD_LIST_UNLOCK();
3248 }
3249
3250 proc_fdunlock(p);
3251
3252 done:
3253 if (error != 0) {
3254 if (fp != NULL) {
3255 fp_free(p, fd, fp);
3256 fp = NULL;
3257 }
3258 if (fd_data != NULL) {
3259 zfree(necp_client_fd_zone, fd_data);
3260 fd_data = NULL;
3261 }
3262 }
3263
3264 return (error);
3265 }
3266
3267 static int
3268 necp_client_add(struct proc *p, struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
3269 {
3270 int error = 0;
3271 struct necp_client *client = NULL;
3272
3273 if (fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER) {
3274 NECPLOG0(LOG_ERR, "NECP client observers with push enabled may not add their own clients");
3275 return (EINVAL);
3276 }
3277
3278 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) ||
3279 uap->buffer_size == 0 || uap->buffer_size > NECP_MAX_CLIENT_PARAMETERS_SIZE || uap->buffer == 0) {
3280 return (EINVAL);
3281 }
3282
3283 if ((client = _MALLOC(sizeof(struct necp_client) + uap->buffer_size, M_NECP,
3284 M_WAITOK | M_ZERO)) == NULL) {
3285 error = ENOMEM;
3286 goto done;
3287 }
3288
3289 error = copyin(uap->buffer, client->parameters, uap->buffer_size);
3290 if (error) {
3291 NECPLOG(LOG_ERR, "necp_client_add parameters copyin error (%d)", error);
3292 goto done;
3293 }
3294
3295 lck_mtx_init(&client->lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
3296 lck_mtx_init(&client->route_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
3297 necp_client_retain(client); // Hold our reference until close
3298
3299 client->parameters_length = uap->buffer_size;
3300 client->proc_pid = fd_data->proc_pid; // Save off proc pid in case the client will persist past fd
3301 client->platform_binary = ((csproc_get_platform_binary(p) == 0) ? 0 : 1);
3302
3303 uuid_generate_random(client->client_id);
3304 LIST_INIT(&client->assertion_list);
3305 LIST_INIT(&client->flow_list);
3306
3307 error = copyout(client->client_id, uap->client_id, sizeof(uuid_t));
3308 if (error) {
3309 NECPLOG(LOG_ERR, "necp_client_add client_id copyout error (%d)", error);
3310 goto done;
3311 }
3312
3313 necp_client_update_observer_add(client);
3314
3315 NECP_FD_LOCK(fd_data);
3316 RB_INSERT(_necp_client_tree, &fd_data->clients, client);
3317 OSIncrementAtomic(&necp_client_count);
3318 NECP_CLIENT_TREE_LOCK_EXCLUSIVE();
3319 RB_INSERT(_necp_client_global_tree, &necp_client_global_tree, client);
3320 NECP_CLIENT_TREE_UNLOCK();
3321
3322 // Prime the client result
3323 NECP_CLIENT_LOCK(client);
3324 (void)necp_update_client_result(current_proc(), fd_data, client, NULL);
3325 NECP_CLIENT_UNLOCK(client);
3326 NECP_FD_UNLOCK(fd_data);
3327 done:
3328 if (error != 0) {
3329 if (client != NULL) {
3330 FREE(client, M_NECP);
3331 client = NULL;
3332 }
3333 }
3334 *retval = error;
3335
3336 return (error);
3337 }
3338
3339 static int
3340 necp_client_remove(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
3341 {
3342 int error = 0;
3343 struct necp_client *client = NULL;
3344 struct necp_client find = {};
3345 uuid_t client_id = {};
3346 struct ifnet_stats_per_flow flow_ifnet_stats = {};
3347
3348 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t)) {
3349 error = EINVAL;
3350 goto done;
3351 }
3352
3353 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
3354 if (error) {
3355 NECPLOG(LOG_ERR, "necp_client_remove copyin client_id error (%d)", error);
3356 goto done;
3357 }
3358
3359 if (uap->buffer != 0 && uap->buffer_size == sizeof(flow_ifnet_stats)) {
3360 error = copyin(uap->buffer, &flow_ifnet_stats, uap->buffer_size);
3361 if (error) {
3362 NECPLOG(LOG_ERR, "necp_client_remove flow_ifnet_stats copyin error (%d)", error);
3363 // Not fatal; make sure to zero-out stats in case of partial copy
3364 memset(&flow_ifnet_stats, 0, sizeof (flow_ifnet_stats));
3365 error = 0;
3366 }
3367 } else if (uap->buffer != 0) {
3368 NECPLOG(LOG_ERR, "necp_client_remove unexpected parameters length (%zu)", uap->buffer_size);
3369 }
3370
3371 NECP_FD_LOCK(fd_data);
3372
3373 pid_t pid = fd_data->proc_pid;
3374 uuid_copy(find.client_id, client_id);
3375 client = RB_FIND(_necp_client_tree, &fd_data->clients, &find);
3376 if (client != NULL) {
3377 NECP_CLIENT_TREE_LOCK_EXCLUSIVE();
3378 RB_REMOVE(_necp_client_global_tree, &necp_client_global_tree, client);
3379 NECP_CLIENT_TREE_UNLOCK();
3380 RB_REMOVE(_necp_client_tree, &fd_data->clients, client);
3381 }
3382
3383 NECP_FD_UNLOCK(fd_data);
3384
3385 if (client != NULL) {
3386 ASSERT(error == 0);
3387 necp_destroy_client(client, pid, true);
3388 } else {
3389 error = ENOENT;
3390 NECPLOG(LOG_ERR, "necp_client_remove invalid client_id (%d)", error);
3391 }
3392
3393 done:
3394 *retval = error;
3395
3396 return (error);
3397 }
3398
3399 static int
3400 necp_client_check_tcp_heuristics(struct necp_client *client, struct necp_client_flow *flow, u_int32_t *flags, u_int8_t *tfo_cookie, u_int8_t *tfo_cookie_len)
3401 {
3402 struct necp_client_parsed_parameters parsed_parameters;
3403 int error = 0;
3404
3405 error = necp_client_parse_parameters(client->parameters,
3406 (u_int32_t)client->parameters_length,
3407 &parsed_parameters);
3408 if (error) {
3409 NECPLOG(LOG_ERR, "necp_client_parse_parameters error (%d)", error);
3410 return (error);
3411 }
3412
3413 if ((flow->remote_addr.sa.sa_family != AF_INET &&
3414 flow->remote_addr.sa.sa_family != AF_INET6) ||
3415 (flow->local_addr.sa.sa_family != AF_INET &&
3416 flow->local_addr.sa.sa_family != AF_INET6)) {
3417 return (EINVAL);
3418 }
3419
3420 NECP_CLIENT_ROUTE_LOCK(client);
3421
3422 if (client->current_route == NULL) {
3423 error = ENOENT;
3424 goto do_unlock;
3425 }
3426
3427 bool check_ecn = false;
3428 do {
3429 if ((parsed_parameters.flags & NECP_CLIENT_PARAMETER_FLAG_ECN_ENABLE) ==
3430 NECP_CLIENT_PARAMETER_FLAG_ECN_ENABLE) {
3431 check_ecn = true;
3432 break;
3433 }
3434
3435 if ((parsed_parameters.flags & NECP_CLIENT_PARAMETER_FLAG_ECN_DISABLE) ==
3436 NECP_CLIENT_PARAMETER_FLAG_ECN_DISABLE) {
3437 break;
3438 }
3439
3440 if (client->current_route != NULL) {
3441 if (client->current_route->rt_ifp->if_eflags & IFEF_ECN_ENABLE) {
3442 check_ecn = true;
3443 break;
3444 }
3445 if (client->current_route->rt_ifp->if_eflags & IFEF_ECN_DISABLE) {
3446 break;
3447 }
3448 }
3449
3450 bool inbound = ((parsed_parameters.flags & NECP_CLIENT_PARAMETER_FLAG_LISTENER) == 0);
3451 if ((inbound && tcp_ecn_inbound == 1) ||
3452 (!inbound && tcp_ecn_outbound == 1)) {
3453 check_ecn = true;
3454 }
3455 } while (false);
3456
3457 if (check_ecn) {
3458 if (tcp_heuristic_do_ecn_with_address(client->current_route->rt_ifp,
3459 (union sockaddr_in_4_6 *)&flow->local_addr)) {
3460 *flags |= NECP_CLIENT_RESULT_FLAG_ECN_ENABLED;
3461 }
3462 }
3463
3464 if ((parsed_parameters.flags & NECP_CLIENT_PARAMETER_FLAG_TFO_ENABLE) ==
3465 NECP_CLIENT_PARAMETER_FLAG_TFO_ENABLE) {
3466
3467 if (!tcp_heuristic_do_tfo_with_address(client->current_route->rt_ifp,
3468 (union sockaddr_in_4_6 *)&flow->local_addr,
3469 (union sockaddr_in_4_6 *)&flow->remote_addr,
3470 tfo_cookie, tfo_cookie_len)) {
3471 *flags |= NECP_CLIENT_RESULT_FLAG_FAST_OPEN_BLOCKED;
3472 *tfo_cookie_len = 0;
3473 }
3474 } else {
3475 *flags |= NECP_CLIENT_RESULT_FLAG_FAST_OPEN_BLOCKED;
3476 *tfo_cookie_len = 0;
3477 }
3478 do_unlock:
3479 NECP_CLIENT_ROUTE_UNLOCK(client);
3480
3481 return (error);
3482 }
3483
3484 static int
3485 necp_client_copy_internal(struct necp_client *client, bool client_is_observed, struct necp_client_action_args *uap, int *retval)
3486 {
3487 int error = 0;
3488 // Copy results out
3489 if (uap->action == NECP_CLIENT_ACTION_COPY_PARAMETERS) {
3490 if (uap->buffer_size < client->parameters_length) {
3491 error = EINVAL;
3492 goto done;
3493 }
3494 error = copyout(client->parameters, uap->buffer, client->parameters_length);
3495 if (error) {
3496 NECPLOG(LOG_ERR, "necp_client_copy parameters copyout error (%d)", error);
3497 goto done;
3498 }
3499 *retval = client->parameters_length;
3500 } else if (uap->action == NECP_CLIENT_ACTION_COPY_UPDATED_RESULT &&
3501 client->result_read && client->flow_result_read) {
3502 // Copy updates only, but nothing to read
3503 // Just return 0 for bytes read
3504 *retval = 0;
3505 } else if (uap->action == NECP_CLIENT_ACTION_COPY_RESULT ||
3506 uap->action == NECP_CLIENT_ACTION_COPY_UPDATED_RESULT) {
3507 size_t assigned_results_size = 0;
3508 struct necp_client_flow *flow = NULL;
3509 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
3510 if (flow->nexus || (flow->socket && flow->assigned)) {
3511 size_t header_length = 0;
3512 if (flow->nexus) {
3513 header_length = sizeof(struct necp_client_nexus_flow_header);
3514 } else {
3515 header_length = sizeof(struct necp_client_flow_header);
3516 }
3517 assigned_results_size += (header_length + flow->assigned_results_length);
3518
3519 if (flow->has_protoctl_event) {
3520 assigned_results_size += sizeof(struct necp_client_flow_protoctl_event_header);
3521 }
3522 }
3523 }
3524 if (uap->buffer_size < (client->result_length + assigned_results_size)) {
3525 error = EINVAL;
3526 goto done;
3527 }
3528 error = copyout(client->result, uap->buffer, client->result_length);
3529 if (error) {
3530 NECPLOG(LOG_ERR, "necp_client_copy result copyout error (%d)", error);
3531 goto done;
3532 }
3533
3534 size_t assigned_results_cursor = 0;
3535
3536 flow = NULL;
3537 LIST_FOREACH(flow, &client->flow_list, flow_chain) {
3538 if (flow->nexus || (flow->socket && flow->assigned)) {
3539 // Write TLV headers
3540 struct necp_client_nexus_flow_header header = {};
3541 u_int32_t length = 0;
3542 u_int32_t flags = 0;
3543 u_int8_t tfo_cookie_len = 0;
3544 u_int8_t type = 0;
3545
3546 if (flow->nexus) {
3547 if (flow->check_tcp_heuristics) {
3548 u_int8_t tfo_cookie[NECP_TFO_COOKIE_LEN_MAX];
3549 tfo_cookie_len = NECP_TFO_COOKIE_LEN_MAX;
3550
3551 if (necp_client_check_tcp_heuristics(client, flow, &flags,
3552 tfo_cookie, &tfo_cookie_len) != 0) {
3553 tfo_cookie_len = 0;
3554 } else {
3555 flow->check_tcp_heuristics = FALSE;
3556
3557 if (tfo_cookie_len != 0) {
3558 type = NECP_CLIENT_RESULT_TFO_COOKIE;
3559 length = tfo_cookie_len;
3560 memcpy(&header.tfo_cookie_tlv_header.type, &type, sizeof(type));
3561 memcpy(&header.tfo_cookie_tlv_header.length, &length, sizeof(length));
3562 memcpy(&header.tfo_cookie_value, tfo_cookie, tfo_cookie_len);
3563 }
3564 }
3565 }
3566 }
3567
3568 size_t header_length = 0;
3569 if (flow->nexus) {
3570 if (tfo_cookie_len != 0) {
3571 header_length = sizeof(struct necp_client_nexus_flow_header) - (NECP_TFO_COOKIE_LEN_MAX - tfo_cookie_len);
3572 } else {
3573 header_length = sizeof(struct necp_client_nexus_flow_header) - sizeof(struct necp_tlv_header) - NECP_TFO_COOKIE_LEN_MAX;
3574 }
3575 } else {
3576 header_length = sizeof(struct necp_client_flow_header);
3577 }
3578
3579 type = NECP_CLIENT_RESULT_FLAGS;
3580 length = sizeof(header.flow_header.flags_value);
3581 memcpy(&header.flow_header.flags_tlv_header.type, &type, sizeof(type));
3582 memcpy(&header.flow_header.flags_tlv_header.length, &length, sizeof(length));
3583 if (flow->assigned) {
3584 flags |= NECP_CLIENT_RESULT_FLAG_FLOW_ASSIGNED;
3585 }
3586 if (flow->viable) {
3587 flags |= NECP_CLIENT_RESULT_FLAG_FLOW_VIABLE;
3588 }
3589 memcpy(&header.flow_header.flags_value, &flags, sizeof(flags));
3590
3591 type = NECP_CLIENT_RESULT_INTERFACE;
3592 length = sizeof(header.flow_header.interface_value);
3593 memcpy(&header.flow_header.interface_tlv_header.type, &type, sizeof(type));
3594 memcpy(&header.flow_header.interface_tlv_header.length, &length, sizeof(length));
3595
3596 struct necp_client_result_interface interface_struct;
3597 interface_struct.generation = 0;
3598 interface_struct.index = flow->interface_index;
3599
3600 memcpy(&header.flow_header.interface_value, &interface_struct, sizeof(interface_struct));
3601 if (flow->nexus) {
3602 type = NECP_CLIENT_RESULT_NETAGENT;
3603 length = sizeof(header.agent_value);
3604 memcpy(&header.agent_tlv_header.type, &type, sizeof(type));
3605 memcpy(&header.agent_tlv_header.length, &length, sizeof(length));
3606
3607 struct necp_client_result_netagent agent_struct;
3608 agent_struct.generation = 0;
3609 uuid_copy(agent_struct.netagent_uuid, flow->u.nexus_agent);
3610
3611 memcpy(&header.agent_value, &agent_struct, sizeof(agent_struct));
3612 }
3613
3614 // Don't include outer TLV header in length field
3615 type = NECP_CLIENT_RESULT_FLOW;
3616 length = (header_length - sizeof(struct necp_tlv_header) + flow->assigned_results_length);
3617 if (flow->has_protoctl_event) {
3618 length += sizeof(struct necp_client_flow_protoctl_event_header);
3619 }
3620 memcpy(&header.flow_header.outer_header.type, &type, sizeof(type));
3621 memcpy(&header.flow_header.outer_header.length, &length, sizeof(length));
3622
3623 error = copyout(&header, uap->buffer + client->result_length + assigned_results_cursor, header_length);
3624 if (error) {
3625 NECPLOG(LOG_ERR, "necp_client_copy assigned results tlv_header copyout error (%d)", error);
3626 goto done;
3627 }
3628 assigned_results_cursor += header_length;
3629
3630 if (flow->assigned_results && flow->assigned_results_length) {
3631 // Write inner TLVs
3632 error = copyout(flow->assigned_results, uap->buffer + client->result_length + assigned_results_cursor,
3633 flow->assigned_results_length);
3634 if (error) {
3635 NECPLOG(LOG_ERR, "necp_client_copy assigned results copyout error (%d)", error);
3636 goto done;
3637 }
3638 }
3639 assigned_results_cursor += flow->assigned_results_length;
3640
3641 /* Read the protocol event and reset it */
3642 if (flow->has_protoctl_event) {
3643 struct necp_client_flow_protoctl_event_header protoctl_event_header = {};
3644
3645 type = NECP_CLIENT_RESULT_PROTO_CTL_EVENT;
3646 length = sizeof(protoctl_event_header.protoctl_event);
3647
3648 memcpy(&protoctl_event_header.protoctl_tlv_header.type, &type, sizeof(type));
3649 memcpy(&protoctl_event_header.protoctl_tlv_header.length, &length, sizeof(length));
3650 memcpy(&protoctl_event_header.protoctl_event, &flow->protoctl_event,
3651 sizeof(flow->protoctl_event));
3652
3653 error = copyout(&protoctl_event_header, uap->buffer + client->result_length + assigned_results_cursor,
3654 sizeof(protoctl_event_header));
3655
3656 if (error) {
3657 NECPLOG(LOG_ERR, "necp_client_copy protocol control event results"
3658 " tlv_header copyout error (%d)", error);
3659 goto done;
3660 }
3661 assigned_results_cursor += sizeof(protoctl_event_header);
3662 flow->has_protoctl_event = FALSE;
3663 flow->protoctl_event.protoctl_event_code = 0;
3664 flow->protoctl_event.protoctl_event_val = 0;
3665 flow->protoctl_event.protoctl_event_tcp_seq_num = 0;
3666 }
3667 }
3668 }
3669
3670 *retval = client->result_length + assigned_results_cursor;
3671
3672 if (!client_is_observed) {
3673 client->result_read = TRUE;
3674 client->flow_result_read = TRUE;
3675 }
3676 }
3677
3678 done:
3679 return (error);
3680 }
3681
3682 static int
3683 necp_client_copy(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
3684 {
3685 int error = 0;
3686 struct necp_client *client = NULL;
3687 uuid_t client_id;
3688 uuid_clear(client_id);
3689
3690 *retval = 0;
3691
3692 if (uap->buffer_size == 0 || uap->buffer == 0) {
3693 error = EINVAL;
3694 goto done;
3695 }
3696
3697 if (uap->action != NECP_CLIENT_ACTION_COPY_PARAMETERS &&
3698 uap->action != NECP_CLIENT_ACTION_COPY_RESULT &&
3699 uap->action != NECP_CLIENT_ACTION_COPY_UPDATED_RESULT) {
3700 error = EINVAL;
3701 goto done;
3702 }
3703
3704 if (uap->client_id) {
3705 if (uap->client_id_len != sizeof(uuid_t)) {
3706 NECPLOG(LOG_ERR, "Incorrect length (got %d, expected %d)", uap->client_id_len, sizeof(uuid_t));
3707 error = ERANGE;
3708 goto done;
3709 }
3710
3711 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
3712 if (error) {
3713 NECPLOG(LOG_ERR, "necp_client_copy client_id copyin error (%d)", error);
3714 goto done;
3715 }
3716 }
3717
3718 const bool is_wildcard = (bool)uuid_is_null(client_id);
3719
3720 NECP_FD_LOCK(fd_data);
3721
3722 if (is_wildcard) {
3723 if (uap->action == NECP_CLIENT_ACTION_COPY_RESULT || uap->action == NECP_CLIENT_ACTION_COPY_UPDATED_RESULT) {
3724 struct necp_client *find_client = NULL;
3725 RB_FOREACH(find_client, _necp_client_tree, &fd_data->clients) {
3726 NECP_CLIENT_LOCK(find_client);
3727 if (!find_client->result_read || !find_client->flow_result_read) {
3728 client = find_client;
3729 // Leave the client locked, and break
3730 break;
3731 }
3732 NECP_CLIENT_UNLOCK(find_client);
3733 }
3734 }
3735 } else {
3736 client = necp_client_fd_find_client_and_lock(fd_data, client_id);
3737 }
3738
3739 if (client != NULL) {
3740 // If client is set, it is locked
3741 error = necp_client_copy_internal(client, FALSE, uap, retval);
3742 NECP_CLIENT_UNLOCK(client);
3743 }
3744
3745 // Unlock our own fd before moving on or returning
3746 NECP_FD_UNLOCK(fd_data);
3747
3748 if (client == NULL) {
3749 if (fd_data->flags & NECP_OPEN_FLAG_OBSERVER) {
3750 // Observers are allowed to lookup clients on other fds
3751
3752 // Lock tree
3753 NECP_CLIENT_TREE_LOCK_SHARED();
3754
3755 bool found_client = FALSE;
3756
3757 struct necp_client find;
3758 uuid_copy(find.client_id, client_id);
3759 client = RB_FIND(_necp_client_global_tree, &necp_client_global_tree, &find);
3760 if (client != NULL) {
3761 NECP_CLIENT_LOCK(client);
3762
3763 // Matched, copy out data
3764 found_client = TRUE;
3765 error = necp_client_copy_internal(client, TRUE, uap, retval);
3766
3767 NECP_CLIENT_UNLOCK(client);
3768 }
3769
3770 // Unlock tree
3771 NECP_CLIENT_TREE_UNLOCK();
3772
3773 // No client found, fail
3774 if (!found_client) {
3775 error = ENOENT;
3776 goto done;
3777 }
3778 } else {
3779 // No client found, and not allowed to search other fds, fail
3780 error = ENOENT;
3781 goto done;
3782 }
3783 }
3784
3785 done:
3786 return (error);
3787 }
3788
3789 static int
3790 necp_client_copy_client_update(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
3791 {
3792 int error = 0;
3793
3794 *retval = 0;
3795
3796 if (!(fd_data->flags & NECP_OPEN_FLAG_PUSH_OBSERVER)) {
3797 NECPLOG0(LOG_ERR, "NECP fd is not observer, cannot copy client update");
3798 return (EINVAL);
3799 }
3800
3801 if (uap->client_id_len != sizeof(uuid_t) || uap->client_id == 0) {
3802 NECPLOG0(LOG_ERR, "Client id invalid, cannot copy client update");
3803 return (EINVAL);
3804 }
3805
3806 if (uap->buffer_size == 0 || uap->buffer == 0) {
3807 NECPLOG0(LOG_ERR, "Buffer invalid, cannot copy client update");
3808 return (EINVAL);
3809 }
3810
3811 NECP_FD_LOCK(fd_data);
3812 struct necp_client_update *client_update = TAILQ_FIRST(&fd_data->update_list);
3813 if (client_update != NULL) {
3814 TAILQ_REMOVE(&fd_data->update_list, client_update, chain);
3815 VERIFY(fd_data->update_count > 0);
3816 fd_data->update_count--;
3817 }
3818 NECP_FD_UNLOCK(fd_data);
3819
3820 if (client_update != NULL) {
3821 error = copyout(client_update->client_id, uap->client_id, sizeof(uuid_t));
3822 if (error) {
3823 NECPLOG(LOG_ERR, "Copy client update copyout client id error (%d)", error);
3824 } else {
3825 if (uap->buffer_size < client_update->update_length) {
3826 NECPLOG(LOG_ERR, "Buffer size cannot hold update (%zu < %zu)", uap->buffer_size, client_update->update_length);
3827 error = EINVAL;
3828 } else {
3829 error = copyout(&client_update->update, uap->buffer, client_update->update_length);
3830 if (error) {
3831 NECPLOG(LOG_ERR, "Copy client update copyout error (%d)", error);
3832 } else {
3833 *retval = client_update->update_length;
3834 }
3835 }
3836 }
3837
3838 FREE(client_update, M_NECP);
3839 client_update = NULL;
3840 } else {
3841 error = ENOENT;
3842 }
3843
3844 return (error);
3845 }
3846
3847 static int
3848 necp_client_copy_parameters_locked(struct necp_client *client, struct necp_client_nexus_parameters *parameters)
3849 {
3850 VERIFY(parameters != NULL);
3851
3852 struct necp_client_parsed_parameters parsed_parameters = {};
3853 int error = necp_client_parse_parameters(client->parameters, (u_int32_t)client->parameters_length, &parsed_parameters);
3854
3855 parameters->pid = client->proc_pid;
3856 if (parsed_parameters.valid_fields & NECP_PARSED_PARAMETERS_FIELD_EFFECTIVE_PID) {
3857 parameters->epid = parsed_parameters.effective_pid;
3858 } else {
3859 parameters->epid = parameters->pid;
3860 }
3861 memcpy(&parameters->local_addr, &parsed_parameters.local_addr, sizeof(parameters->local_addr));
3862 memcpy(&parameters->remote_addr, &parsed_parameters.remote_addr, sizeof(parameters->remote_addr));
3863 parameters->ip_protocol = parsed_parameters.ip_protocol;
3864 parameters->traffic_class = parsed_parameters.traffic_class;
3865 uuid_copy(parameters->euuid, parsed_parameters.effective_uuid);
3866 parameters->is_listener = (parsed_parameters.flags & NECP_CLIENT_PARAMETER_FLAG_LISTENER) ? 1 : 0;
3867 parameters->policy_id = client->policy_id;
3868
3869 // parse client result flag
3870 u_int32_t client_result_flags = 0;
3871 u_int32_t value_size = 0;
3872 u_int8_t *flags_pointer = NULL;
3873 flags_pointer = necp_buffer_get_tlv_value(client->result, 0, &value_size);
3874 if (flags_pointer && value_size == sizeof(client_result_flags)) {
3875 memcpy(&client_result_flags, flags_pointer, value_size);
3876 }
3877 parameters->allow_qos_marking = (client_result_flags & NECP_CLIENT_RESULT_FLAG_ALLOW_QOS_MARKING) ? 1 : 0;
3878
3879 return (error);
3880 }
3881
3882 int
3883 necp_client_copy_parameters(uuid_t client_id, struct necp_client_nexus_parameters *parameters)
3884 {
3885 int error = 0;
3886 struct necp_client *client = NULL;
3887
3888 if (parameters == NULL) {
3889 return EINVAL;
3890 }
3891
3892 // Lock tree
3893 NECP_CLIENT_TREE_LOCK_SHARED();
3894
3895 bool found_client = FALSE;
3896 struct necp_client find;
3897 uuid_copy(find.client_id, client_id);
3898 client = RB_FIND(_necp_client_global_tree, &necp_client_global_tree, &find);
3899 if (client != NULL) {
3900 NECP_CLIENT_LOCK(client);
3901
3902 // Matched, parse parameters
3903 found_client = TRUE;
3904 error = necp_client_copy_parameters_locked(client, parameters);
3905
3906 NECP_CLIENT_UNLOCK(client);
3907 }
3908
3909 // Unlock tree
3910 NECP_CLIENT_TREE_UNLOCK();
3911
3912 // No client found, fail
3913 if (!found_client) {
3914 return ENOENT;
3915 }
3916
3917 return error;
3918 }
3919
3920 static int
3921 necp_client_list(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
3922 {
3923 int error = 0;
3924 struct necp_client *find_client = NULL;
3925 uuid_t *list = NULL;
3926 u_int32_t requested_client_count = 0;
3927 u_int32_t client_count = 0;
3928 size_t copy_buffer_size = 0;
3929
3930 if (uap->buffer_size < sizeof(requested_client_count) || uap->buffer == 0) {
3931 error = EINVAL;
3932 goto done;
3933 }
3934
3935 if (!(fd_data->flags & NECP_OPEN_FLAG_OBSERVER)) {
3936 NECPLOG0(LOG_ERR, "Client does not hold necessary entitlement to list other NECP clients");
3937 error = EACCES;
3938 goto done;
3939 }
3940
3941 error = copyin(uap->buffer, &requested_client_count, sizeof(requested_client_count));
3942 if (error) {
3943 goto done;
3944 }
3945
3946 if (os_mul_overflow(sizeof(uuid_t), requested_client_count, &copy_buffer_size)) {
3947 error = ERANGE;
3948 goto done;
3949 }
3950
3951 if (uap->buffer_size - sizeof(requested_client_count) != copy_buffer_size) {
3952 error = EINVAL;
3953 goto done;
3954 }
3955
3956 if (copy_buffer_size > NECP_MAX_CLIENT_LIST_SIZE) {
3957 error = EINVAL;
3958 goto done;
3959 }
3960
3961 if (requested_client_count > 0) {
3962 if ((list = _MALLOC(copy_buffer_size, M_NECP, M_WAITOK | M_ZERO)) == NULL) {
3963 error = ENOMEM;
3964 goto done;
3965 }
3966 }
3967
3968 // Lock tree
3969 NECP_CLIENT_TREE_LOCK_SHARED();
3970
3971 find_client = NULL;
3972 RB_FOREACH(find_client, _necp_client_global_tree, &necp_client_global_tree) {
3973 NECP_CLIENT_LOCK(find_client);
3974 if (!uuid_is_null(find_client->client_id)) {
3975 if (client_count < requested_client_count) {
3976 uuid_copy(list[client_count], find_client->client_id);
3977 }
3978 client_count++;
3979 }
3980 NECP_CLIENT_UNLOCK(find_client);
3981 }
3982
3983 // Unlock tree
3984 NECP_CLIENT_TREE_UNLOCK();
3985
3986 error = copyout(&client_count, uap->buffer, sizeof(client_count));
3987 if (error) {
3988 NECPLOG(LOG_ERR, "necp_client_list buffer copyout error (%d)", error);
3989 goto done;
3990 }
3991
3992 if (requested_client_count > 0 &&
3993 client_count > 0 &&
3994 list != NULL) {
3995 error = copyout(list, uap->buffer + sizeof(client_count), copy_buffer_size);
3996 if (error) {
3997 NECPLOG(LOG_ERR, "necp_client_list client count copyout error (%d)", error);
3998 goto done;
3999 }
4000 }
4001 done:
4002 if (list != NULL) {
4003 FREE(list, M_NECP);
4004 }
4005 *retval = error;
4006
4007 return (error);
4008 }
4009
4010
4011 static void
4012 necp_client_add_assertion(struct necp_client *client, uuid_t netagent_uuid)
4013 {
4014 struct necp_client_assertion *new_assertion = NULL;
4015
4016 MALLOC(new_assertion, struct necp_client_assertion *, sizeof(*new_assertion), M_NECP, M_WAITOK);
4017 if (new_assertion == NULL) {
4018 NECPLOG0(LOG_ERR, "Failed to allocate assertion");
4019 return;
4020 }
4021
4022 uuid_copy(new_assertion->asserted_netagent, netagent_uuid);
4023
4024 LIST_INSERT_HEAD(&client->assertion_list, new_assertion, assertion_chain);
4025 }
4026
4027 static bool
4028 necp_client_remove_assertion(struct necp_client *client, uuid_t netagent_uuid)
4029 {
4030 struct necp_client_assertion *found_assertion = NULL;
4031 struct necp_client_assertion *search_assertion = NULL;
4032 LIST_FOREACH(search_assertion, &client->assertion_list, assertion_chain) {
4033 if (uuid_compare(search_assertion->asserted_netagent, netagent_uuid) == 0) {
4034 found_assertion = search_assertion;
4035 break;
4036 }
4037 }
4038
4039 if (found_assertion == NULL) {
4040 NECPLOG0(LOG_ERR, "Netagent uuid not previously asserted");
4041 return false;
4042 }
4043
4044 LIST_REMOVE(found_assertion, assertion_chain);
4045 FREE(found_assertion, M_NECP);
4046 return true;
4047 }
4048
4049 static int
4050 necp_client_agent_action(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4051 {
4052 int error = 0;
4053 struct necp_client *client = NULL;
4054 uuid_t client_id;
4055 bool acted_on_agent = FALSE;
4056 u_int8_t *parameters = NULL;
4057 size_t parameters_size = uap->buffer_size;
4058
4059 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) ||
4060 uap->buffer_size == 0 || uap->buffer == 0) {
4061 NECPLOG0(LOG_ERR, "necp_client_agent_action invalid parameters");
4062 error = EINVAL;
4063 goto done;
4064 }
4065
4066 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
4067 if (error) {
4068 NECPLOG(LOG_ERR, "necp_client_agent_action copyin client_id error (%d)", error);
4069 goto done;
4070 }
4071
4072 if ((parameters = _MALLOC(uap->buffer_size, M_NECP, M_WAITOK | M_ZERO)) == NULL) {
4073 NECPLOG0(LOG_ERR, "necp_client_agent_action malloc failed");
4074 error = ENOMEM;
4075 goto done;
4076 }
4077
4078 error = copyin(uap->buffer, parameters, uap->buffer_size);
4079 if (error) {
4080 NECPLOG(LOG_ERR, "necp_client_agent_action parameters copyin error (%d)", error);
4081 goto done;
4082 }
4083
4084 NECP_FD_LOCK(fd_data);
4085 client = necp_client_fd_find_client_and_lock(fd_data, client_id);
4086 if (client != NULL) {
4087 size_t offset = 0;
4088 while ((offset + sizeof(struct necp_tlv_header)) <= parameters_size) {
4089 u_int8_t type = necp_buffer_get_tlv_type(parameters, offset);
4090 u_int32_t length = necp_buffer_get_tlv_length(parameters, offset);
4091
4092 if (length > (parameters_size - (offset + sizeof(struct necp_tlv_header)))) {
4093 // If the length is larger than what can fit in the remaining parameters size, bail
4094 NECPLOG(LOG_ERR, "Invalid TLV length (%u)", length);
4095 break;
4096 }
4097
4098 if (length > 0) {
4099 u_int8_t *value = necp_buffer_get_tlv_value(parameters, offset, NULL);
4100 if (length >= sizeof(uuid_t) &&
4101 value != NULL &&
4102 (type == NECP_CLIENT_PARAMETER_TRIGGER_AGENT ||
4103 type == NECP_CLIENT_PARAMETER_ASSERT_AGENT ||
4104 type == NECP_CLIENT_PARAMETER_UNASSERT_AGENT)) {
4105
4106 uuid_t agent_uuid;
4107 uuid_copy(agent_uuid, value);
4108 u_int8_t netagent_message_type = 0;
4109 if (type == NECP_CLIENT_PARAMETER_TRIGGER_AGENT) {
4110 netagent_message_type = NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER;
4111 } else if (type == NECP_CLIENT_PARAMETER_ASSERT_AGENT) {
4112 netagent_message_type = NETAGENT_MESSAGE_TYPE_CLIENT_ASSERT;
4113 } else if (type == NECP_CLIENT_PARAMETER_UNASSERT_AGENT) {
4114 netagent_message_type = NETAGENT_MESSAGE_TYPE_CLIENT_UNASSERT;
4115 }
4116
4117 // Before unasserting, verify that the assertion was already taken
4118 if (type == NECP_CLIENT_PARAMETER_UNASSERT_AGENT) {
4119 if (!necp_client_remove_assertion(client, agent_uuid)) {
4120 error = ENOENT;
4121 break;
4122 }
4123 }
4124
4125 struct necp_client_nexus_parameters parsed_parameters = {};
4126 necp_client_copy_parameters_locked(client, &parsed_parameters);
4127
4128 error = netagent_client_message_with_params(agent_uuid,
4129 client_id,
4130 fd_data->proc_pid,
4131 netagent_message_type,
4132 &parsed_parameters,
4133 NULL, NULL);
4134 if (error == 0) {
4135 acted_on_agent = TRUE;
4136 } else {
4137 break;
4138 }
4139
4140 // Only save the assertion if the action succeeded
4141 if (type == NECP_CLIENT_PARAMETER_ASSERT_AGENT) {
4142 necp_client_add_assertion(client, agent_uuid);
4143 }
4144 }
4145 }
4146
4147 offset += sizeof(struct necp_tlv_header) + length;
4148 }
4149
4150 NECP_CLIENT_UNLOCK(client);
4151 }
4152 NECP_FD_UNLOCK(fd_data);
4153
4154 if (!acted_on_agent &&
4155 error == 0) {
4156 error = ENOENT;
4157 }
4158 done:
4159 *retval = error;
4160 if (parameters != NULL) {
4161 FREE(parameters, M_NECP);
4162 parameters = NULL;
4163 }
4164
4165 return (error);
4166 }
4167
4168 static int
4169 necp_client_copy_agent(__unused struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4170 {
4171 int error = 0;
4172 uuid_t agent_uuid;
4173
4174 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) ||
4175 uap->buffer_size == 0 || uap->buffer == 0) {
4176 NECPLOG0(LOG_ERR, "necp_client_copy_agent bad input");
4177 error = EINVAL;
4178 goto done;
4179 }
4180
4181 error = copyin(uap->client_id, agent_uuid, sizeof(uuid_t));
4182 if (error) {
4183 NECPLOG(LOG_ERR, "necp_client_copy_agent copyin agent_uuid error (%d)", error);
4184 goto done;
4185 }
4186
4187 error = netagent_copyout(agent_uuid, uap->buffer, uap->buffer_size);
4188 if (error) {
4189 // netagent_copyout already logs appropriate errors
4190 goto done;
4191 }
4192 done:
4193 *retval = error;
4194
4195 return (error);
4196 }
4197
4198 static int
4199 necp_client_agent_use(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4200 {
4201 int error = 0;
4202 struct necp_client *client = NULL;
4203 uuid_t client_id;
4204 struct necp_agent_use_parameters parameters;
4205
4206 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) ||
4207 uap->buffer_size != sizeof(parameters) || uap->buffer == 0) {
4208 error = EINVAL;
4209 goto done;
4210 }
4211
4212 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
4213 if (error) {
4214 NECPLOG(LOG_ERR, "Copyin client_id error (%d)", error);
4215 goto done;
4216 }
4217
4218 error = copyin(uap->buffer, &parameters, uap->buffer_size);
4219 if (error) {
4220 NECPLOG(LOG_ERR, "Parameters copyin error (%d)", error);
4221 goto done;
4222 }
4223
4224 NECP_FD_LOCK(fd_data);
4225 client = necp_client_fd_find_client_and_lock(fd_data, client_id);
4226 if (client != NULL) {
4227 error = netagent_use(parameters.agent_uuid, &parameters.out_use_count);
4228 NECP_CLIENT_UNLOCK(client);
4229 } else {
4230 error = ENOENT;
4231 }
4232
4233 NECP_FD_UNLOCK(fd_data);
4234
4235 if (error == 0) {
4236 error = copyout(&parameters, uap->buffer, uap->buffer_size);
4237 if (error) {
4238 NECPLOG(LOG_ERR, "Parameters copyout error (%d)", error);
4239 goto done;
4240 }
4241 }
4242
4243 done:
4244 *retval = error;
4245
4246 return (error);
4247 }
4248
4249 static int
4250 necp_client_copy_interface(__unused struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4251 {
4252 int error = 0;
4253 u_int32_t interface_index = 0;
4254 struct necp_interface_details interface_details;
4255
4256 if (uap->client_id == 0 || uap->client_id_len != sizeof(u_int32_t) ||
4257 uap->buffer_size < sizeof(interface_details) || uap->buffer == 0) {
4258 NECPLOG0(LOG_ERR, "necp_client_copy_interface bad input");
4259 error = EINVAL;
4260 goto done;
4261 }
4262
4263 error = copyin(uap->client_id, &interface_index, sizeof(u_int32_t));
4264 if (error) {
4265 NECPLOG(LOG_ERR, "necp_client_copy_interface copyin interface_index error (%d)", error);
4266 goto done;
4267 }
4268
4269 if (interface_index == 0) {
4270 error = ENOENT;
4271 NECPLOG(LOG_ERR, "necp_client_copy_interface bad interface_index (%d)", interface_index);
4272 goto done;
4273 }
4274
4275 memset(&interface_details, 0, sizeof(interface_details));
4276
4277 ifnet_head_lock_shared();
4278 ifnet_t interface = NULL;
4279 if (interface_index != IFSCOPE_NONE && interface_index <= (u_int32_t)if_index) {
4280 interface = ifindex2ifnet[interface_index];
4281 }
4282
4283 if (interface != NULL) {
4284 if (interface->if_xname != NULL) {
4285 strlcpy((char *)&interface_details.name, interface->if_xname, sizeof(interface_details.name));
4286 }
4287 interface_details.index = interface->if_index;
4288 interface_details.generation = ifnet_get_generation(interface);
4289 if (interface->if_delegated.ifp != NULL) {
4290 interface_details.delegate_index = interface->if_delegated.ifp->if_index;
4291 }
4292 interface_details.functional_type = if_functional_type(interface, TRUE);
4293 if (IFNET_IS_EXPENSIVE(interface)) {
4294 interface_details.flags |= NECP_INTERFACE_FLAG_EXPENSIVE;
4295 }
4296 if ((interface->if_eflags & IFEF_TXSTART) == IFEF_TXSTART) {
4297 interface_details.flags |= NECP_INTERFACE_FLAG_TXSTART;
4298 }
4299 if ((interface->if_eflags & IFEF_NOACKPRI) == IFEF_NOACKPRI) {
4300 interface_details.flags |= NECP_INTERFACE_FLAG_NOACKPRI;
4301 }
4302 interface_details.mtu = interface->if_mtu;
4303
4304 u_int8_t ipv4_signature_len = sizeof(interface_details.ipv4_signature.signature);
4305 u_int16_t ipv4_signature_flags;
4306 if (ifnet_get_netsignature(interface, AF_INET, &ipv4_signature_len, &ipv4_signature_flags,
4307 (u_int8_t *)&interface_details.ipv4_signature) != 0) {
4308 ipv4_signature_len = 0;
4309 }
4310 interface_details.ipv4_signature.signature_len = ipv4_signature_len;
4311
4312 u_int8_t ipv6_signature_len = sizeof(interface_details.ipv6_signature.signature);
4313 u_int16_t ipv6_signature_flags;
4314 if (ifnet_get_netsignature(interface, AF_INET6, &ipv6_signature_len, &ipv6_signature_flags,
4315 (u_int8_t *)&interface_details.ipv6_signature) != 0) {
4316 ipv6_signature_len = 0;
4317 }
4318 interface_details.ipv6_signature.signature_len = ipv6_signature_len;
4319 }
4320
4321 ifnet_head_done();
4322
4323 error = copyout(&interface_details, uap->buffer, sizeof(interface_details));
4324 if (error) {
4325 NECPLOG(LOG_ERR, "necp_client_copy_interface copyout error (%d)", error);
4326 goto done;
4327 }
4328 done:
4329 *retval = error;
4330
4331 return (error);
4332 }
4333
4334
4335 static int
4336 necp_client_copy_route_statistics(__unused struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4337 {
4338 int error = 0;
4339 struct necp_client *client = NULL;
4340 uuid_t client_id;
4341
4342 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) ||
4343 uap->buffer_size < sizeof(struct necp_stat_counts) || uap->buffer == 0) {
4344 NECPLOG0(LOG_ERR, "necp_client_copy_route_statistics bad input");
4345 error = EINVAL;
4346 goto done;
4347 }
4348
4349 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
4350 if (error) {
4351 NECPLOG(LOG_ERR, "necp_client_copy_route_statistics copyin client_id error (%d)", error);
4352 goto done;
4353 }
4354
4355 // Lock
4356 NECP_FD_LOCK(fd_data);
4357 client = necp_client_fd_find_client_and_lock(fd_data, client_id);
4358 if (client != NULL) {
4359 NECP_CLIENT_ROUTE_LOCK(client);
4360 struct necp_stat_counts route_stats = {};
4361 if (client->current_route != NULL && client->current_route->rt_stats != NULL) {
4362 struct nstat_counts *rt_stats = client->current_route->rt_stats;
4363 atomic_get_64(route_stats.necp_stat_rxpackets, &rt_stats->nstat_rxpackets);
4364 atomic_get_64(route_stats.necp_stat_rxbytes, &rt_stats->nstat_rxbytes);
4365 atomic_get_64(route_stats.necp_stat_txpackets, &rt_stats->nstat_txpackets);
4366 atomic_get_64(route_stats.necp_stat_txbytes, &rt_stats->nstat_txbytes);
4367 route_stats.necp_stat_rxduplicatebytes = rt_stats->nstat_rxduplicatebytes;
4368 route_stats.necp_stat_rxoutoforderbytes = rt_stats->nstat_rxoutoforderbytes;
4369 route_stats.necp_stat_txretransmit = rt_stats->nstat_txretransmit;
4370 route_stats.necp_stat_connectattempts = rt_stats->nstat_connectattempts;
4371 route_stats.necp_stat_connectsuccesses = rt_stats->nstat_connectsuccesses;
4372 route_stats.necp_stat_min_rtt = rt_stats->nstat_min_rtt;
4373 route_stats.necp_stat_avg_rtt = rt_stats->nstat_avg_rtt;
4374 route_stats.necp_stat_var_rtt = rt_stats->nstat_var_rtt;
4375 route_stats.necp_stat_route_flags = client->current_route->rt_flags;
4376 }
4377
4378 // Unlock before copying out
4379 NECP_CLIENT_ROUTE_UNLOCK(client);
4380 NECP_CLIENT_UNLOCK(client);
4381 NECP_FD_UNLOCK(fd_data);
4382
4383 error = copyout(&route_stats, uap->buffer, sizeof(route_stats));
4384 if (error) {
4385 NECPLOG(LOG_ERR, "necp_client_copy_route_statistics copyout error (%d)", error);
4386 }
4387 } else {
4388 // Unlock
4389 NECP_FD_UNLOCK(fd_data);
4390 error = ENOENT;
4391 }
4392
4393
4394 done:
4395 *retval = error;
4396 return (error);
4397 }
4398
4399 static int
4400 necp_client_update_cache(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval)
4401 {
4402 int error = 0;
4403 struct necp_client *client = NULL;
4404 uuid_t client_id;
4405
4406 if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t)) {
4407 error = EINVAL;
4408 goto done;
4409 }
4410
4411 error = copyin(uap->client_id, client_id, sizeof(uuid_t));
4412 if (error) {
4413 NECPLOG(LOG_ERR, "necp_client_update_cache copyin client_id error (%d)", error);
4414 goto done;
4415 }
4416
4417 NECP_FD_LOCK(fd_data);
4418 client = necp_client_fd_find_client_and_lock(fd_data, client_id);
4419 if (client == NULL) {
4420 NECP_FD_UNLOCK(fd_data);
4421 error = ENOENT;
4422 goto done;
4423 }
4424
4425 NECP_CLIENT_ROUTE_LOCK(client);
4426 // This needs to be changed when TFO/ECN is supported by multiple flows
4427 struct necp_client_flow *flow = LIST_FIRST(&client->flow_list);
4428 if (flow == NULL ||
4429 (flow->remote_addr.sa.sa_family != AF_INET &&
4430 flow->remote_addr.sa.sa_family != AF_INET6) ||
4431 (flow->local_addr.sa.sa_family != AF_INET &&
4432 flow->local_addr.sa.sa_family != AF_INET6)) {
4433 error = EINVAL;
4434 NECPLOG(LOG_ERR, "necp_client_update_cache no flow error (%d)", error);
4435 goto done_unlock;
4436 }
4437
4438 necp_cache_buffer cache_buffer;
4439 memset(&cache_buffer, 0, sizeof(cache_buffer));
4440
4441 if (uap->buffer_size != sizeof(necp_cache_buffer) ||
4442 uap->buffer == USER_ADDR_NULL) {
4443 error = EINVAL;
4444 goto done_unlock;
4445 }
4446
4447 error = copyin(uap->buffer, &cache_buffer, sizeof(cache_buffer));
4448 if (error) {
4449 NECPLOG(LOG_ERR, "necp_client_update_cache copyin cache buffer error (%d)", error);
4450 goto done_unlock;
4451 }
4452
4453 if (cache_buffer.necp_cache_buf_type == NECP_CLIENT_CACHE_TYPE_ECN &&
4454 cache_buffer.necp_cache_buf_ver == NECP_CLIENT_CACHE_TYPE_ECN_VER_1) {
4455 if (cache_buffer.necp_cache_buf_size != sizeof(necp_tcp_ecn_cache) ||
4456 cache_buffer.necp_cache_buf_addr == USER_ADDR_NULL) {
4457 error = EINVAL;
4458 goto done_unlock;
4459 }
4460
4461 necp_tcp_ecn_cache ecn_cache_buffer;
4462 memset(&ecn_cache_buffer, 0, sizeof(ecn_cache_buffer));
4463
4464 error = copyin(cache_buffer.necp_cache_buf_addr, &ecn_cache_buffer, sizeof(necp_tcp_ecn_cache));
4465 if (error) {
4466 NECPLOG(LOG_ERR, "necp_client_update_cache copyin ecn cache buffer error (%d)", error);
4467 goto done_unlock;
4468 }
4469
4470 if (client->current_route != NULL && client->current_route->rt_ifp != NULL) {
4471 if (!client->platform_binary) {
4472 ecn_cache_buffer.necp_tcp_ecn_heuristics_success = 0;
4473 }
4474 tcp_heuristics_ecn_update(&ecn_cache_buffer, client->current_route->rt_ifp,
4475 (union sockaddr_in_4_6 *)&flow->local_addr);
4476 }
4477 } else if (cache_buffer.necp_cache_buf_type == NECP_CLIENT_CACHE_TYPE_TFO &&
4478 cache_buffer.necp_cache_buf_ver == NECP_CLIENT_CACHE_TYPE_TFO_VER_1) {
4479 if (cache_buffer.necp_cache_buf_size != sizeof(necp_tcp_tfo_cache) ||
4480 cache_buffer.necp_cache_buf_addr == USER_ADDR_NULL) {
4481 error = EINVAL;
4482 goto done_unlock;
4483 }
4484
4485 necp_tcp_tfo_cache tfo_cache_buffer;
4486 memset(&tfo_cache_buffer, 0, sizeof(tfo_cache_buffer));
4487
4488 error = copyin(cache_buffer.necp_cache_buf_addr, &tfo_cache_buffer, sizeof(necp_tcp_tfo_cache));
4489 if (error) {
4490 NECPLOG(LOG_ERR, "necp_client_update_cache copyin tfo cache buffer error (%d)", error);
4491 goto done_unlock;
4492 }
4493
4494 if (client->current_route != NULL && client->current_route->rt_ifp != NULL) {
4495 if (!client->platform_binary) {
4496 tfo_cache_buffer.necp_tcp_tfo_heuristics_success = 0;
4497 }
4498 tcp_heuristics_tfo_update(&tfo_cache_buffer, client->current_route->rt_ifp,
4499 (union sockaddr_in_4_6 *)&flow->local_addr,
4500 (union sockaddr_in_4_6 *)&flow->remote_addr);
4501 }
4502 } else {
4503 error = EINVAL;
4504 }
4505 done_unlock:
4506 NECP_CLIENT_ROUTE_UNLOCK(client);
4507 NECP_CLIENT_UNLOCK(client);
4508 NECP_FD_UNLOCK(fd_data);
4509 done:
4510 *retval = error;
4511 return (error);
4512 }
4513
4514 int
4515 necp_client_action(struct proc *p, struct necp_client_action_args *uap, int *retval)
4516 {
4517 #pragma unused(p)
4518 int error = 0;
4519 int return_value = 0;
4520 struct necp_fd_data *fd_data = NULL;
4521 error = necp_find_fd_data(uap->necp_fd, &fd_data);
4522 if (error != 0) {
4523 NECPLOG(LOG_ERR, "necp_client_action find fd error (%d)", error);
4524 return (error);
4525 }
4526
4527 u_int32_t action = uap->action;
4528 switch (action) {
4529 case NECP_CLIENT_ACTION_ADD: {
4530 return_value = necp_client_add(p, fd_data, uap, retval);
4531 break;
4532 }
4533 case NECP_CLIENT_ACTION_REMOVE: {
4534 return_value = necp_client_remove(fd_data, uap, retval);
4535 break;
4536 }
4537 case NECP_CLIENT_ACTION_COPY_PARAMETERS:
4538 case NECP_CLIENT_ACTION_COPY_RESULT:
4539 case NECP_CLIENT_ACTION_COPY_UPDATED_RESULT: {
4540 return_value = necp_client_copy(fd_data, uap, retval);
4541 break;
4542 }
4543 case NECP_CLIENT_ACTION_COPY_LIST: {
4544 return_value = necp_client_list(fd_data, uap, retval);
4545 break;
4546 }
4547 case NECP_CLIENT_ACTION_AGENT: {
4548 return_value = necp_client_agent_action(fd_data, uap, retval);
4549 break;
4550 }
4551 case NECP_CLIENT_ACTION_COPY_AGENT: {
4552 return_value = necp_client_copy_agent(fd_data, uap, retval);
4553 break;
4554 }
4555 case NECP_CLIENT_ACTION_AGENT_USE: {
4556 return_value = necp_client_agent_use(fd_data, uap, retval);
4557 break;
4558 }
4559 case NECP_CLIENT_ACTION_COPY_INTERFACE: {
4560 return_value = necp_client_copy_interface(fd_data, uap, retval);
4561 break;
4562 }
4563 case NECP_CLIENT_ACTION_COPY_ROUTE_STATISTICS: {
4564 return_value = necp_client_copy_route_statistics(fd_data, uap, retval);
4565 break;
4566 }
4567 case NECP_CLIENT_ACTION_UPDATE_CACHE: {
4568 return_value = necp_client_update_cache(fd_data, uap, retval);
4569 break;
4570 }
4571 case NECP_CLIENT_ACTION_COPY_CLIENT_UPDATE: {
4572 return_value = necp_client_copy_client_update(fd_data, uap, retval);
4573 break;
4574 }
4575 default: {
4576 NECPLOG(LOG_ERR, "necp_client_action unknown action (%u)", action);
4577 return_value = EINVAL;
4578 break;
4579 }
4580 }
4581
4582 file_drop(uap->necp_fd);
4583
4584 return (return_value);
4585 }
4586
4587 #define NECP_MAX_MATCH_POLICY_PARAMETER_SIZE 1024
4588
4589 int
4590 necp_match_policy(struct proc *p, struct necp_match_policy_args *uap, int32_t *retval)
4591 {
4592 #pragma unused(retval)
4593 u_int8_t *parameters = NULL;
4594 struct necp_aggregate_result returned_result = {};
4595 int error = 0;
4596
4597 if (uap == NULL) {
4598 error = EINVAL;
4599 goto done;
4600 }
4601
4602 if (uap->parameters == 0 || uap->parameters_size == 0 || uap->parameters_size > NECP_MAX_MATCH_POLICY_PARAMETER_SIZE || uap->returned_result == 0) {
4603 error = EINVAL;
4604 goto done;
4605 }
4606
4607 MALLOC(parameters, u_int8_t *, uap->parameters_size, M_NECP, M_WAITOK | M_ZERO);
4608 if (parameters == NULL) {
4609 error = ENOMEM;
4610 goto done;
4611 }
4612 // Copy parameters in
4613 error = copyin(uap->parameters, parameters, uap->parameters_size);
4614 if (error) {
4615 goto done;
4616 }
4617
4618 error = necp_application_find_policy_match_internal(p, parameters, uap->parameters_size,
4619 &returned_result, NULL, 0, NULL, NULL, NULL, false);
4620 if (error) {
4621 goto done;
4622 }
4623
4624 // Copy return value back
4625 error = copyout(&returned_result, uap->returned_result, sizeof(struct necp_aggregate_result));
4626 if (error) {
4627 goto done;
4628 }
4629 done:
4630 if (parameters != NULL) {
4631 FREE(parameters, M_NECP);
4632 }
4633 return (error);
4634 }
4635
4636 /// Socket operations
4637 #define NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH 253
4638
4639 static bool
4640 necp_set_socket_attribute(u_int8_t *buffer, size_t buffer_length, u_int8_t type, char **buffer_p)
4641 {
4642 int error = 0;
4643 int cursor = 0;
4644 size_t string_size = 0;
4645 char *local_string = NULL;
4646 u_int8_t *value = NULL;
4647
4648 cursor = necp_buffer_find_tlv(buffer, buffer_length, 0, type, 0);
4649 if (cursor < 0) {
4650 // This will clear out the parameter
4651 goto done;
4652 }
4653
4654 string_size = necp_buffer_get_tlv_length(buffer, cursor);
4655 if (string_size == 0 || string_size > NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH) {
4656 // This will clear out the parameter
4657 goto done;
4658 }
4659
4660 MALLOC(local_string, char *, string_size + 1, M_NECP, M_WAITOK | M_ZERO);
4661 if (local_string == NULL) {
4662 NECPLOG(LOG_ERR, "Failed to allocate a socket attribute buffer (size %d)", string_size);
4663 goto fail;
4664 }
4665
4666 value = necp_buffer_get_tlv_value(buffer, cursor, NULL);
4667 if (value == NULL) {
4668 NECPLOG0(LOG_ERR, "Failed to get socket attribute");
4669 goto fail;
4670 }
4671
4672 memcpy(local_string, value, string_size);
4673 local_string[string_size] = 0;
4674
4675 done:
4676 if (*buffer_p != NULL) {
4677 FREE(*buffer_p, M_NECP);
4678 *buffer_p = NULL;
4679 }
4680
4681 *buffer_p = local_string;
4682 return (0);
4683 fail:
4684 if (local_string != NULL) {
4685 FREE(local_string, M_NECP);
4686 }
4687 return (error);
4688 }
4689
4690 errno_t
4691 necp_set_socket_attributes(struct socket *so, struct sockopt *sopt)
4692 {
4693 int error = 0;
4694 u_int8_t *buffer = NULL;
4695 struct inpcb *inp = NULL;
4696
4697 if ((SOCK_DOM(so) != PF_INET
4698 #if INET6
4699 && SOCK_DOM(so) != PF_INET6
4700 #endif
4701 )) {
4702 error = EINVAL;
4703 goto done;
4704 }
4705
4706 inp = sotoinpcb(so);
4707
4708 size_t valsize = sopt->sopt_valsize;
4709 if (valsize == 0 ||
4710 valsize > ((sizeof(struct necp_tlv_header) + NECP_MAX_SOCKET_ATTRIBUTE_STRING_LENGTH) * 2)) {
4711 goto done;
4712 }
4713
4714 MALLOC(buffer, u_int8_t *, valsize, M_NECP, M_WAITOK | M_ZERO);
4715 if (buffer == NULL) {
4716 goto done;
4717 }
4718
4719 error = sooptcopyin(sopt, buffer, valsize, 0);
4720 if (error) {
4721 goto done;
4722 }
4723
4724 error = necp_set_socket_attribute(buffer, valsize, NECP_TLV_ATTRIBUTE_DOMAIN, &inp->inp_necp_attributes.inp_domain);
4725 if (error) {
4726 NECPLOG0(LOG_ERR, "Could not set domain TLV for socket attributes");
4727 goto done;
4728 }
4729
4730 error = necp_set_socket_attribute(buffer, valsize, NECP_TLV_ATTRIBUTE_ACCOUNT, &inp->inp_necp_attributes.inp_account);
4731 if (error) {
4732 NECPLOG0(LOG_ERR, "Could not set account TLV for socket attributes");
4733 goto done;
4734 }
4735
4736 if (necp_debug) {
4737 NECPLOG(LOG_DEBUG, "Set on socket: Domain %s, Account %s", inp->inp_necp_attributes.inp_domain, inp->inp_necp_attributes.inp_account);
4738 }
4739 done:
4740 if (buffer != NULL) {
4741 FREE(buffer, M_NECP);
4742 }
4743
4744 return (error);
4745 }
4746
4747 errno_t
4748 necp_get_socket_attributes(struct socket *so, struct sockopt *sopt)
4749 {
4750 int error = 0;
4751 u_int8_t *buffer = NULL;
4752 u_int8_t *cursor = NULL;
4753 size_t valsize = 0;
4754 struct inpcb *inp = NULL;
4755
4756 if ((SOCK_DOM(so) != PF_INET
4757 #if INET6
4758 && SOCK_DOM(so) != PF_INET6
4759 #endif
4760 )) {
4761 error = EINVAL;
4762 goto done;
4763 }
4764
4765 inp = sotoinpcb(so);
4766 if (inp->inp_necp_attributes.inp_domain != NULL) {
4767 valsize += sizeof(struct necp_tlv_header) + strlen(inp->inp_necp_attributes.inp_domain);
4768 }
4769 if (inp->inp_necp_attributes.inp_account != NULL) {
4770 valsize += sizeof(struct necp_tlv_header) + strlen(inp->inp_necp_attributes.inp_account);
4771 }
4772 if (valsize == 0) {
4773 goto done;
4774 }
4775
4776 MALLOC(buffer, u_int8_t *, valsize, M_NECP, M_WAITOK | M_ZERO);
4777 if (buffer == NULL) {
4778 goto done;
4779 }
4780
4781 cursor = buffer;
4782 if (inp->inp_necp_attributes.inp_domain != NULL) {
4783 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_ATTRIBUTE_DOMAIN, strlen(inp->inp_necp_attributes.inp_domain), inp->inp_necp_attributes.inp_domain,
4784 buffer, valsize);
4785 }
4786
4787 if (inp->inp_necp_attributes.inp_account != NULL) {
4788 cursor = necp_buffer_write_tlv(cursor, NECP_TLV_ATTRIBUTE_ACCOUNT, strlen(inp->inp_necp_attributes.inp_account), inp->inp_necp_attributes.inp_account,
4789 buffer, valsize);
4790 }
4791
4792 error = sooptcopyout(sopt, buffer, valsize);
4793 if (error) {
4794 goto done;
4795 }
4796 done:
4797 if (buffer != NULL) {
4798 FREE(buffer, M_NECP);
4799 }
4800
4801 return (error);
4802 }
4803
4804 void *
4805 necp_create_nexus_assign_message(uuid_t nexus_instance, u_int32_t nexus_port, void *key, uint32_t key_length,
4806 struct necp_client_endpoint *local_endpoint, struct necp_client_endpoint *remote_endpoint,
4807 u_int32_t flow_adv_index, size_t *message_length)
4808 {
4809 u_int8_t *buffer = NULL;
4810 u_int8_t *cursor = NULL;
4811 size_t valsize = 0;
4812 bool has_nexus_assignment = FALSE;
4813
4814
4815 if (!uuid_is_null(nexus_instance)) {
4816 has_nexus_assignment = TRUE;
4817 valsize += sizeof(struct necp_tlv_header) + sizeof(uuid_t);
4818 valsize += sizeof(struct necp_tlv_header) + sizeof(u_int32_t);
4819 }
4820 if (flow_adv_index != NECP_FLOWADV_IDX_INVALID) {
4821 valsize += sizeof(struct necp_tlv_header) + sizeof(u_int32_t);
4822 }
4823 if (key != NULL && key_length > 0) {
4824 valsize += sizeof(struct necp_tlv_header) + key_length;
4825 }
4826 if (local_endpoint != NULL) {
4827 valsize += sizeof(struct necp_tlv_header) + sizeof(struct necp_client_endpoint);
4828 }
4829 if (remote_endpoint != NULL) {
4830 valsize += sizeof(struct necp_tlv_header) + sizeof(struct necp_client_endpoint);
4831 }
4832 if (valsize == 0) {
4833 return (NULL);
4834 }
4835
4836 MALLOC(buffer, u_int8_t *, valsize, M_NETAGENT, M_WAITOK | M_ZERO); // Use M_NETAGENT area, since it is expected upon free
4837 if (buffer == NULL) {
4838 return (NULL);
4839 }
4840
4841 cursor = buffer;
4842 if (has_nexus_assignment) {
4843 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_RESULT_NEXUS_INSTANCE, sizeof(uuid_t), nexus_instance, buffer, valsize);
4844 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_RESULT_NEXUS_PORT, sizeof(u_int32_t), &nexus_port, buffer, valsize);
4845 }
4846 if (flow_adv_index != NECP_FLOWADV_IDX_INVALID) {
4847 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_RESULT_NEXUS_PORT_FLOW_INDEX, sizeof(u_int32_t), &flow_adv_index, buffer, valsize);
4848 }
4849 if (key != NULL && key_length > 0) {
4850 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_PARAMETER_NEXUS_KEY, key_length, key, buffer, valsize);
4851 }
4852 if (local_endpoint != NULL) {
4853 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_RESULT_LOCAL_ENDPOINT, sizeof(struct necp_client_endpoint), local_endpoint, buffer, valsize);
4854 }
4855 if (remote_endpoint != NULL) {
4856 cursor = necp_buffer_write_tlv(cursor, NECP_CLIENT_RESULT_REMOTE_ENDPOINT, sizeof(struct necp_client_endpoint), remote_endpoint, buffer, valsize);
4857 }
4858
4859 *message_length = valsize;
4860
4861 return (buffer);
4862 }
4863
4864 void
4865 necp_inpcb_remove_cb(struct inpcb *inp)
4866 {
4867 if (!uuid_is_null(inp->necp_client_uuid)) {
4868 necp_client_unregister_socket_flow(inp->necp_client_uuid, inp);
4869 uuid_clear(inp->necp_client_uuid);
4870 }
4871 }
4872
4873 void
4874 necp_inpcb_dispose(struct inpcb *inp)
4875 {
4876 necp_inpcb_remove_cb(inp); // Clear out socket registrations if not yet done
4877 if (inp->inp_necp_attributes.inp_domain != NULL) {
4878 FREE(inp->inp_necp_attributes.inp_domain, M_NECP);
4879 inp->inp_necp_attributes.inp_domain = NULL;
4880 }
4881 if (inp->inp_necp_attributes.inp_account != NULL) {
4882 FREE(inp->inp_necp_attributes.inp_account, M_NECP);
4883 inp->inp_necp_attributes.inp_account = NULL;
4884 }
4885 }
4886
4887 void
4888 necp_mppcb_dispose(struct mppcb *mpp)
4889 {
4890 if (!uuid_is_null(mpp->necp_client_uuid)) {
4891 necp_client_unregister_multipath_cb(mpp->necp_client_uuid, mpp);
4892 uuid_clear(mpp->necp_client_uuid);
4893 }
4894 }
4895
4896 /// Module init
4897
4898 errno_t
4899 necp_client_init(void)
4900 {
4901 necp_fd_grp_attr = lck_grp_attr_alloc_init();
4902 if (necp_fd_grp_attr == NULL) {
4903 panic("lck_grp_attr_alloc_init failed\n");
4904 /* NOTREACHED */
4905 }
4906
4907 necp_fd_mtx_grp = lck_grp_alloc_init("necp_fd", necp_fd_grp_attr);
4908 if (necp_fd_mtx_grp == NULL) {
4909 panic("lck_grp_alloc_init failed\n");
4910 /* NOTREACHED */
4911 }
4912
4913 necp_fd_mtx_attr = lck_attr_alloc_init();
4914 if (necp_fd_mtx_attr == NULL) {
4915 panic("lck_attr_alloc_init failed\n");
4916 /* NOTREACHED */
4917 }
4918
4919 necp_client_fd_size = sizeof(struct necp_fd_data);
4920 necp_client_fd_zone = zinit(necp_client_fd_size,
4921 NECP_CLIENT_FD_ZONE_MAX * necp_client_fd_size,
4922 0, NECP_CLIENT_FD_ZONE_NAME);
4923 if (necp_client_fd_zone == NULL) {
4924 panic("zinit(necp_client_fd) failed\n");
4925 /* NOTREACHED */
4926 }
4927
4928 necp_flow_size = sizeof(struct necp_client_flow);
4929 necp_flow_cache = mcache_create(NECP_FLOW_ZONE_NAME, necp_flow_size, sizeof (uint64_t), 0, MCR_SLEEP);
4930 if (necp_flow_cache == NULL) {
4931 panic("mcache_create(necp_flow_cache) failed\n");
4932 /* NOTREACHED */
4933 }
4934
4935 necp_client_update_tcall = thread_call_allocate_with_options(necp_update_all_clients_callout, NULL,
4936 THREAD_CALL_PRIORITY_KERNEL, THREAD_CALL_OPTIONS_ONCE);
4937 VERIFY(necp_client_update_tcall != NULL);
4938
4939 lck_rw_init(&necp_fd_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
4940 lck_rw_init(&necp_observer_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
4941 lck_rw_init(&necp_client_tree_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
4942 lck_rw_init(&necp_collect_stats_list_lock, necp_fd_mtx_grp, necp_fd_mtx_attr);
4943
4944 LIST_INIT(&necp_fd_list);
4945 LIST_INIT(&necp_fd_observer_list);
4946 LIST_INIT(&necp_collect_stats_client_list);
4947
4948 RB_INIT(&necp_client_global_tree);
4949
4950 return (0);
4951 }
4952
4953 void
4954 necp_client_reap_caches(boolean_t purge)
4955 {
4956 mcache_reap_now(necp_flow_cache, purge);
4957 }
4958