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