xref: /xnu-10002.1.13/bsd/net/if_ports_used.h (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a) !
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  * struct net_port_info_una_wake_event is the event data for KEV_POWER_WAKE_PACKET
166  *
167  * una_wake_pkt_control_flags is valid when NPIF_TCP is set and contains the TCP packet
168  * header flags -- see TH_FLAGS in netinet/tcp.h
169  *
170  * See <net/if_private.h> for definiton of values of these kinds of fields:
171  *  - xxx_if_family             IFRTYPE_FAMILY_YYY
172  *  - xxx_if_subfamily          IFRTYPE_SUBFAMILY_YYY
173  *  - xxx_if_functional_type    IFRTYPE_FUNCTIONAL_YYY
174  */
175 struct net_port_info_wake_event {
176 	uuid_t              wake_uuid;
177 	struct timeval32    wake_pkt_timestamp; /* when processed by networking stack */
178 	uint16_t            wake_pkt_if_index; /* interface of incoming wake packet */
179 	in_port_t           wake_pkt_port; /* local port in network byte order */
180 	uint16_t            wake_pkt_flags; /* NPIF_xxx */
181 	pid_t               wake_pkt_owner_pid;
182 	pid_t               wake_pkt_effective_pid;
183 	char                wake_pkt_owner_pname[MAXCOMLEN + 1];
184 	char                wake_pkt_effective_pname[MAXCOMLEN + 1];
185 	uuid_t              wake_pkt_owner_uuid;
186 	uuid_t              wake_pkt_effective_uuid;
187 	in_port_t           wake_pkt_foreign_port; /* network byte order */
188 	union in_addr_4_6   wake_pkt_local_addr_;
189 	union in_addr_4_6   wake_pkt_foreign_addr_;
190 	char                wake_pkt_ifname[IFNAMSIZ]; /* name + unit */
191 
192 	/* Following fields added with NPI_HAS_PACKET_INFO */
193 	uint32_t            wake_pkt_total_len; /* actual length of packet */
194 	uint32_t            wake_pkt_data_len; /* exclude transport (TCP/UDP) header length */
195 	uint16_t            wake_pkt_control_flags;
196 
197 	/* Followings fields added with NPI_HAS_PHYSICAL_LINK */
198 	struct npi_if_info  wake_pkt_if_info;  /* inner-most interface of TCP/UDP packet */
199 
200 	char                wake_pkt_phy_ifname[IFNAMSIZ]; /* name + unit */
201 	struct npi_if_info  wake_pkt_phy_if_info; /* outer-most interface of wake packet */
202 };
203 
204 /*
205  * struct net_port_info_una_wake_event is the event data for KEV_POWER_UNATTRIBUTED_WAKE
206  *
207  * una_wake_pkt_proto is useful to track unexpected wake packets when NPIF_IPV4 or
208  * NPIF_IPV6 is set this is the IP protocol -- see IPPROTO_x from netinet/in.h.
209  * When NPIF_IPV4 and NPIF_IPV6 are not set the cotent of una_wake_pkt can give clues
210  * on the type of unexpected wake packet
211  */
212 #define NPI_MAX_UNA_WAKE_PKT_LEN 102
213 struct net_port_info_una_wake_event {
214 	uuid_t              una_wake_uuid;
215 	struct timeval32    una_wake_pkt_timestamp; /* when processed by networking stack */
216 	uint16_t            una_wake_pkt_if_index; /* interface of incoming wake packet */
217 	uint16_t            una_wake_pkt_flags; /* NPIF_xxx */
218 	uint16_t            _una_wake_pkt_reserved; /* not used */
219 	uint16_t            una_wake_ptk_len; /* length of una_wake_pkt */
220 	uint8_t             una_wake_pkt[NPI_MAX_UNA_WAKE_PKT_LEN]; /* initial portion of the IPv4/IPv6 packet  */
221 	in_port_t           una_wake_pkt_local_port; /* network byte order */
222 	in_port_t           una_wake_pkt_foreign_port; /* network byte order */
223 	union in_addr_4_6   una_wake_pkt_local_addr_;
224 	union in_addr_4_6   una_wake_pkt_foreign_addr_;
225 	char                una_wake_pkt_ifname[IFNAMSIZ]; /* name + unit */
226 
227 	/* Following fields added with NPI_HAS_PACKET_INFO */
228 	uint32_t            una_wake_pkt_total_len; /* actual length of packet */
229 	uint32_t            una_wake_pkt_data_len; /* exclude transport (TCP/UDP) header length */
230 	uint16_t            una_wake_pkt_control_flags; /* for NPIF_TCP, see TH_FLAGS in netinet/tcp.h */
231 	uint16_t            una_wake_pkt_proto; /* IPv4 or IPv6 protocol */
232 
233 	/* Followings fields added with NPI_HAS_PHYSICAL_LINK */
234 	struct npi_if_info  una_wake_pkt_if_info; /* inner-most interface for TCP/UDP tuple  */
235 
236 	char                una_wake_pkt_phy_ifname[IFNAMSIZ]; /* name + unit */
237 	struct npi_if_info  una_wake_pkt_phy_if_info; /* outer-most interface of wake packet */
238 };
239 
240 #define IFPU_HAS_MATCH_WAKE_PKT_NO_FLAG 1 /* ifpu_match_wake_pkt_no_flag is defined */
241 
242 #define IF_PORTS_USED_STATS_LIST \
243 	X(uint64_t, ifpu_wakeuid_gen, "wakeuuid generation%s", "", "s") \
244 	X(uint64_t, ifpu_wakeuuid_not_set_count, "offload port list quer%s with wakeuuid not set", "y", "ies") \
245 	X(uint64_t, ifpu_npe_total, "total offload port entr%s created since boot", "y", "ies") \
246 	X(uint64_t, ifpu_npe_count, "current offload port entr%s", "y", "ies") \
247 	X(uint64_t, ifpu_npe_max, "max offload port entr%s", "y", "ies") \
248 	X(uint64_t, ifpu_npe_dup, "duplicate offload port entr%s", "y", "ies") \
249 	X(uint64_t, ifpu_npi_hash_search_total, "total table entry search%s", "", "es") \
250 	X(uint64_t, ifpu_npi_hash_search_max, "max hash table entry search%s", "", "es") \
251 	X(uint64_t, ifpu_so_match_wake_pkt, "match so wake packet call%s", "", "s") \
252 	X(uint64_t, ifpu_ch_match_wake_pkt, "match ch wake packet call%s", "", "s") \
253 	X(uint64_t, ifpu_ipv4_wake_pkt, "IPv4 wake packet%s", "", "s") \
254 	X(uint64_t, ifpu_ipv6_wake_pkt, "IPv6 wake packet%s", "", "s") \
255 	X(uint64_t, ifpu_tcp_wake_pkt, "TCP wake packet%s", "", "s") \
256 	X(uint64_t, ifpu_udp_wake_pkt, "UDP wake packet%s", "", "s") \
257 	X(uint64_t, ifpu_isakmp_natt_wake_pkt, "ISAKMP NAT traversal wake packet%s", "", "s") \
258 	X(uint64_t, ifpu_esp_wake_pkt, "ESP wake packet%s", "", "s") \
259 	X(uint64_t, ifpu_bad_proto_wake_pkt, "bad protocol wake packet%s", "", "s") \
260 	X(uint64_t, ifpu_bad_family_wake_pkt, "bad family wake packet%s", "", "s") \
261 	X(uint64_t, ifpu_wake_pkt_event, "wake packet event%s", "", "s") \
262 	X(uint64_t, ifpu_dup_wake_pkt_event, "duplicate wake packet event%s in same wake cycle", "", "s") \
263 	X(uint64_t, ifpu_wake_pkt_event_error, "wake packet event%s undelivered", "", "s") \
264 	X(uint64_t, ifpu_unattributed_wake_event, "unattributed wake packet event%s", "", "s") \
265 	X(uint64_t, ifpu_dup_unattributed_wake_event, "duplicate unattributed wake packet event%s in same wake cycle", "", "s") \
266 	X(uint64_t, ifpu_unattributed_wake_event_error, "unattributed wake packet event%s undelivered", "", "s") \
267 	X(uint64_t, ifpu_unattributed_null_recvif, "unattributed wake packet%s received with null interface", "", "s") \
268 	X(uint64_t, ifpu_match_wake_pkt_no_flag, "bad packet%s without wake flag", "", "s") \
269 	X(uint64_t, ifpu_frag_wake_pkt, "pure fragment wake packet%s", "", "s") \
270 	X(uint64_t, ifpu_incomplete_tcp_hdr_pkt, "packet%s with incomplete TCP header", "", "s") \
271 	X(uint64_t, ifpu_incomplete_udp_hdr_pkt, "packet%s with incomplete UDP header", "", "s") \
272 	X(uint64_t, ifpu_npi_not_added_no_wakeuuid, "port entr%s not added with wakeuuid not set", "y", "ies") \
273 	X(uint64_t, ifpu_deferred_isakmp_natt_wake_pkt, "deferred matching of ISAKMP NAT traversal wake packet%s", "", "s")
274 
275 struct if_ports_used_stats {
276 #define X(_type, _field, ...) _type _field;
277 	IF_PORTS_USED_STATS_LIST
278 #undef X
279 };
280 
281 #ifdef XNU_KERNEL_PRIVATE
282 
283 void if_ports_used_init(void);
284 
285 void if_ports_used_update_wakeuuid(struct ifnet *);
286 
287 struct inpcb;
288 bool if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp);
289 
290 #if SKYWALK
291 struct ns_flow_info;
292 struct flow_entry;
293 bool if_ports_used_add_flow_entry(const struct flow_entry *fe, const uint32_t ifindex,
294     const struct ns_flow_info *nfi, uint32_t ns_flags);
295 void if_ports_used_match_pkt(struct ifnet *ifp, struct __kern_packet *pkt);
296 #endif /* SKYWALK */
297 
298 void if_ports_used_match_mbuf(struct ifnet *ifp, protocol_family_t proto_family,
299     struct mbuf *m);
300 
301 #endif /* XNU_KERNEL_PRIVATE */
302 #endif /* PRIVATE */
303 
304 #endif /* _NET_IF_PORT_USED_H_ */
305