1 /* 2 * Copyright (c) 2017-2024 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 #ifndef _NET_IF_PORT_USED_H_ 30 #define _NET_IF_PORT_USED_H_ 31 32 #ifdef PRIVATE 33 34 #include <sys/types.h> 35 #include <stdbool.h> 36 #include <stdint.h> 37 #include <sys/proc.h> 38 #include <sys/queue.h> 39 #include <sys/_types/_timeval32.h> 40 #include <net/if.h> 41 #include <netinet/in.h> 42 #include <uuid/uuid.h> 43 #include <stdbool.h> 44 45 #define IP_PORTRANGE_SIZE 65536 46 47 #define WAKE_PKT_EVENT_CONTROL_ENTITLEMENT "com.apple.private.network.wake_pkt.control" 48 49 /* 50 * The sysctl "net.link.generic.system.port_used.list" returns: 51 * - one "struct xnpigen" as a preamble 52 * - zero or more "struct net_port_info" according to xng_npi_count 53 * 54 * The list may contain information several interfaces if several drivers 55 * queried the list of port to offload 56 * 57 * The same local port may have more than one "struct net_port_info" on 58 * a given interface, for example when a local server has mutiple clients 59 * connections 60 */ 61 62 struct xnpigen { 63 uint32_t xng_len; /* length of this data structure */ 64 uint32_t xng_gen; /* how many times the list was built */ 65 uint32_t xng_npi_count; /* number of net_port_info following */ 66 uint32_t xng_npi_size; /* number of struct net_port_info */ 67 uuid_t xng_wakeuuid; /* WakeUUID when list was built */ 68 }; 69 70 union in_addr_4_6 { 71 struct in_addr _in_a_4; 72 struct in6_addr _in_a_6; 73 }; 74 75 #define NPIF_IPV4 0x0001 76 #define NPIF_IPV6 0x0002 77 #define NPIF_TCP 0x0004 78 #define NPIF_UDP 0x0008 79 #define NPIF_DELEGATED 0x0010 80 #define NPIF_SOCKET 0x0020 81 #define NPIF_CHANNEL 0x0040 82 #define NPIF_LISTEN 0x0080 83 #define NPIF_WAKEPKT 0x0100 84 #define NPIF_NOWAKE 0x0200 85 #define NPIF_FRAG 0x0400 86 #define NPIF_ESP 0x0800 87 #define NPIF_COMPLINK 0x1000 88 #define NPIF_CONNECTION_IDLE 0x2000 89 #define NPIF_LPW 0x4000 90 #define NPIF_DELAYWAKEPKTEVENT 0x8000 91 92 #define NPI_FLAGS_TABLE(x) \ 93 X(NPIF_IPV4, "4", "IPv4 flow") \ 94 X(NPIF_IPV6, "6", "IPv6 flow") \ 95 X(NPIF_TCP, "T", "TCP flow") \ 96 X(NPIF_UDP, "U", "UDP flow") \ 97 X(NPIF_DELEGATED, "D", "process delegated") \ 98 X(NPIF_SOCKET, "S", "socket flow") \ 99 X(NPIF_CHANNEL, "C", "channel") \ 100 X(NPIF_LISTEN, "L", "listening flow") \ 101 X(NPIF_WAKEPKT, "W", "wake packet") \ 102 X(NPIF_NOWAKE, "N", "flow marked with NOWAKEFROMSLEEP") \ 103 X(NPIF_FRAG, "F", "packet is pure fragment") \ 104 X(NPIF_ESP, "E", "ESP packet") \ 105 X(NPIF_COMPLINK, "c", "interface is companion link") \ 106 X(NPIF_CONNECTION_IDLE, "i", "flow connection is idle") \ 107 X(NPIF_LPW, "l", "packet received in low power wake") \ 108 X(NPIF_DELAYWAKEPKTEVENT, "d", "delayed wake packet attribution") 109 110 #define NPI_HAS_EFFECTIVE_UUID 1 111 112 struct net_port_info { 113 uint16_t npi_if_index; 114 uint16_t npi_flags; /* NPIF_xxx */ 115 struct timeval32 npi_timestamp; /* when passed to driver */ 116 uuid_t npi_flow_uuid; 117 in_port_t npi_local_port; /* network byte order */ 118 in_port_t npi_foreign_port; /* network byte order */ 119 union in_addr_4_6 npi_local_addr_; 120 union in_addr_4_6 npi_foreign_addr_; 121 pid_t npi_owner_pid; 122 pid_t npi_effective_pid; 123 char npi_owner_pname[MAXCOMLEN + 1]; 124 char npi_effective_pname[MAXCOMLEN + 1]; 125 uuid_t npi_owner_uuid; 126 uuid_t npi_effective_uuid; 127 }; 128 129 #define npi_local_addr_in npi_local_addr_._in_a_4 130 #define npi_foreign_addr_in npi_foreign_addr_._in_a_4 131 132 #define npi_local_addr_in6 npi_local_addr_._in_a_6 133 #define npi_foreign_addr_in6 npi_foreign_addr_._in_a_6 134 135 #define NPI_HAS_WAKE_EVENT_TUPLE 1 136 #define NPI_HAS_PACKET_INFO 1 137 #define NPI_HAS_PHYSICAL_LINK 1 /* npi_if_info and phy_if fields are present */ 138 139 /* 140 * struct npi_if_info provides detailed information about the kind of interface 141 * 142 * See <net/if_private.h> for definitions of possible values of each field 143 * 144 * Note: the IFRTYPE_xxx values are the same as the IFNET_xxx used inside the kernel 145 */ 146 struct npi_if_info { 147 uint32_t npi_if_family; /* IFRTYPE_FAMILY_xxx */ 148 uint32_t npi_if_subfamily; /* IFRTYPE_SUBFAMILY_xxx */ 149 uint32_t npi_if_functional_type; /* IFRTYPE_FUNCTIONAL_xxx */ 150 }; 151 152 #define NPI_IF_INFO_IS_ETHERNET(_npi) \ 153 ((_npi)->npi_if_family == IFRTYPE_FAMILY_ETHERNET) 154 155 #define NPI_IF_INFO_IS_ETHERNET_WIRED(_npi) \ 156 (NPI_IF_INFO_IS_ETHERNET(_npi) && \ 157 (_npi)->npi_if_subfamily != IFRTYPE_SUBFAMILY_WIFI) 158 159 #define NPI_IF_INFO_IS_WIFI(_npi) \ 160 (NPI_IF_INFO_IS_ETHERNET(_npi) && \ 161 (_npi)->npi_if_subfamily == IFRTYPE_SUBFAMILY_WIFI) 162 163 #define NPI_IF_INFO_IS_CELLULAR(_npi) \ 164 ((_npi)->npi_if_family == IFRTYPE_FAMILY_CELLULAR) 165 166 #define NPI_IF_INFO_IS_IPSEC(_npi) \ 167 ((_npi)->npi_if_family == IFRTYPE_FAMILY_IPSEC) 168 169 #define NPI_IF_INFO_IS_IPSEC_COMPANIONLINK(_npi) \ 170 ((_npi)->npi_if_family == IFRTYPE_FAMILY_IPSEC && \ 171 (_npi)->npi_if_functional_type == IFRTYPE_FUNCTIONAL_COMPANIONLINK) 172 173 #define NPI_IF_INFO_IS_IPSEC_COMPANIONLINK_BLUETOOTH(_npi) \ 174 (NPI_IF_INFO_IS_IPSEC_COMPANIONLINK(_npi) && \ 175 (_npi)->npi_if_subfamily == IFRTYPE_SUBFAMILY_BLUETOOTH) 176 177 #define NPI_IF_INFO_IS_IPSEC_COMPANIONLINK_WIFI(_npi) \ 178 (NPI_IF_INFO_IS_IPSEC_COMPANIONLINK(_npi) && \ 179 (_npi)->npi_if_subfamily == IFRTYPE_SUBFAMILY_WIFI) 180 181 #define NPI_IF_INFO_IS_IPSEC_COMPANIONLINK_QUICKRELAY(_npi) \ 182 (NPI_IF_INFO_IS_IPSEC_COMPANIONLINK(_npi) && \ 183 (_npi)->npi_if_subfamily == IFRTYPE_SUBFAMILY_QUICKRELAY) 184 185 #define NPI_IF_INFO_IS_UTUN(_npi) \ 186 ((_npi)->npi_if_family == IFRTYPE_FAMILY_UTUN) 187 188 /* 189 * Symbolic names for bits of wake_pkt_control_flags and una_wake_pkt_control_flags 190 * When the protocol is TCP (flag NPIF_TCP set) the lower 8 bits correspond to the TCP header flag 191 */ 192 #define NPICF_TH_FIN 0x01 193 #define NPICF_TH_SYN 0x02 194 #define NPICF_TH_RST 0x04 195 #define NPICF_TH_PUSH 0x08 196 #define NPICF_TH_ACK 0x10 197 #define NPICF_TH_URG 0x20 198 #define NPICF_TH_ECE 0x40 199 #define NPICF_TH_CWR 0x80 200 #define NPICF_NOWAKE 0x1000 201 202 /* 203 * struct net_port_info_wake_event is the event data for KEV_POWER_WAKE_PACKET 204 * 205 * See <net/if_private.h> for definiton of values of these kinds of fields: 206 * - xxx_if_family IFRTYPE_FAMILY_YYY 207 * - xxx_if_subfamily IFRTYPE_SUBFAMILY_YYY 208 * - xxx_if_functional_type IFRTYPE_FUNCTIONAL_YYY 209 */ 210 struct net_port_info_wake_event { 211 uuid_t wake_uuid; 212 struct timeval32 wake_pkt_timestamp; /* when processed by networking stack */ 213 uint16_t wake_pkt_if_index; /* interface of incoming wake packet */ 214 in_port_t wake_pkt_port; /* local port in network byte order */ 215 uint16_t wake_pkt_flags; /* NPIF_xxx */ 216 pid_t wake_pkt_owner_pid; 217 pid_t wake_pkt_effective_pid; 218 char wake_pkt_owner_pname[MAXCOMLEN + 1]; 219 char wake_pkt_effective_pname[MAXCOMLEN + 1]; 220 uuid_t wake_pkt_owner_uuid; 221 uuid_t wake_pkt_effective_uuid; 222 in_port_t wake_pkt_foreign_port; /* network byte order */ 223 union in_addr_4_6 wake_pkt_local_addr_; 224 union in_addr_4_6 wake_pkt_foreign_addr_; 225 char wake_pkt_ifname[IFNAMSIZ]; /* name + unit */ 226 227 /* Following fields added with NPI_HAS_PACKET_INFO */ 228 uint32_t wake_pkt_total_len; /* actual length of packet */ 229 uint32_t wake_pkt_data_len; /* exclude transport (TCP/UDP) header length */ 230 uint16_t wake_pkt_control_flags; /* see NPICF_xxx above */ 231 232 /* Followings fields added with NPI_HAS_PHYSICAL_LINK */ 233 struct npi_if_info wake_pkt_if_info; /* inner-most interface of TCP/UDP packet */ 234 235 char wake_pkt_phy_ifname[IFNAMSIZ]; /* name + unit */ 236 struct npi_if_info wake_pkt_phy_if_info; /* outer-most interface of wake packet */ 237 }; 238 239 /* 240 * struct net_port_info_una_wake_event is the event data for KEV_POWER_UNATTRIBUTED_WAKE 241 * 242 * una_wake_pkt_proto is useful to track unexpected wake packets when NPIF_IPV4 or 243 * NPIF_IPV6 is set this is the IP protocol -- see IPPROTO_x from netinet/in.h. 244 * When NPIF_IPV4 and NPIF_IPV6 are not set the cotent of una_wake_pkt can give clues 245 * on the type of unexpected wake packet 246 */ 247 #define NPI_MAX_UNA_WAKE_PKT_LEN 102 248 struct net_port_info_una_wake_event { 249 uuid_t una_wake_uuid; 250 struct timeval32 una_wake_pkt_timestamp; /* when processed by networking stack */ 251 uint16_t una_wake_pkt_if_index; /* interface of incoming wake packet */ 252 uint16_t una_wake_pkt_flags; /* NPIF_xxx */ 253 uint16_t _una_wake_pkt_reserved; /* not used */ 254 uint16_t una_wake_ptk_len; /* length of una_wake_pkt */ 255 uint8_t una_wake_pkt[NPI_MAX_UNA_WAKE_PKT_LEN]; /* initial portion of the IPv4/IPv6 packet */ 256 in_port_t una_wake_pkt_local_port; /* network byte order */ 257 in_port_t una_wake_pkt_foreign_port; /* network byte order */ 258 union in_addr_4_6 una_wake_pkt_local_addr_; 259 union in_addr_4_6 una_wake_pkt_foreign_addr_; 260 char una_wake_pkt_ifname[IFNAMSIZ]; /* name + unit */ 261 262 /* Following fields added with NPI_HAS_PACKET_INFO */ 263 uint32_t una_wake_pkt_total_len; /* actual length of packet */ 264 uint32_t una_wake_pkt_data_len; /* exclude transport (TCP/UDP) header length */ 265 uint16_t una_wake_pkt_control_flags; /* see NPICF_xxx above */ 266 uint16_t una_wake_pkt_proto; /* IPv4 or IPv6 protocol */ 267 268 /* Followings fields added with NPI_HAS_PHYSICAL_LINK */ 269 struct npi_if_info una_wake_pkt_if_info; /* inner-most interface for TCP/UDP tuple */ 270 271 char una_wake_pkt_phy_ifname[IFNAMSIZ]; /* name + unit */ 272 struct npi_if_info una_wake_pkt_phy_if_info; /* outer-most interface of wake packet */ 273 }; 274 275 #define IFPU_HAS_DELAY_WAKE_EVENT_FIELDS 1 /* ifpu_delay_phy_wake_pkt and co are defined */ 276 277 #define IF_PORTS_USED_STATS_LIST \ 278 X(uint64_t, ifpu_wakeuid_gen, "wakeuuid generation%s", "", "s") \ 279 X(uint64_t, ifpu_wakeuuid_not_set_count, "offload port list quer%s with wakeuuid not set", "y", "ies") \ 280 X(uint64_t, ifpu_npe_total, "total offload port entr%s created since boot", "y", "ies") \ 281 X(uint64_t, ifpu_npe_count, "current offload port entr%s", "y", "ies") \ 282 X(uint64_t, ifpu_npe_max, "max offload port entr%s", "y", "ies") \ 283 X(uint64_t, ifpu_npe_dup, "duplicate offload port entr%s", "y", "ies") \ 284 X(uint64_t, ifpu_npi_hash_search_total, "total table entry search%s", "", "es") \ 285 X(uint64_t, ifpu_npi_hash_search_max, "max hash table entry search%s", "", "es") \ 286 X(uint64_t, ifpu_so_match_wake_pkt, "match so wake packet call%s", "", "s") \ 287 X(uint64_t, ifpu_ch_match_wake_pkt, "match ch wake packet call%s", "", "s") \ 288 X(uint64_t, ifpu_ipv4_wake_pkt, "IPv4 wake packet%s", "", "s") \ 289 X(uint64_t, ifpu_ipv6_wake_pkt, "IPv6 wake packet%s", "", "s") \ 290 X(uint64_t, ifpu_tcp_wake_pkt, "TCP wake packet%s", "", "s") \ 291 X(uint64_t, ifpu_udp_wake_pkt, "UDP wake packet%s", "", "s") \ 292 X(uint64_t, ifpu_isakmp_natt_wake_pkt, "ISAKMP NAT traversal wake packet%s", "", "s") \ 293 X(uint64_t, ifpu_esp_wake_pkt, "ESP wake packet%s", "", "s") \ 294 X(uint64_t, ifpu_bad_proto_wake_pkt, "bad protocol wake packet%s", "", "s") \ 295 X(uint64_t, ifpu_bad_family_wake_pkt, "bad family wake packet%s", "", "s") \ 296 X(uint64_t, ifpu_wake_pkt_event, "wake packet event%s", "", "s") \ 297 X(uint64_t, ifpu_dup_wake_pkt_event, "duplicate wake packet event%s in same wake cycle", "", "s") \ 298 X(uint64_t, ifpu_wake_pkt_event_error, "wake packet event%s undelivered", "", "s") \ 299 X(uint64_t, ifpu_unattributed_wake_event, "unattributed wake packet event%s", "", "s") \ 300 X(uint64_t, ifpu_dup_unattributed_wake_event, "duplicate unattributed wake packet event%s in same wake cycle", "", "s") \ 301 X(uint64_t, ifpu_unattributed_wake_event_error, "unattributed wake packet event%s undelivered", "", "s") \ 302 X(uint64_t, ifpu_unattributed_null_recvif, "unattributed wake packet%s received with null interface", "", "s") \ 303 X(uint64_t, ifpu_match_wake_pkt_no_flag, "bad packet%s without wake flag", "", "s") \ 304 X(uint64_t, ifpu_frag_wake_pkt, "pure fragment wake packet%s", "", "s") \ 305 X(uint64_t, ifpu_incomplete_tcp_hdr_pkt, "packet%s with incomplete TCP header", "", "s") \ 306 X(uint64_t, ifpu_incomplete_udp_hdr_pkt, "packet%s with incomplete UDP header", "", "s") \ 307 X(uint64_t, ifpu_npi_not_added_no_wakeuuid, "port entr%s not added with wakeuuid not set", "y", "ies") \ 308 X(uint64_t, ifpu_deferred_isakmp_natt_wake_pkt, "deferred matching of ISAKMP NAT traversal wake packet%s", "", "s") \ 309 X(uint64_t, ifpu_spurious_wake_event, "spurious no wake from sleep packet event%s", "", "s") \ 310 X(uint64_t, ifpu_delayed_attributed_wake_event, "delayed attributed wake packet event%s", "", "s") \ 311 X(uint64_t, ifpu_delayed_unattributed_wake_event, "delayed unattributed wake packet event%s", "", "s") \ 312 X(uint64_t, ifpu_delayed_wake_event_undelivered, "undelivered delayed wake packet event%s", "", "s") \ 313 X(uint64_t, ifpu_connection_idle_wake, "connection idle wake%s", "", "s") \ 314 X(uint64_t, ifpu_lpw_connection_idle_wake, "LPW connection idle wake%s", "", "s") \ 315 X(uint64_t, ifpu_lpw_not_idle_wake, "LPW not idle connection wake%s", "", "s") \ 316 X(uint64_t, ifpu_lpw_to_full_wake, "LPW to full wake transition%s", "", "s") \ 317 X(uint64_t, ifpu_ignored_phy_wake_pkt, "ignored wake packet%s in same wake cycle", "", "s") \ 318 X(uint64_t, ifpu_delay_phy_wake_pkt, "delayed wake packet%s", "", "s") \ 319 X(uint64_t, ifpu_ignored_delayed_attributed_events, "ignored delayed attributed event%s", "", "s") \ 320 X(uint64_t, ifpu_ignored_delayed_unattributed_events, "ignored delayed unattributed event%s", "", "s") \ 321 X(uint64_t, ifpu_wake_pkt_event_notify_in_vain, "wake pkt event notifications%s in vain", "", "s") 322 323 struct if_ports_used_stats { 324 #define X(_type, _field, ...) _type _field; 325 IF_PORTS_USED_STATS_LIST 326 #undef X 327 }; 328 329 #ifdef XNU_KERNEL_PRIVATE 330 331 #include <os/log.h> 332 333 extern os_log_t wake_packet_log_handle; 334 335 extern int if_ports_used_verbose; 336 337 void if_ports_used_init(void); 338 339 void if_ports_used_update_wakeuuid(struct ifnet *); 340 341 struct inpcb; 342 bool if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp); 343 344 #if SKYWALK 345 struct ns_flow_info; 346 struct flow_entry; 347 bool if_ports_used_add_flow_entry(const struct flow_entry *fe, const uint32_t ifindex, 348 const struct ns_flow_info *nfi, uint32_t ns_flags); 349 void if_ports_used_match_pkt(struct ifnet *ifp, struct __kern_packet *pkt); 350 #endif /* SKYWALK */ 351 352 void if_ports_used_match_mbuf(struct ifnet *ifp, protocol_family_t proto_family, 353 struct mbuf *m); 354 355 void init_inband_wake_pkt_tagging_for_family(struct ifnet *ifp); 356 357 #if (DEBUG | DEVELOPMENT) 358 bool check_wake_mbuf(ifnet_t ifp, protocol_family_t protocol_family, mbuf_ref_t m); 359 bool check_wake_pkt(ifnet_t ifp, struct __kern_packet *pkt); 360 #endif /* (DEBUG | DEVELOPMENT) */ 361 362 bool if_is_lpw_enabled(struct ifnet *); 363 void if_exit_lpw(struct ifnet *ifp, const char *lpw_exit_reason); 364 365 #endif /* XNU_KERNEL_PRIVATE */ 366 #endif /* PRIVATE */ 367 368 369 #endif /* _NET_IF_PORT_USED_H_ */ 370