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
59struct 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
67union 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
88struct 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 */
122struct 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 */
186struct 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
224struct 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
287struct 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
295extern int if_ports_used_verbose;
296
297void if_ports_used_init(void);
298
299void if_ports_used_update_wakeuuid(struct ifnet *);
300
301struct inpcb;
302bool if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp);
303
304#if SKYWALK
305struct ns_flow_info;
306struct flow_entry;
307bool 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);
309void if_ports_used_match_pkt(struct ifnet *ifp, struct __kern_packet *pkt);
310#endif /* SKYWALK */
311
312void 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