2 * Copyright (c) 2017-2018 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>
56 extern bool IOPMCopySleepWakeUUIDKey(char *buffer
, size_t buf_len
);
58 SYSCTL_DECL(_net_link_generic_system
);
60 SYSCTL_NODE(_net_link_generic_system
, OID_AUTO
, port_used
,
61 CTLFLAG_RW
| CTLFLAG_LOCKED
, 0, "if port used");
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", "");
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", "");
73 static int use_test_wakeuuid
= 0;
74 static uuid_t test_wakeuuid
;
75 static uuid_string_t test_wakeuuid_str
;
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, "");
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", "");
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", "");
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", "");
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) */
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
, "");
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, "");
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, "");
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, "");
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);
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", "");
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", "");
140 static int if_ports_used_inited
= 0;
142 decl_lck_mtx_data(static, net_port_entry_head_lock
);
143 static lck_grp_t
*net_port_entry_head_lock_group
;
145 struct net_port_entry
{
146 SLIST_ENTRY(net_port_entry
) npe_next
;
147 struct net_port_info npe_npi
;
150 static struct zone
*net_port_entry_zone
= NULL
;
152 #define NET_PORT_ENTRY_ZONE_MAX 128
153 #define NET_PORT_ENTRY_ZONE_NAME "net_port_entry"
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 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
);
191 zone_change(net_port_entry_zone
, Z_EXPAND
, TRUE
);
192 zone_change(net_port_entry_zone
, Z_CALLERACCT
, FALSE
);
194 if_ports_used_inited
= 1;
196 lck_attr_free(lck_attributes
);
197 lck_grp_attr_free(lck_grp_attributes
);
202 net_port_entry_list_clear(void)
204 struct net_port_entry
*npe
;
206 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
208 while ((npe
= SLIST_FIRST(&net_port_entry_list
)) != NULL
) {
209 SLIST_REMOVE_HEAD(&net_port_entry_list
, npe_next
);
211 zfree(net_port_entry_zone
, npe
);
213 net_port_entry_count
= 0;
214 net_port_entry_gen
++;
218 get_test_wake_uuid(uuid_string_t wakeuuid_str
, size_t len
)
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
);
226 } else if (strlen(test_wakeuuid_str
) != 0) {
227 if (wakeuuid_str
!= NULL
&& len
!= 0) {
228 strlcpy(wakeuuid_str
, test_wakeuuid_str
, len
);
240 is_wakeuuid_set(void)
243 * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
244 * That means we are currently in a sleep/wake cycle
246 return get_test_wake_uuid(NULL
, 0) || IOPMCopySleepWakeUUIDKey(NULL
, 0);
250 if_ports_used_update_wakeuuid(struct ifnet
*ifp
)
253 bool wakeuuid_is_set
= false;
254 bool updated
= false;
255 uuid_string_t wakeuuid_str
;
257 uuid_clear(wakeuuid
);
259 if (__improbable(use_test_wakeuuid
)) {
260 wakeuuid_is_set
= get_test_wake_uuid(wakeuuid_str
,
261 sizeof(wakeuuid_str
));
263 wakeuuid_is_set
= IOPMCopySleepWakeUUIDKey(wakeuuid_str
,
264 sizeof(wakeuuid_str
));
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;
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
) : "");
283 wakeuuid_not_set_count
+= 1;
285 microtime(&wakeuuid_not_set_last_time
);
286 strlcpy(wakeuuid_not_set_last_if
, if_name(ifp
),
287 sizeof(wakeuuid_not_set_last_if
));
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
);
299 * Record the time last checked
301 microuptime(&wakeuiid_last_check
);
302 lck_mtx_unlock(&net_port_entry_head_lock
);
304 if (updated
&& if_ports_used_verbose
> 0) {
305 uuid_string_t uuid_str
;
307 uuid_unparse(current_wakeuuid
, uuid_str
);
308 log(LOG_ERR
, "%s: current wakeuuid %s\n",
315 net_port_info_equal(const struct net_port_info
*x
,
316 const struct net_port_info
*y
)
318 ASSERT(x
!= NULL
&& y
!= NULL
);
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) {
336 net_port_info_has_entry(const struct net_port_info
*npi
)
338 struct net_port_entry
*npe
;
340 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
342 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
343 if (net_port_info_equal(&npe
->npe_npi
, npi
)) {
352 net_port_info_add_entry(const struct net_port_info
*npi
)
354 struct net_port_entry
*npe
= NULL
;
356 bool entry_added
= false;
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",
365 ntohs(npi
->npi_local_port
),
369 npi
->npi_effective_pid
);
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",
379 ntohs(npi
->npi_local_port
),
383 npi
->npi_effective_pid
);
386 bzero(npe
, sizeof(struct net_port_entry
));
388 memcpy(&npe
->npe_npi
, npi
, sizeof(npe
->npe_npi
));
390 lck_mtx_lock(&net_port_entry_head_lock
);
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
++;
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",
402 ntohs(npi
->npi_local_port
),
406 npi
->npi_effective_pid
);
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",
413 ntohs(npi
->npi_local_port
),
417 npi
->npi_effective_pid
);
421 lck_mtx_unlock(&net_port_entry_head_lock
);
423 if (entry_added
== false) {
424 zfree(net_port_entry_zone
, npe
);
430 #if (DEVELOPMENT || DEBUG)
432 sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS
434 #pragma unused(oidp, arg1, arg2)
437 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
440 if (req
->oldptr
== USER_ADDR_NULL
) {
441 req
->oldidx
= sizeof(uuid_t
);
444 if (req
->newptr
!= USER_ADDR_NULL
) {
445 uuid_generate(test_wakeuuid
);
447 error
= SYSCTL_OUT(req
, test_wakeuuid
,
448 MIN(sizeof(uuid_t
), req
->oldlen
));
454 sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
456 #pragma unused(oidp, arg1, arg2)
459 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
462 if (req
->oldptr
== USER_ADDR_NULL
) {
463 req
->oldidx
= sizeof(uuid_t
);
466 if (req
->newptr
!= USER_ADDR_NULL
) {
467 uuid_clear(test_wakeuuid
);
469 error
= SYSCTL_OUT(req
, test_wakeuuid
,
470 MIN(sizeof(uuid_t
), req
->oldlen
));
476 sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
478 #pragma unused(oidp, arg1, arg2)
482 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
485 error
= sysctl_io_string(req
, test_wakeuuid_str
, sizeof(test_wakeuuid_str
), 1, &changed
);
487 os_log_info(OS_LOG_DEFAULT
, "%s: test_wakeuuid_str %s",
488 __func__
, test_wakeuuid_str
);
494 #endif /* (DEVELOPMENT || DEBUG) */
497 sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS
499 #pragma unused(oidp, arg1, arg2)
501 if (proc_is64bit(req
->p
)) {
502 struct user64_timeval tv
= {};
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
));
508 struct user32_timeval tv
= {};
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
));
517 sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS
519 #pragma unused(oidp, arg1, arg2)
521 return SYSCTL_OUT(req
, &wakeuuid_not_set_last_if
,
522 strlen(wakeuuid_not_set_last_if
) + 1);
526 sysctl_net_port_info_list SYSCTL_HANDLER_ARGS
528 #pragma unused(oidp, arg1, arg2)
530 struct xnpigen xnpigen
;
531 struct net_port_entry
*npe
;
533 if ((error
= priv_check_cred(kauth_cred_get(),
534 PRIV_NET_PRIVILEGED_NETWORK_STATISTICS
, 0)) != 0) {
537 lck_mtx_lock(&net_port_entry_head_lock
);
539 if (req
->oldptr
== USER_ADDR_NULL
) {
540 /* Add a 25 % cushion */
541 uint32_t cnt
= net_port_entry_count
;
543 req
->oldidx
= sizeof(struct xnpigen
) +
544 cnt
* sizeof(struct net_port_info
);
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
));
556 printf("%s: SYSCTL_OUT(xnpigen) error %d\n",
561 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
562 error
= SYSCTL_OUT(req
, &npe
->npe_npi
,
563 sizeof(struct net_port_info
));
565 printf("%s: SYSCTL_OUT(npi) error %d\n",
571 lck_mtx_unlock(&net_port_entry_head_lock
);
577 * Mirror the arguments of ifnet_get_local_ports_extended()
583 sysctl_get_ports_used SYSCTL_HANDLER_ARGS
586 int *name
= (int *)arg1
;
590 protocol_family_t protocol
;
593 u_int8_t
*bitfield
= NULL
;
595 if (req
->newptr
!= USER_ADDR_NULL
) {
600 * 3 is the required number of parameters: ifindex, protocol and flags
607 if (req
->oldptr
== USER_ADDR_NULL
) {
608 req
->oldidx
= bitstr_size(IP_PORTRANGE_SIZE
);
611 if (req
->oldlen
< bitstr_size(IP_PORTRANGE_SIZE
)) {
620 ifnet_head_lock_shared();
621 if (!IF_INDEX_IN_RANGE(idx
)) {
626 ifp
= ifindex2ifnet
[idx
];
629 bitfield
= _MALLOC(bitstr_size(IP_PORTRANGE_SIZE
), M_TEMP
,
631 if (bitfield
== NULL
) {
635 error
= ifnet_get_local_ports_extended(ifp
, protocol
, flags
, bitfield
);
637 printf("%s: ifnet_get_local_ports_extended() error %d\n",
641 error
= SYSCTL_OUT(req
, bitfield
, bitstr_size(IP_PORTRANGE_SIZE
));
643 if (bitfield
!= NULL
) {
644 _FREE(bitfield
, M_TEMP
);
649 __private_extern__
void
650 if_ports_used_add_inpcb(const uint32_t ifindex
, const struct inpcb
*inp
)
652 struct net_port_info npi
;
653 struct socket
*so
= inp
->inp_socket
;
655 bzero(&npi
, sizeof(struct net_port_info
));
657 npi
.npi_if_index
= ifindex
;
659 npi
.npi_flags
|= NPIF_SOCKET
;
661 npi
.npi_timestamp
.tv_sec
= wakeuiid_last_check
.tv_sec
;
662 npi
.npi_timestamp
.tv_usec
= wakeuiid_last_check
.tv_usec
;
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
;
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
;
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
;
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
));
690 npi
.npi_owner_pid
= so
->last_pid
;
692 if (so
->last_pid
!= 0) {
693 proc_name(so
->last_pid
, npi
.npi_owner_pname
,
694 sizeof(npi
.npi_owner_pname
));
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
));
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
));
712 (void) net_port_info_add_entry(&npi
);