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>
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 struct zone
*net_port_entry_zone
= NULL
;
154 #define NET_PORT_ENTRY_ZONE_MAX 128
155 #define NET_PORT_ENTRY_ZONE_NAME "net_port_entry"
157 static SLIST_HEAD(net_port_entry_list
, net_port_entry
) net_port_entry_list
=
158 SLIST_HEAD_INITIALIZER(&net_port_entry_list
);
160 struct timeval wakeuiid_last_check
;
163 if_ports_used_init(void)
165 if (if_ports_used_inited
== 0) {
166 lck_grp_attr_t
*lck_grp_attributes
= NULL
;
167 lck_attr_t
*lck_attributes
= NULL
;
169 timerclear(&wakeuiid_last_check
);
170 uuid_clear(current_wakeuuid
);
171 uuid_clear(test_wakeuuid
);
173 lck_grp_attributes
= lck_grp_attr_alloc_init();
174 net_port_entry_head_lock_group
= lck_grp_alloc_init(
175 "net port entry lock", lck_grp_attributes
);
177 lck_attributes
= lck_attr_alloc_init();
178 if (lck_attributes
== NULL
) {
179 panic("%s: lck_attr_alloc_init() failed", __func__
);
181 lck_mtx_init(&net_port_entry_head_lock
,
182 net_port_entry_head_lock_group
,
185 net_port_entry_count
= 0;
186 net_port_entry_zone
= zinit(sizeof(struct net_port_entry
),
187 NET_PORT_ENTRY_ZONE_MAX
* sizeof(struct net_port_entry
),
188 0, NET_PORT_ENTRY_ZONE_NAME
);
189 if (net_port_entry_zone
== NULL
) {
190 panic("%s: zinit(%s) failed", __func__
,
191 NET_PORT_ENTRY_ZONE_NAME
);
193 zone_change(net_port_entry_zone
, Z_EXPAND
, TRUE
);
194 zone_change(net_port_entry_zone
, Z_CALLERACCT
, FALSE
);
196 if_ports_used_inited
= 1;
198 lck_attr_free(lck_attributes
);
199 lck_grp_attr_free(lck_grp_attributes
);
204 net_port_entry_list_clear(void)
206 struct net_port_entry
*npe
;
208 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
210 while ((npe
= SLIST_FIRST(&net_port_entry_list
)) != NULL
) {
211 SLIST_REMOVE_HEAD(&net_port_entry_list
, npe_next
);
213 zfree(net_port_entry_zone
, npe
);
215 net_port_entry_count
= 0;
216 net_port_entry_gen
++;
220 get_test_wake_uuid(uuid_string_t wakeuuid_str
, size_t len
)
222 if (__improbable(use_test_wakeuuid
)) {
223 if (!uuid_is_null(test_wakeuuid
)) {
224 if (wakeuuid_str
!= NULL
&& len
!= 0) {
225 uuid_unparse(test_wakeuuid
, wakeuuid_str
);
228 } else if (strlen(test_wakeuuid_str
) != 0) {
229 if (wakeuuid_str
!= NULL
&& len
!= 0) {
230 strlcpy(wakeuuid_str
, test_wakeuuid_str
, len
);
242 is_wakeuuid_set(void)
245 * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set
246 * That means we are currently in a sleep/wake cycle
248 return get_test_wake_uuid(NULL
, 0) || IOPMCopySleepWakeUUIDKey(NULL
, 0);
252 if_ports_used_update_wakeuuid(struct ifnet
*ifp
)
255 bool wakeuuid_is_set
= false;
256 bool updated
= false;
257 uuid_string_t wakeuuid_str
;
259 uuid_clear(wakeuuid
);
261 if (__improbable(use_test_wakeuuid
)) {
262 wakeuuid_is_set
= get_test_wake_uuid(wakeuuid_str
,
263 sizeof(wakeuuid_str
));
265 wakeuuid_is_set
= IOPMCopySleepWakeUUIDKey(wakeuuid_str
,
266 sizeof(wakeuuid_str
));
269 if (wakeuuid_is_set
) {
270 if (uuid_parse(wakeuuid_str
, wakeuuid
) != 0) {
271 os_log(OS_LOG_DEFAULT
,
272 "%s: IOPMCopySleepWakeUUIDKey got bad value %s\n",
273 __func__
, wakeuuid_str
);
274 wakeuuid_is_set
= false;
278 if (!wakeuuid_is_set
) {
279 if (if_ports_used_verbose
> 0) {
280 os_log_info(OS_LOG_DEFAULT
,
281 "%s: SleepWakeUUID not set, "
282 "don't update the port list for %s\n",
283 __func__
, ifp
!= NULL
? if_name(ifp
) : "");
285 wakeuuid_not_set_count
+= 1;
287 microtime(&wakeuuid_not_set_last_time
);
288 strlcpy(wakeuuid_not_set_last_if
, if_name(ifp
),
289 sizeof(wakeuuid_not_set_last_if
));
294 lck_mtx_lock(&net_port_entry_head_lock
);
295 if (uuid_compare(wakeuuid
, current_wakeuuid
) != 0) {
296 net_port_entry_list_clear();
297 uuid_copy(current_wakeuuid
, wakeuuid
);
301 * Record the time last checked
303 microuptime(&wakeuiid_last_check
);
304 lck_mtx_unlock(&net_port_entry_head_lock
);
306 if (updated
&& if_ports_used_verbose
> 0) {
307 uuid_string_t uuid_str
;
309 uuid_unparse(current_wakeuuid
, uuid_str
);
310 log(LOG_ERR
, "%s: current wakeuuid %s\n",
317 net_port_info_equal(const struct net_port_info
*x
,
318 const struct net_port_info
*y
)
320 ASSERT(x
!= NULL
&& y
!= NULL
);
322 if (x
->npi_if_index
== y
->npi_if_index
&&
323 x
->npi_local_port
== y
->npi_local_port
&&
324 x
->npi_foreign_port
== y
->npi_foreign_port
&&
325 x
->npi_owner_pid
== y
->npi_owner_pid
&&
326 x
->npi_effective_pid
== y
->npi_effective_pid
&&
327 x
->npi_flags
== y
->npi_flags
&&
328 memcmp(&x
->npi_local_addr_
, &y
->npi_local_addr_
,
329 sizeof(union in_addr_4_6
)) == 0 &&
330 memcmp(&x
->npi_foreign_addr_
, &y
->npi_foreign_addr_
,
331 sizeof(union in_addr_4_6
)) == 0) {
338 net_port_info_has_entry(const struct net_port_info
*npi
)
340 struct net_port_entry
*npe
;
342 LCK_MTX_ASSERT(&net_port_entry_head_lock
, LCK_MTX_ASSERT_OWNED
);
344 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
345 if (net_port_info_equal(&npe
->npe_npi
, npi
)) {
354 net_port_info_add_entry(const struct net_port_info
*npi
)
356 struct net_port_entry
*npe
= NULL
;
358 bool entry_added
= false;
362 if (__improbable(is_wakeuuid_set() == false)) {
363 if (if_ports_used_verbose
> 0) {
364 log(LOG_ERR
, "%s: wakeuuid not set %u not adding "
365 "port: %u flags: 0x%xif: %u pid: %u epid %u\n",
367 ntohs(npi
->npi_local_port
),
371 npi
->npi_effective_pid
);
376 npe
= zalloc(net_port_entry_zone
);
377 if (__improbable(npe
== NULL
)) {
378 log(LOG_ERR
, "%s: zalloc() failed for "
379 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
381 ntohs(npi
->npi_local_port
),
385 npi
->npi_effective_pid
);
388 bzero(npe
, sizeof(struct net_port_entry
));
390 memcpy(&npe
->npe_npi
, npi
, sizeof(npe
->npe_npi
));
392 lck_mtx_lock(&net_port_entry_head_lock
);
394 if (net_port_info_has_entry(npi
) == false) {
395 SLIST_INSERT_HEAD(&net_port_entry_list
, npe
, npe_next
);
396 num
= net_port_entry_count
++;
399 if (if_ports_used_verbose
> 0) {
400 log(LOG_ERR
, "%s: num %u for "
401 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
404 ntohs(npi
->npi_local_port
),
408 npi
->npi_effective_pid
);
411 if (if_ports_used_verbose
> 0) {
412 log(LOG_ERR
, "%s: entry already added "
413 "port: %u flags: 0x%x if: %u pid: %u epid %u\n",
415 ntohs(npi
->npi_local_port
),
419 npi
->npi_effective_pid
);
423 lck_mtx_unlock(&net_port_entry_head_lock
);
425 if (entry_added
== false) {
426 zfree(net_port_entry_zone
, npe
);
432 #if (DEVELOPMENT || DEBUG)
434 sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS
436 #pragma unused(oidp, arg1, arg2)
439 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
442 if (req
->oldptr
== USER_ADDR_NULL
) {
443 req
->oldidx
= sizeof(uuid_t
);
446 if (req
->newptr
!= USER_ADDR_NULL
) {
447 uuid_generate(test_wakeuuid
);
449 error
= SYSCTL_OUT(req
, test_wakeuuid
,
450 MIN(sizeof(uuid_t
), req
->oldlen
));
456 sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS
458 #pragma unused(oidp, arg1, arg2)
461 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
464 if (req
->oldptr
== USER_ADDR_NULL
) {
465 req
->oldidx
= sizeof(uuid_t
);
468 if (req
->newptr
!= USER_ADDR_NULL
) {
469 uuid_clear(test_wakeuuid
);
471 error
= SYSCTL_OUT(req
, test_wakeuuid
,
472 MIN(sizeof(uuid_t
), req
->oldlen
));
478 sysctl_test_wakeuuid_str SYSCTL_HANDLER_ARGS
480 #pragma unused(oidp, arg1, arg2)
484 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
487 error
= sysctl_io_string(req
, test_wakeuuid_str
, sizeof(test_wakeuuid_str
), 1, &changed
);
489 os_log_info(OS_LOG_DEFAULT
, "%s: test_wakeuuid_str %s",
490 __func__
, test_wakeuuid_str
);
496 #endif /* (DEVELOPMENT || DEBUG) */
499 sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS
501 #pragma unused(oidp, arg1, arg2)
503 if (proc_is64bit(req
->p
)) {
504 struct user64_timeval tv
= {};
506 tv
.tv_sec
= wakeuuid_not_set_last_time
.tv_sec
;
507 tv
.tv_usec
= wakeuuid_not_set_last_time
.tv_usec
;
508 return SYSCTL_OUT(req
, &tv
, sizeof(tv
));
510 struct user32_timeval tv
= {};
512 tv
.tv_sec
= wakeuuid_not_set_last_time
.tv_sec
;
513 tv
.tv_usec
= wakeuuid_not_set_last_time
.tv_usec
;
514 return SYSCTL_OUT(req
, &tv
, sizeof(tv
));
519 sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS
521 #pragma unused(oidp, arg1, arg2)
523 return SYSCTL_OUT(req
, &wakeuuid_not_set_last_if
,
524 strlen(wakeuuid_not_set_last_if
) + 1);
528 sysctl_net_port_info_list SYSCTL_HANDLER_ARGS
530 #pragma unused(oidp, arg1, arg2)
532 struct xnpigen xnpigen
;
533 struct net_port_entry
*npe
;
535 if ((error
= priv_check_cred(kauth_cred_get(),
536 PRIV_NET_PRIVILEGED_NETWORK_STATISTICS
, 0)) != 0) {
539 lck_mtx_lock(&net_port_entry_head_lock
);
541 if (req
->oldptr
== USER_ADDR_NULL
) {
542 /* Add a 25 % cushion */
543 uint32_t cnt
= net_port_entry_count
;
545 req
->oldidx
= sizeof(struct xnpigen
) +
546 cnt
* sizeof(struct net_port_info
);
550 memset(&xnpigen
, 0, sizeof(struct xnpigen
));
551 xnpigen
.xng_len
= sizeof(struct xnpigen
);
552 xnpigen
.xng_gen
= net_port_entry_gen
;
553 uuid_copy(xnpigen
.xng_wakeuuid
, current_wakeuuid
);
554 xnpigen
.xng_npi_count
= net_port_entry_count
;
555 xnpigen
.xng_npi_size
= sizeof(struct net_port_info
);
556 error
= SYSCTL_OUT(req
, &xnpigen
, sizeof(xnpigen
));
558 printf("%s: SYSCTL_OUT(xnpigen) error %d\n",
563 SLIST_FOREACH(npe
, &net_port_entry_list
, npe_next
) {
564 error
= SYSCTL_OUT(req
, &npe
->npe_npi
,
565 sizeof(struct net_port_info
));
567 printf("%s: SYSCTL_OUT(npi) error %d\n",
573 lck_mtx_unlock(&net_port_entry_head_lock
);
579 * Mirror the arguments of ifnet_get_local_ports_extended()
585 sysctl_get_ports_used SYSCTL_HANDLER_ARGS
588 int *name
= (int *)arg1
;
592 protocol_family_t protocol
;
595 u_int8_t
*bitfield
= NULL
;
597 if (req
->newptr
!= USER_ADDR_NULL
) {
602 * 3 is the required number of parameters: ifindex, protocol and flags
609 if (req
->oldptr
== USER_ADDR_NULL
) {
610 req
->oldidx
= bitstr_size(IP_PORTRANGE_SIZE
);
613 if (req
->oldlen
< bitstr_size(IP_PORTRANGE_SIZE
)) {
622 ifnet_head_lock_shared();
623 if (!IF_INDEX_IN_RANGE(idx
)) {
628 ifp
= ifindex2ifnet
[idx
];
631 bitfield
= _MALLOC(bitstr_size(IP_PORTRANGE_SIZE
), M_TEMP
,
633 if (bitfield
== NULL
) {
637 error
= ifnet_get_local_ports_extended(ifp
, protocol
, flags
, bitfield
);
639 printf("%s: ifnet_get_local_ports_extended() error %d\n",
643 error
= SYSCTL_OUT(req
, bitfield
, bitstr_size(IP_PORTRANGE_SIZE
));
645 if (bitfield
!= NULL
) {
646 _FREE(bitfield
, M_TEMP
);
651 __private_extern__
void
652 if_ports_used_add_inpcb(const uint32_t ifindex
, const struct inpcb
*inp
)
654 struct net_port_info npi
;
655 struct socket
*so
= inp
->inp_socket
;
657 bzero(&npi
, sizeof(struct net_port_info
));
659 npi
.npi_if_index
= ifindex
;
661 npi
.npi_flags
|= NPIF_SOCKET
;
663 npi
.npi_timestamp
.tv_sec
= wakeuiid_last_check
.tv_sec
;
664 npi
.npi_timestamp
.tv_usec
= wakeuiid_last_check
.tv_usec
;
666 if (SOCK_PROTO(so
) == IPPROTO_TCP
) {
667 struct tcpcb
*tp
= intotcpcb(inp
);
669 npi
.npi_flags
|= NPIF_TCP
;
670 if (tp
!= NULL
&& tp
->t_state
== TCPS_LISTEN
) {
671 npi
.npi_flags
|= NPIF_LISTEN
;
673 } else if (SOCK_PROTO(so
) == IPPROTO_UDP
) {
674 npi
.npi_flags
|= NPIF_UDP
;
676 panic("%s: unexpected protocol %u for inp %p\n", __func__
,
677 SOCK_PROTO(inp
->inp_socket
), inp
);
680 uuid_copy(npi
.npi_flow_uuid
, inp
->necp_client_uuid
);
682 npi
.npi_local_port
= inp
->inp_lport
;
683 npi
.npi_foreign_port
= inp
->inp_fport
;
686 * Take in account IPv4 addresses mapped on IPv6
688 if ((inp
->inp_vflag
& INP_IPV6
) != 0 && (inp
->inp_flags
& IN6P_IPV6_V6ONLY
) == 0 &&
689 (inp
->inp_vflag
& (INP_IPV6
| INP_IPV4
)) == (INP_IPV6
| INP_IPV4
)) {
690 npi
.npi_flags
|= NPIF_IPV6
| NPIF_IPV4
;
691 memcpy(&npi
.npi_local_addr_in6
,
692 &inp
->in6p_laddr
, sizeof(struct in6_addr
));
693 } else if (inp
->inp_vflag
& INP_IPV4
) {
694 npi
.npi_flags
|= NPIF_IPV4
;
695 npi
.npi_local_addr_in
= inp
->inp_laddr
;
696 npi
.npi_foreign_addr_in
= inp
->inp_faddr
;
698 npi
.npi_flags
|= NPIF_IPV6
;
699 memcpy(&npi
.npi_local_addr_in6
,
700 &inp
->in6p_laddr
, sizeof(struct in6_addr
));
701 memcpy(&npi
.npi_foreign_addr_in6
,
702 &inp
->in6p_faddr
, sizeof(struct in6_addr
));
705 npi
.npi_owner_pid
= so
->last_pid
;
707 if (so
->last_pid
!= 0) {
708 proc_name(so
->last_pid
, npi
.npi_owner_pname
,
709 sizeof(npi
.npi_owner_pname
));
712 if (so
->so_flags
& SOF_DELEGATED
) {
713 npi
.npi_flags
|= NPIF_DELEGATED
;
714 npi
.npi_effective_pid
= so
->e_pid
;
715 if (so
->e_pid
!= 0) {
716 proc_name(so
->e_pid
, npi
.npi_effective_pname
,
717 sizeof(npi
.npi_effective_pname
));
720 npi
.npi_effective_pid
= so
->last_pid
;
721 if (so
->last_pid
!= 0) {
722 strlcpy(npi
.npi_effective_pname
, npi
.npi_owner_pname
,
723 sizeof(npi
.npi_effective_pname
));
727 (void) net_port_info_add_entry(&npi
);