]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_ports_used.c
378d834fccce819a8cddeddee724df7eb584a9f9
[apple/xnu.git] / bsd / net / if_ports_used.c
1 /*
2 * Copyright (c) 2017-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 <sys/types.h>
30 #include <sys/sysctl.h>
31 #include <sys/time.h>
32 #include <sys/mcache.h>
33 #include <sys/malloc.h>
34 #include <sys/kauth.h>
35 #include <sys/bitstring.h>
36 #include <sys/priv.h>
37 #include <sys/protosw.h>
38 #include <sys/socket.h>
39
40 #include <kern/locks.h>
41 #include <kern/zalloc.h>
42
43 #include <libkern/libkern.h>
44
45 #include <net/kpi_interface.h>
46 #include <net/if_var.h>
47 #include <net/if_ports_used.h>
48
49 #include <netinet/in_pcb.h>
50
51
52 #include <stdbool.h>
53
54 #include <os/log.h>
55
56 extern bool IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len);
57
58 SYSCTL_DECL(_net_link_generic_system);
59
60 SYSCTL_NODE(_net_link_generic_system, OID_AUTO, port_used,
61 CTLFLAG_RW | CTLFLAG_LOCKED, 0, "if port used");
62
63 static uuid_t current_wakeuuid;
64 SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, current_wakeuuid,
65 CTLFLAG_RD | CTLFLAG_LOCKED,
66 current_wakeuuid, sizeof(uuid_t), "S,uuid_t", "");
67
68 static int sysctl_net_port_info_list SYSCTL_HANDLER_ARGS;
69 SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, list,
70 CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0,
71 sysctl_net_port_info_list, "S,xnpigen", "");
72
73 static int use_test_wakeuuid = 0;
74 static uuid_t test_wakeuuid;
75 static uuid_string_t test_wakeuuid_str;
76
77 #if (DEVELOPMENT || DEBUG)
78 SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, use_test_wakeuuid,
79 CTLFLAG_RW | CTLFLAG_LOCKED,
80 &use_test_wakeuuid, 0, "");
81
82 int sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS;
83 SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, new_test_wakeuuid,
84 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
85 sysctl_new_test_wakeuuid, "S,uuid_t", "");
86
87 int sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS;
88 SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, clear_test_wakeuuid,
89 CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
90 sysctl_clear_test_wakeuuid, "S,uuid_t", "");
91
92 int sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS;
93 SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid_str,
94 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
95 sysctl_test_wakeuuid_str, "A", "");
96
97 SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid,
98 CTLFLAG_RD | CTLFLAG_LOCKED,
99 test_wakeuuid, sizeof(uuid_t), "S,uuid_t", "");
100 #endif /* (DEVELOPMENT || DEBUG) */
101
102 static int sysctl_get_ports_used SYSCTL_HANDLER_ARGS;
103 SYSCTL_NODE(_net_link_generic_system, OID_AUTO, get_ports_used,
104 CTLFLAG_RD | CTLFLAG_LOCKED,
105 sysctl_get_ports_used, "");
106
107 static uint32_t net_port_entry_count = 0;
108 SYSCTL_UINT(_net_link_generic_system_port_used, OID_AUTO, entry_count,
109 CTLFLAG_RW | CTLFLAG_LOCKED,
110 &net_port_entry_count, 0, "");
111
112 static uint32_t net_port_entry_gen = 0;
113 SYSCTL_UINT(_net_link_generic_system_port_used, OID_AUTO, entry_gen,
114 CTLFLAG_RW | CTLFLAG_LOCKED,
115 &net_port_entry_gen, 0, "");
116
117 static int if_ports_used_verbose = 0;
118 SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, verbose,
119 CTLFLAG_RW | CTLFLAG_LOCKED,
120 &if_ports_used_verbose, 0, "");
121
122 static unsigned long wakeuuid_not_set_count = 0;
123 SYSCTL_ULONG(_net_link_generic_system_port_used, OID_AUTO,
124 wakeuuid_not_set_count, CTLFLAG_RD | CTLFLAG_LOCKED,
125 &wakeuuid_not_set_count, 0);
126
127 struct timeval wakeuuid_not_set_last_time;
128 int sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS;
129 static SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO,
130 wakeuuid_not_set_last_time, CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED,
131 0, 0, sysctl_wakeuuid_not_set_last_time, "S,timeval", "");
132
133 char wakeuuid_not_set_last_if[IFXNAMSIZ];
134 int sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS;
135 static SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO,
136 wakeuuid_not_set_last_if, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED,
137 0, 0, sysctl_wakeuuid_not_set_last_if, "A", "");
138
139
140 static int if_ports_used_inited = 0;
141
142 decl_lck_mtx_data(static, net_port_entry_head_lock);
143 static lck_grp_t *net_port_entry_head_lock_group;
144
145 struct net_port_entry {
146 SLIST_ENTRY(net_port_entry) npe_next;
147 struct net_port_info npe_npi;
148 };
149
150 static struct zone *net_port_entry_zone = NULL;
151
152 #define NET_PORT_ENTRY_ZONE_MAX 128
153 #define NET_PORT_ENTRY_ZONE_NAME "net_port_entry"
154
155 static SLIST_HEAD(net_port_entry_list, net_port_entry) net_port_entry_list =
156 SLIST_HEAD_INITIALIZER(&net_port_entry_list);
157
158 struct timeval wakeuiid_last_check;
159
160 void
161 if_ports_used_init(void)
162 {
163 if (if_ports_used_inited == 0) {
164 lck_grp_attr_t *lck_grp_attributes = NULL;
165 lck_attr_t *lck_attributes = NULL;
166
167 timerclear(&wakeuiid_last_check);
168 uuid_clear(current_wakeuuid);
169 uuid_clear(test_wakeuuid);
170
171 lck_grp_attributes = lck_grp_attr_alloc_init();
172 net_port_entry_head_lock_group = lck_grp_alloc_init(
173 "net port entry lock", lck_grp_attributes);
174
175 lck_attributes = lck_attr_alloc_init();
176 if (lck_attributes == NULL) {
177 panic("%s: lck_attr_alloc_init() failed", __func__);
178 }
179 lck_mtx_init(&net_port_entry_head_lock,
180 net_port_entry_head_lock_group,
181 lck_attributes);
182
183 net_port_entry_count = 0;
184 net_port_entry_zone = zinit(sizeof(struct net_port_entry),
185 NET_PORT_ENTRY_ZONE_MAX * sizeof(struct net_port_entry),
186 0, NET_PORT_ENTRY_ZONE_NAME);
187 if (net_port_entry_zone == NULL) {
188 panic("%s: zinit(%s) failed", __func__,
189 NET_PORT_ENTRY_ZONE_NAME);
190 }
191 zone_change(net_port_entry_zone, Z_EXPAND, TRUE);
192 zone_change(net_port_entry_zone, Z_CALLERACCT, FALSE);
193
194 if_ports_used_inited = 1;
195
196 lck_attr_free(lck_attributes);
197 lck_grp_attr_free(lck_grp_attributes);
198 }
199 }
200
201 static void
202 net_port_entry_list_clear(void)
203 {
204 struct net_port_entry *npe;
205
206 LCK_MTX_ASSERT(&net_port_entry_head_lock, LCK_MTX_ASSERT_OWNED);
207
208 while ((npe = SLIST_FIRST(&net_port_entry_list)) != NULL) {
209 SLIST_REMOVE_HEAD(&net_port_entry_list, npe_next);
210
211 zfree(net_port_entry_zone, npe);
212 }
213 net_port_entry_count = 0;
214 net_port_entry_gen++;
215 }
216
217 static bool
218 get_test_wake_uuid(uuid_string_t wakeuuid_str, size_t len)
219 {
220 if (__improbable(use_test_wakeuuid)) {
221 if (!uuid_is_null(test_wakeuuid)) {
222 if (wakeuuid_str != NULL && len != 0) {
223 uuid_unparse(test_wakeuuid, wakeuuid_str);
224 }
225 return true;
226 } else if (strlen(test_wakeuuid_str) != 0) {
227 if (wakeuuid_str != NULL && len != 0) {
228 strlcpy(wakeuuid_str, test_wakeuuid_str, len);
229 }
230 return true;
231 } else {
232 return false;
233 }
234 } else {
235 return false;
236 }
237 }
238
239 static bool
240 is_wakeuuid_set(void)
241 {
242 /*
243 * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
244 * That means we are currently in a sleep/wake cycle
245 */
246 return get_test_wake_uuid(NULL, 0) || IOPMCopySleepWakeUUIDKey(NULL, 0);
247 }
248
249 void
250 if_ports_used_update_wakeuuid(struct ifnet *ifp)
251 {
252 uuid_t wakeuuid;
253 bool wakeuuid_is_set = false;
254 bool updated = false;
255 uuid_string_t wakeuuid_str;
256
257 uuid_clear(wakeuuid);
258
259 if (__improbable(use_test_wakeuuid)) {
260 wakeuuid_is_set = get_test_wake_uuid(wakeuuid_str,
261 sizeof(wakeuuid_str));
262 } else {
263 wakeuuid_is_set = IOPMCopySleepWakeUUIDKey(wakeuuid_str,
264 sizeof(wakeuuid_str));
265 }
266
267 if (wakeuuid_is_set) {
268 if (uuid_parse(wakeuuid_str, wakeuuid) != 0) {
269 os_log(OS_LOG_DEFAULT,
270 "%s: IOPMCopySleepWakeUUIDKey got bad value %s\n",
271 __func__, wakeuuid_str);
272 wakeuuid_is_set = false;
273 }
274 }
275
276 if (!wakeuuid_is_set) {
277 if (if_ports_used_verbose > 0) {
278 os_log_info(OS_LOG_DEFAULT,
279 "%s: SleepWakeUUID not set, "
280 "don't update the port list for %s\n",
281 __func__, ifp != NULL ? if_name(ifp) : "");
282 }
283 wakeuuid_not_set_count += 1;
284 if (ifp != NULL) {
285 microtime(&wakeuuid_not_set_last_time);
286 strlcpy(wakeuuid_not_set_last_if, if_name(ifp),
287 sizeof(wakeuuid_not_set_last_if));
288 }
289 return;
290 }
291
292 lck_mtx_lock(&net_port_entry_head_lock);
293 if (uuid_compare(wakeuuid, current_wakeuuid) != 0) {
294 net_port_entry_list_clear();
295 uuid_copy(current_wakeuuid, wakeuuid);
296 updated = true;
297 }
298 /*
299 * Record the time last checked
300 */
301 microuptime(&wakeuiid_last_check);
302 lck_mtx_unlock(&net_port_entry_head_lock);
303
304 if (updated && if_ports_used_verbose > 0) {
305 uuid_string_t uuid_str;
306
307 uuid_unparse(current_wakeuuid, uuid_str);
308 log(LOG_ERR, "%s: current wakeuuid %s\n",
309 __func__,
310 uuid_str);
311 }
312 }
313
314 static bool
315 net_port_info_equal(const struct net_port_info *x,
316 const struct net_port_info *y)
317 {
318 ASSERT(x != NULL && y != NULL);
319
320 if (x->npi_if_index == y->npi_if_index &&
321 x->npi_local_port == y->npi_local_port &&
322 x->npi_foreign_port == y->npi_foreign_port &&
323 x->npi_owner_pid == y->npi_owner_pid &&
324 x->npi_effective_pid == y->npi_effective_pid &&
325 x->npi_flags == y->npi_flags &&
326 memcmp(&x->npi_local_addr_, &y->npi_local_addr_,
327 sizeof(union in_addr_4_6)) == 0 &&
328 memcmp(&x->npi_foreign_addr_, &y->npi_foreign_addr_,
329 sizeof(union in_addr_4_6)) == 0) {
330 return true;
331 }
332 return false;
333 }
334
335 static bool
336 net_port_info_has_entry(const struct net_port_info *npi)
337 {
338 struct net_port_entry *npe;
339
340 LCK_MTX_ASSERT(&net_port_entry_head_lock, LCK_MTX_ASSERT_OWNED);
341
342 SLIST_FOREACH(npe, &net_port_entry_list, npe_next) {
343 if (net_port_info_equal(&npe->npe_npi, npi)) {
344 return true;
345 }
346 }
347
348 return false;
349 }
350
351 static bool
352 net_port_info_add_entry(const struct net_port_info *npi)
353 {
354 struct net_port_entry *npe = NULL;
355 uint32_t num = 0;
356 bool entry_added = false;
357
358 ASSERT(npi != NULL);
359
360 if (__improbable(is_wakeuuid_set() == false)) {
361 if (if_ports_used_verbose > 0) {
362 log(LOG_ERR, "%s: wakeuuid not set %u not adding "
363 "port: %u flags: 0x%xif: %u pid: %u epid %u\n",
364 __func__,
365 ntohs(npi->npi_local_port),
366 npi->npi_flags,
367 npi->npi_if_index,
368 npi->npi_owner_pid,
369 npi->npi_effective_pid);
370 }
371 return 0;
372 }
373
374 npe = zalloc(net_port_entry_zone);
375 if (__improbable(npe == NULL)) {
376 log(LOG_ERR, "%s: zalloc() failed for "
377 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
378 __func__,
379 ntohs(npi->npi_local_port),
380 npi->npi_flags,
381 npi->npi_if_index,
382 npi->npi_owner_pid,
383 npi->npi_effective_pid);
384 return 0;
385 }
386 bzero(npe, sizeof(struct net_port_entry));
387
388 memcpy(&npe->npe_npi, npi, sizeof(npe->npe_npi));
389
390 lck_mtx_lock(&net_port_entry_head_lock);
391
392 if (net_port_info_has_entry(npi) == false) {
393 SLIST_INSERT_HEAD(&net_port_entry_list, npe, npe_next);
394 num = net_port_entry_count++;
395 entry_added = true;
396
397 if (if_ports_used_verbose > 0) {
398 log(LOG_ERR, "%s: num %u for "
399 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
400 __func__,
401 num,
402 ntohs(npi->npi_local_port),
403 npi->npi_flags,
404 npi->npi_if_index,
405 npi->npi_owner_pid,
406 npi->npi_effective_pid);
407 }
408 } else {
409 if (if_ports_used_verbose > 0) {
410 log(LOG_ERR, "%s: entry already added "
411 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
412 __func__,
413 ntohs(npi->npi_local_port),
414 npi->npi_flags,
415 npi->npi_if_index,
416 npi->npi_owner_pid,
417 npi->npi_effective_pid);
418 }
419 }
420
421 lck_mtx_unlock(&net_port_entry_head_lock);
422
423 if (entry_added == false) {
424 zfree(net_port_entry_zone, npe);
425 npe = NULL;
426 }
427 return entry_added;
428 }
429
430 #if (DEVELOPMENT || DEBUG)
431 int
432 sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS
433 {
434 #pragma unused(oidp, arg1, arg2)
435 int error = 0;
436
437 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
438 return EPERM;
439 }
440 if (req->oldptr == USER_ADDR_NULL) {
441 req->oldidx = sizeof(uuid_t);
442 return 0;
443 }
444 if (req->newptr != USER_ADDR_NULL) {
445 uuid_generate(test_wakeuuid);
446 }
447 error = SYSCTL_OUT(req, test_wakeuuid,
448 MIN(sizeof(uuid_t), req->oldlen));
449
450 return error;
451 }
452
453 int
454 sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
455 {
456 #pragma unused(oidp, arg1, arg2)
457 int error = 0;
458
459 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
460 return EPERM;
461 }
462 if (req->oldptr == USER_ADDR_NULL) {
463 req->oldidx = sizeof(uuid_t);
464 return 0;
465 }
466 if (req->newptr != USER_ADDR_NULL) {
467 uuid_clear(test_wakeuuid);
468 }
469 error = SYSCTL_OUT(req, test_wakeuuid,
470 MIN(sizeof(uuid_t), req->oldlen));
471
472 return error;
473 }
474
475 int
476 sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
477 {
478 #pragma unused(oidp, arg1, arg2)
479 int error = 0;
480 int changed;
481
482 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
483 return EPERM;
484 }
485 error = sysctl_io_string(req, test_wakeuuid_str, sizeof(test_wakeuuid_str), 1, &changed);
486 if (changed) {
487 os_log_info(OS_LOG_DEFAULT, "%s: test_wakeuuid_str %s",
488 __func__, test_wakeuuid_str);
489 }
490
491 return error;
492 }
493
494 #endif /* (DEVELOPMENT || DEBUG) */
495
496 int
497 sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS
498 {
499 #pragma unused(oidp, arg1, arg2)
500
501 if (proc_is64bit(req->p)) {
502 struct user64_timeval tv = {};
503
504 tv.tv_sec = wakeuuid_not_set_last_time.tv_sec;
505 tv.tv_usec = wakeuuid_not_set_last_time.tv_usec;
506 return SYSCTL_OUT(req, &tv, sizeof(tv));
507 } else {
508 struct user32_timeval tv = {};
509
510 tv.tv_sec = wakeuuid_not_set_last_time.tv_sec;
511 tv.tv_usec = wakeuuid_not_set_last_time.tv_usec;
512 return SYSCTL_OUT(req, &tv, sizeof(tv));
513 }
514 }
515
516 int
517 sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS
518 {
519 #pragma unused(oidp, arg1, arg2)
520
521 return SYSCTL_OUT(req, &wakeuuid_not_set_last_if,
522 strlen(wakeuuid_not_set_last_if) + 1);
523 }
524
525 static int
526 sysctl_net_port_info_list SYSCTL_HANDLER_ARGS
527 {
528 #pragma unused(oidp, arg1, arg2)
529 int error = 0;
530 struct xnpigen xnpigen;
531 struct net_port_entry *npe;
532
533 if ((error = priv_check_cred(kauth_cred_get(),
534 PRIV_NET_PRIVILEGED_NETWORK_STATISTICS, 0)) != 0) {
535 return EPERM;
536 }
537 lck_mtx_lock(&net_port_entry_head_lock);
538
539 if (req->oldptr == USER_ADDR_NULL) {
540 /* Add a 25 % cushion */
541 uint32_t cnt = net_port_entry_count;
542 cnt += cnt >> 4;
543 req->oldidx = sizeof(struct xnpigen) +
544 cnt * sizeof(struct net_port_info);
545 goto done;
546 }
547
548 memset(&xnpigen, 0, sizeof(struct xnpigen));
549 xnpigen.xng_len = sizeof(struct xnpigen);
550 xnpigen.xng_gen = net_port_entry_gen;
551 uuid_copy(xnpigen.xng_wakeuuid, current_wakeuuid);
552 xnpigen.xng_npi_count = net_port_entry_count;
553 xnpigen.xng_npi_size = sizeof(struct net_port_info);
554 error = SYSCTL_OUT(req, &xnpigen, sizeof(xnpigen));
555 if (error != 0) {
556 printf("%s: SYSCTL_OUT(xnpigen) error %d\n",
557 __func__, error);
558 goto done;
559 }
560
561 SLIST_FOREACH(npe, &net_port_entry_list, npe_next) {
562 error = SYSCTL_OUT(req, &npe->npe_npi,
563 sizeof(struct net_port_info));
564 if (error != 0) {
565 printf("%s: SYSCTL_OUT(npi) error %d\n",
566 __func__, error);
567 goto done;
568 }
569 }
570 done:
571 lck_mtx_unlock(&net_port_entry_head_lock);
572
573 return error;
574 }
575
576 /*
577 * Mirror the arguments of ifnet_get_local_ports_extended()
578 * ifindex
579 * protocol
580 * flags
581 */
582 static int
583 sysctl_get_ports_used SYSCTL_HANDLER_ARGS
584 {
585 #pragma unused(oidp)
586 int *name = (int *)arg1;
587 int namelen = arg2;
588 int error = 0;
589 int idx;
590 protocol_family_t protocol;
591 u_int32_t flags;
592 ifnet_t ifp = NULL;
593 u_int8_t *bitfield = NULL;
594
595 if (req->newptr != USER_ADDR_NULL) {
596 error = EPERM;
597 goto done;
598 }
599 /*
600 * 3 is the required number of parameters: ifindex, protocol and flags
601 */
602 if (namelen != 3) {
603 error = ENOENT;
604 goto done;
605 }
606
607 if (req->oldptr == USER_ADDR_NULL) {
608 req->oldidx = bitstr_size(IP_PORTRANGE_SIZE);
609 goto done;
610 }
611 if (req->oldlen < bitstr_size(IP_PORTRANGE_SIZE)) {
612 error = ENOMEM;
613 goto done;
614 }
615
616 idx = name[0];
617 protocol = name[1];
618 flags = name[2];
619
620 ifnet_head_lock_shared();
621 if (!IF_INDEX_IN_RANGE(idx)) {
622 ifnet_head_done();
623 error = ENOENT;
624 goto done;
625 }
626 ifp = ifindex2ifnet[idx];
627 ifnet_head_done();
628
629 bitfield = _MALLOC(bitstr_size(IP_PORTRANGE_SIZE), M_TEMP,
630 M_WAITOK | M_ZERO);
631 if (bitfield == NULL) {
632 error = ENOMEM;
633 goto done;
634 }
635 error = ifnet_get_local_ports_extended(ifp, protocol, flags, bitfield);
636 if (error != 0) {
637 printf("%s: ifnet_get_local_ports_extended() error %d\n",
638 __func__, error);
639 goto done;
640 }
641 error = SYSCTL_OUT(req, bitfield, bitstr_size(IP_PORTRANGE_SIZE));
642 done:
643 if (bitfield != NULL) {
644 _FREE(bitfield, M_TEMP);
645 }
646 return error;
647 }
648
649 __private_extern__ void
650 if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp)
651 {
652 struct net_port_info npi;
653 struct socket *so = inp->inp_socket;
654
655 bzero(&npi, sizeof(struct net_port_info));
656
657 npi.npi_if_index = ifindex;
658
659 npi.npi_flags |= NPIF_SOCKET;
660
661 npi.npi_timestamp.tv_sec = wakeuiid_last_check.tv_sec;
662 npi.npi_timestamp.tv_usec = wakeuiid_last_check.tv_usec;
663
664 if (SOCK_PROTO(so) == IPPROTO_TCP) {
665 npi.npi_flags |= NPIF_TCP;
666 } else if (SOCK_PROTO(so) == IPPROTO_UDP) {
667 npi.npi_flags |= NPIF_UDP;
668 } else {
669 panic("%s: unexpected protocol %u for inp %p\n", __func__,
670 SOCK_PROTO(inp->inp_socket), inp);
671 }
672
673 uuid_copy(npi.npi_flow_uuid, inp->necp_client_uuid);
674
675 npi.npi_local_port = inp->inp_lport;
676 npi.npi_foreign_port = inp->inp_fport;
677
678 if (inp->inp_vflag & INP_IPV4) {
679 npi.npi_flags |= NPIF_IPV4;
680 npi.npi_local_addr_in = inp->inp_laddr;
681 npi.npi_foreign_addr_in = inp->inp_faddr;
682 } else {
683 npi.npi_flags |= NPIF_IPV6;
684 memcpy(&npi.npi_local_addr_in6,
685 &inp->in6p_laddr, sizeof(struct in6_addr));
686 memcpy(&npi.npi_foreign_addr_in6,
687 &inp->in6p_faddr, sizeof(struct in6_addr));
688 }
689
690 npi.npi_owner_pid = so->last_pid;
691
692 if (so->last_pid != 0) {
693 proc_name(so->last_pid, npi.npi_owner_pname,
694 sizeof(npi.npi_owner_pname));
695 }
696
697 if (so->so_flags & SOF_DELEGATED) {
698 npi.npi_flags |= NPIF_DELEGATED;
699 npi.npi_effective_pid = so->e_pid;
700 if (so->e_pid != 0) {
701 proc_name(so->e_pid, npi.npi_effective_pname,
702 sizeof(npi.npi_effective_pname));
703 }
704 } else {
705 npi.npi_effective_pid = so->last_pid;
706 if (so->last_pid != 0) {
707 strlcpy(npi.npi_effective_pname, npi.npi_owner_pname,
708 sizeof(npi.npi_effective_pname));
709 }
710 }
711
712 (void) net_port_info_add_entry(&npi);
713 }
714