xref: /xnu-12377.81.4/bsd/net/if_ports_used.h (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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