2 * Copyright (c) 2017-2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <sys/types.h>
30 #include <sys/sysctl.h>
32 #include <sys/mcache.h>
33 #include <sys/malloc.h>
34 #include <sys/kauth.h>
35 #include <sys/bitstring.h>
37 #include <sys/protosw.h>
38 #include <sys/socket.h>
40 #include <kern/locks.h>
41 #include <kern/zalloc.h>
43 #include <libkern/libkern.h>
45 #include <net/kpi_interface.h>
46 #include <net/if_var.h>
47 #include <net/if_ports_used.h>
49 #include <netinet/in_pcb.h>
50 #include <netinet/tcp_var.h>
51 #include <netinet/tcp_fsm.h>
58 extern bool IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
);
60 SYSCTL_DECL(_net_link_generic_system
);
62 SYSCTL_NODE(_net_link_generic_system
, OID_AUTO
, port_used
,
63 CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "if port used");
65 static uuid_t current_wakeuuid
;
66 SYSCTL_OPAQUE(_net_link_generic_system_port_used
, OID_AUTO
, current_wakeuuid
,
67 CTLFLAG_RD
| CTLFLAG_LOCKED
,
68 current_wakeuuid
, sizeof(uuid_t
), "S,uuid_t", "");
70 static int sysctl_net_port_info_list SYSCTL_HANDLER_ARGS
;
71 SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
, list
,
72 CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_LOCKED
, 0, 0,
73 sysctl_net_port_info_list
, "S,xnpigen", "");
75 static int use_test_wakeuuid
= 0;
76 static uuid_t test_wakeuuid
;
77 static uuid_string_t test_wakeuuid_str
;
79 #if (DEVELOPMENT || DEBUG)
80 SYSCTL_INT(_net_link_generic_system_port_used
, OID_AUTO
, use_test_wakeuuid
,
81 CTLFLAG_RW
| CTLFLAG_LOCKED
,
82 &use_test_wakeuuid
, 0, "");
84 int sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS
;
85 SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
, new_test_wakeuuid
,
86 CTLTYPE_STRUCT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, 0,
87 sysctl_new_test_wakeuuid
, "S,uuid_t", "");
89 int sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
;
90 SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
, clear_test_wakeuuid
,
91 CTLTYPE_STRUCT
| CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, 0,
92 sysctl_clear_test_wakeuuid
, "S,uuid_t", "");
94 int sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
;
95 SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
, test_wakeuuid_str
,
96 CTLTYPE_STRING
| CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, 0,
97 sysctl_test_wakeuuid_str
, "A", "");
99 SYSCTL_OPAQUE(_net_link_generic_system_port_used
, OID_AUTO
, test_wakeuuid
,
100 CTLFLAG_RD
| CTLFLAG_LOCKED
,
101 test_wakeuuid
, sizeof(uuid_t
), "S,uuid_t", "");
102 #endif /* (DEVELOPMENT || DEBUG) */
104 static int sysctl_get_ports_used SYSCTL_HANDLER_ARGS
;
105 SYSCTL_NODE(_net_link_generic_system
, OID_AUTO
, get_ports_used
,
106 CTLFLAG_RD
| CTLFLAG_LOCKED
,
107 sysctl_get_ports_used
, "");
109 static uint32_t net_port_entry_count
= 0;
110 SYSCTL_UINT(_net_link_generic_system_port_used
, OID_AUTO
, entry_count
,
111 CTLFLAG_RW
| CTLFLAG_LOCKED
,
112 &net_port_entry_count
, 0, "");
114 static uint32_t net_port_entry_gen
= 0;
115 SYSCTL_UINT(_net_link_generic_system_port_used
, OID_AUTO
, entry_gen
,
116 CTLFLAG_RW
| CTLFLAG_LOCKED
,
117 &net_port_entry_gen
, 0, "");
119 static int if_ports_used_verbose
= 0;
120 SYSCTL_INT(_net_link_generic_system_port_used
, OID_AUTO
, verbose
,
121 CTLFLAG_RW
| CTLFLAG_LOCKED
,
122 &if_ports_used_verbose
, 0, "");
124 static unsigned long wakeuuid_not_set_count
= 0;
125 SYSCTL_ULONG(_net_link_generic_system_port_used
, OID_AUTO
,
126 wakeuuid_not_set_count
, CTLFLAG_RD
| CTLFLAG_LOCKED
,
127 &wakeuuid_not_set_count
, 0);
129 struct timeval wakeuuid_not_set_last_time
;
130 int sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS
;
131 static SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
,
132 wakeuuid_not_set_last_time
, CTLTYPE_STRUCT
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
133 0, 0, sysctl_wakeuuid_not_set_last_time
, "S,timeval", "");
135 char wakeuuid_not_set_last_if
[IFXNAMSIZ
];
136 int sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS
;
137 static SYSCTL_PROC(_net_link_generic_system_port_used
, OID_AUTO
,
138 wakeuuid_not_set_last_if
, CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_LOCKED
,
139 0, 0, sysctl_wakeuuid_not_set_last_if
, "A", "");
142 static int if_ports_used_inited
= 0;
144 decl_lck_mtx_data(static, net_port_entry_head_lock
);
145 static lck_grp_t
*net_port_entry_head_lock_group
;
147 struct net_port_entry
{
148 SLIST_ENTRY(net_port_entry
) npe_next
;
149 struct net_port_info npe_npi
;
152 static ZONE_DECLARE(net_port_entry_zone
, "net_port_entry",
153 sizeof(struct net_port_entry
), ZC_NONE
);
155 static SLIST_HEAD(net_port_entry_list
, net_port_entry
) net_port_entry_list
=
156 SLIST_HEAD_INITIALIZER(&net_port_entry_list
);
158 struct timeval wakeuiid_last_check
;
161 if_ports_used_init(void)
163 if (if_ports_used_inited
== 0) {
164 lck_grp_attr_t
*lck_grp_attributes
= NULL
;
165 lck_attr_t
*lck_attributes
= NULL
;
167 timerclear(&wakeuiid_last_check
);
168 uuid_clear(current_wakeuuid
);
169 uuid_clear(test_wakeuuid
);
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
);
175 lck_attributes
= lck_attr_alloc_init();
176 if (lck_attributes
== NULL
) {
177 panic("%s: lck_attr_alloc_init() failed", __func__
);
179 lck_mtx_init(&net_port_entry_head_lock
,
180 net_port_entry_head_lock_group
,
183 net_port_entry_count
= 0;
184 if_ports_used_inited
= 1;
186 lck_attr_free(lck_attributes
);
187 lck_grp_attr_free(lck_grp_attributes
);
192 net_port_entry_list_clear(void)
194 struct net_port_entry
*npe
;
196 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
198 while ((npe
= SLIST_FIRST(&net_port_entry_list
)) != NULL
) {
199 SLIST_REMOVE_HEAD(&net_port_entry_list
, npe_next
);
201 zfree(net_port_entry_zone
, npe
);
203 net_port_entry_count
= 0;
204 net_port_entry_gen
++;
208 get_test_wake_uuid(uuid_string_t wakeuuid_str
, size_t len
)
210 if (__improbable(use_test_wakeuuid
)) {
211 if (!uuid_is_null(test_wakeuuid
)) {
212 if (wakeuuid_str
!= NULL
&& len
!= 0) {
213 uuid_unparse(test_wakeuuid
, wakeuuid_str
);
216 } else if (strlen(test_wakeuuid_str
) != 0) {
217 if (wakeuuid_str
!= NULL
&& len
!= 0) {
218 strlcpy(wakeuuid_str
, test_wakeuuid_str
, len
);
230 is_wakeuuid_set(void)
233 * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
234 * That means we are currently in a sleep/wake cycle
236 return get_test_wake_uuid(NULL
, 0) || IOPMCopySleepWakeUUIDKey(NULL
, 0);
240 if_ports_used_update_wakeuuid(struct ifnet
*ifp
)
243 bool wakeuuid_is_set
= false;
244 bool updated
= false;
245 uuid_string_t wakeuuid_str
;
247 uuid_clear(wakeuuid
);
249 if (__improbable(use_test_wakeuuid
)) {
250 wakeuuid_is_set
= get_test_wake_uuid(wakeuuid_str
,
251 sizeof(wakeuuid_str
));
253 wakeuuid_is_set
= IOPMCopySleepWakeUUIDKey(wakeuuid_str
,
254 sizeof(wakeuuid_str
));
257 if (wakeuuid_is_set
) {
258 if (uuid_parse(wakeuuid_str
, wakeuuid
) != 0) {
259 os_log(OS_LOG_DEFAULT
,
260 "%s: IOPMCopySleepWakeUUIDKey got bad value %s\n",
261 __func__
, wakeuuid_str
);
262 wakeuuid_is_set
= false;
266 if (!wakeuuid_is_set
) {
267 if (if_ports_used_verbose
> 0) {
268 os_log_info(OS_LOG_DEFAULT
,
269 "%s: SleepWakeUUID not set, "
270 "don't update the port list for %s\n",
271 __func__
, ifp
!= NULL
? if_name(ifp
) : "");
273 wakeuuid_not_set_count
+= 1;
275 microtime(&wakeuuid_not_set_last_time
);
276 strlcpy(wakeuuid_not_set_last_if
, if_name(ifp
),
277 sizeof(wakeuuid_not_set_last_if
));
282 lck_mtx_lock(&net_port_entry_head_lock
);
283 if (uuid_compare(wakeuuid
, current_wakeuuid
) != 0) {
284 net_port_entry_list_clear();
285 uuid_copy(current_wakeuuid
, wakeuuid
);
289 * Record the time last checked
291 microuptime(&wakeuiid_last_check
);
292 lck_mtx_unlock(&net_port_entry_head_lock
);
294 if (updated
&& if_ports_used_verbose
> 0) {
295 uuid_string_t uuid_str
;
297 uuid_unparse(current_wakeuuid
, uuid_str
);
298 log(LOG_ERR
, "%s: current wakeuuid %s\n",
305 net_port_info_equal(const struct net_port_info
*x
,
306 const struct net_port_info
*y
)
308 ASSERT(x
!= NULL
&& y
!= NULL
);
310 if (x
->npi_if_index
== y
->npi_if_index
&&
311 x
->npi_local_port
== y
->npi_local_port
&&
312 x
->npi_foreign_port
== y
->npi_foreign_port
&&
313 x
->npi_owner_pid
== y
->npi_owner_pid
&&
314 x
->npi_effective_pid
== y
->npi_effective_pid
&&
315 x
->npi_flags
== y
->npi_flags
&&
316 memcmp(&x
->npi_local_addr_
, &y
->npi_local_addr_
,
317 sizeof(union in_addr_4_6
)) == 0 &&
318 memcmp(&x
->npi_foreign_addr_
, &y
->npi_foreign_addr_
,
319 sizeof(union in_addr_4_6
)) == 0) {
326 net_port_info_has_entry(const struct net_port_info
*npi
)
328 struct net_port_entry
*npe
;
330 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
332 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
333 if (net_port_info_equal(&npe
->npe_npi
, npi
)) {
342 net_port_info_add_entry(const struct net_port_info
*npi
)
344 struct net_port_entry
*npe
= NULL
;
346 bool entry_added
= false;
350 if (__improbable(is_wakeuuid_set() == false)) {
351 if (if_ports_used_verbose
> 0) {
352 log(LOG_ERR
, "%s: wakeuuid not set not adding "
353 "port: %u flags: 0x%xif: %u pid: %u epid %u\n",
355 ntohs(npi
->npi_local_port
),
359 npi
->npi_effective_pid
);
364 npe
= zalloc(net_port_entry_zone
);
365 if (__improbable(npe
== NULL
)) {
366 log(LOG_ERR
, "%s: zalloc() failed for "
367 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
369 ntohs(npi
->npi_local_port
),
373 npi
->npi_effective_pid
);
376 bzero(npe
, sizeof(struct net_port_entry
));
378 memcpy(&npe
->npe_npi
, npi
, sizeof(npe
->npe_npi
));
380 lck_mtx_lock(&net_port_entry_head_lock
);
382 if (net_port_info_has_entry(npi
) == false) {
383 SLIST_INSERT_HEAD(&net_port_entry_list
, npe
, npe_next
);
384 num
= net_port_entry_count
++;
387 if (if_ports_used_verbose
> 0) {
388 log(LOG_ERR
, "%s: num %u for "
389 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
392 ntohs(npi
->npi_local_port
),
396 npi
->npi_effective_pid
);
399 if (if_ports_used_verbose
> 0) {
400 log(LOG_ERR
, "%s: entry already added "
401 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
403 ntohs(npi
->npi_local_port
),
407 npi
->npi_effective_pid
);
411 lck_mtx_unlock(&net_port_entry_head_lock
);
413 if (entry_added
== false) {
414 zfree(net_port_entry_zone
, npe
);
420 #if (DEVELOPMENT || DEBUG)
422 sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS
424 #pragma unused(oidp, arg1, arg2)
427 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
430 if (req
->oldptr
== USER_ADDR_NULL
) {
431 req
->oldidx
= sizeof(uuid_t
);
434 if (req
->newptr
!= USER_ADDR_NULL
) {
435 uuid_generate(test_wakeuuid
);
437 error
= SYSCTL_OUT(req
, test_wakeuuid
,
438 MIN(sizeof(uuid_t
), req
->oldlen
));
444 sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
446 #pragma unused(oidp, arg1, arg2)
449 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
452 if (req
->oldptr
== USER_ADDR_NULL
) {
453 req
->oldidx
= sizeof(uuid_t
);
456 if (req
->newptr
!= USER_ADDR_NULL
) {
457 uuid_clear(test_wakeuuid
);
459 error
= SYSCTL_OUT(req
, test_wakeuuid
,
460 MIN(sizeof(uuid_t
), req
->oldlen
));
466 sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
468 #pragma unused(oidp, arg1, arg2)
472 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
475 error
= sysctl_io_string(req
, test_wakeuuid_str
, sizeof(test_wakeuuid_str
), 1, &changed
);
477 os_log_info(OS_LOG_DEFAULT
, "%s: test_wakeuuid_str %s",
478 __func__
, test_wakeuuid_str
);
484 #endif /* (DEVELOPMENT || DEBUG) */
487 sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS
489 #pragma unused(oidp, arg1, arg2)
491 if (proc_is64bit(req
->p
)) {
492 struct user64_timeval tv
= {};
494 tv
.tv_sec
= wakeuuid_not_set_last_time
.tv_sec
;
495 tv
.tv_usec
= wakeuuid_not_set_last_time
.tv_usec
;
496 return SYSCTL_OUT(req
, &tv
, sizeof(tv
));
498 struct user32_timeval tv
= {};
500 tv
.tv_sec
= (user32_time_t
)wakeuuid_not_set_last_time
.tv_sec
;
501 tv
.tv_usec
= wakeuuid_not_set_last_time
.tv_usec
;
502 return SYSCTL_OUT(req
, &tv
, sizeof(tv
));
507 sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS
509 #pragma unused(oidp, arg1, arg2)
511 return SYSCTL_OUT(req
, &wakeuuid_not_set_last_if
,
512 strlen(wakeuuid_not_set_last_if
) + 1);
516 sysctl_net_port_info_list SYSCTL_HANDLER_ARGS
518 #pragma unused(oidp, arg1, arg2)
520 struct xnpigen xnpigen
;
521 struct net_port_entry
*npe
;
523 if ((error
= priv_check_cred(kauth_cred_get(),
524 PRIV_NET_PRIVILEGED_NETWORK_STATISTICS
, 0)) != 0) {
527 lck_mtx_lock(&net_port_entry_head_lock
);
529 if (req
->oldptr
== USER_ADDR_NULL
) {
530 /* Add a 25 % cushion */
531 uint32_t cnt
= net_port_entry_count
;
533 req
->oldidx
= sizeof(struct xnpigen
) +
534 cnt
* sizeof(struct net_port_info
);
538 memset(&xnpigen
, 0, sizeof(struct xnpigen
));
539 xnpigen
.xng_len
= sizeof(struct xnpigen
);
540 xnpigen
.xng_gen
= net_port_entry_gen
;
541 uuid_copy(xnpigen
.xng_wakeuuid
, current_wakeuuid
);
542 xnpigen
.xng_npi_count
= net_port_entry_count
;
543 xnpigen
.xng_npi_size
= sizeof(struct net_port_info
);
544 error
= SYSCTL_OUT(req
, &xnpigen
, sizeof(xnpigen
));
546 printf("%s: SYSCTL_OUT(xnpigen) error %d\n",
551 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
552 error
= SYSCTL_OUT(req
, &npe
->npe_npi
,
553 sizeof(struct net_port_info
));
555 printf("%s: SYSCTL_OUT(npi) error %d\n",
561 lck_mtx_unlock(&net_port_entry_head_lock
);
567 * Mirror the arguments of ifnet_get_local_ports_extended()
573 sysctl_get_ports_used SYSCTL_HANDLER_ARGS
576 int *name
= (int *)arg1
;
580 protocol_family_t protocol
;
583 u_int8_t
*bitfield
= NULL
;
585 if (req
->newptr
!= USER_ADDR_NULL
) {
590 * 3 is the required number of parameters: ifindex, protocol and flags
597 if (req
->oldptr
== USER_ADDR_NULL
) {
598 req
->oldidx
= bitstr_size(IP_PORTRANGE_SIZE
);
601 if (req
->oldlen
< bitstr_size(IP_PORTRANGE_SIZE
)) {
610 ifnet_head_lock_shared();
611 if (!IF_INDEX_IN_RANGE(idx
)) {
616 ifp
= ifindex2ifnet
[idx
];
619 bitfield
= _MALLOC(bitstr_size(IP_PORTRANGE_SIZE
), M_TEMP
,
621 if (bitfield
== NULL
) {
625 error
= ifnet_get_local_ports_extended(ifp
, protocol
, flags
, bitfield
);
627 printf("%s: ifnet_get_local_ports_extended() error %d\n",
631 error
= SYSCTL_OUT(req
, bitfield
, bitstr_size(IP_PORTRANGE_SIZE
));
633 if (bitfield
!= NULL
) {
634 _FREE(bitfield
, M_TEMP
);
639 __private_extern__
void
640 if_ports_used_add_inpcb(const uint32_t ifindex
, const struct inpcb
*inp
)
642 struct net_port_info npi
;
643 struct socket
*so
= inp
->inp_socket
;
645 bzero(&npi
, sizeof(struct net_port_info
));
647 /* This is unlikely to happen but better be safe than sorry */
648 if (ifindex
> UINT16_MAX
) {
649 os_log(OS_LOG_DEFAULT
, "%s: ifindex %u too big\n", __func__
, ifindex
);
652 npi
.npi_if_index
= (uint16_t)ifindex
;
654 npi
.npi_flags
|= NPIF_SOCKET
;
656 npi
.npi_timestamp
.tv_sec
= (int32_t)wakeuiid_last_check
.tv_sec
;
657 npi
.npi_timestamp
.tv_usec
= wakeuiid_last_check
.tv_usec
;
659 if (SOCK_PROTO(so
) == IPPROTO_TCP
) {
660 struct tcpcb
*tp
= intotcpcb(inp
);
662 npi
.npi_flags
|= NPIF_TCP
;
663 if (tp
!= NULL
&& tp
->t_state
== TCPS_LISTEN
) {
664 npi
.npi_flags
|= NPIF_LISTEN
;
666 } else if (SOCK_PROTO(so
) == IPPROTO_UDP
) {
667 npi
.npi_flags
|= NPIF_UDP
;
669 panic("%s: unexpected protocol %u for inp %p\n", __func__
,
670 SOCK_PROTO(inp
->inp_socket
), inp
);
673 uuid_copy(npi
.npi_flow_uuid
, inp
->necp_client_uuid
);
675 npi
.npi_local_port
= inp
->inp_lport
;
676 npi
.npi_foreign_port
= inp
->inp_fport
;
679 * Take in account IPv4 addresses mapped on IPv6
681 if ((inp
->inp_vflag
& INP_IPV6
) != 0 && (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0 &&
682 (inp
->inp_vflag
& (INP_IPV6
| INP_IPV4
)) == (INP_IPV6
| INP_IPV4
)) {
683 npi
.npi_flags
|= NPIF_IPV6
| NPIF_IPV4
;
684 memcpy(&npi
.npi_local_addr_in6
,
685 &inp
->in6p_laddr
, sizeof(struct in6_addr
));
686 } else if (inp
->inp_vflag
& INP_IPV4
) {
687 npi
.npi_flags
|= NPIF_IPV4
;
688 npi
.npi_local_addr_in
= inp
->inp_laddr
;
689 npi
.npi_foreign_addr_in
= inp
->inp_faddr
;
691 npi
.npi_flags
|= NPIF_IPV6
;
692 memcpy(&npi
.npi_local_addr_in6
,
693 &inp
->in6p_laddr
, sizeof(struct in6_addr
));
694 memcpy(&npi
.npi_foreign_addr_in6
,
695 &inp
->in6p_faddr
, sizeof(struct in6_addr
));
697 /* Clear the embedded scope ID */
698 if (IN6_IS_ADDR_LINKLOCAL(&npi
.npi_local_addr_in6
)) {
699 npi
.npi_local_addr_in6
.s6_addr16
[1] = 0;
701 if (IN6_IS_ADDR_LINKLOCAL(&npi
.npi_foreign_addr_in6
)) {
702 npi
.npi_foreign_addr_in6
.s6_addr16
[1] = 0;
706 npi
.npi_owner_pid
= so
->last_pid
;
708 if (so
->last_pid
!= 0) {
709 proc_name(so
->last_pid
, npi
.npi_owner_pname
,
710 sizeof(npi
.npi_owner_pname
));
713 if (so
->so_flags
& SOF_DELEGATED
) {
714 npi
.npi_flags
|= NPIF_DELEGATED
;
715 npi
.npi_effective_pid
= so
->e_pid
;
716 if (so
->e_pid
!= 0) {
717 proc_name(so
->e_pid
, npi
.npi_effective_pname
,
718 sizeof(npi
.npi_effective_pname
));
721 npi
.npi_effective_pid
= so
->last_pid
;
722 if (so
->last_pid
!= 0) {
723 strlcpy(npi
.npi_effective_pname
, npi
.npi_owner_pname
,
724 sizeof(npi
.npi_effective_pname
));
728 (void) net_port_info_add_entry(&npi
);