xref: /xnu-10002.81.5/bsd/netinet/ip_var.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*
2  * Copyright (c) 2000-2021 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  * Copyright (c) 1982, 1986, 1993
30  *	The Regents of the University of California.  All rights reserved.
31  *
32  * Redistribution and use in source and binary forms, with or without
33  * modification, are permitted provided that the following conditions
34  * are met:
35  * 1. Redistributions of source code must retain the above copyright
36  *    notice, this list of conditions and the following disclaimer.
37  * 2. Redistributions in binary form must reproduce the above copyright
38  *    notice, this list of conditions and the following disclaimer in the
39  *    documentation and/or other materials provided with the distribution.
40  * 3. All advertising materials mentioning features or use of this software
41  *    must display the following acknowledgement:
42  *	This product includes software developed by the University of
43  *	California, Berkeley and its contributors.
44  * 4. Neither the name of the University nor the names of its contributors
45  *    may be used to endorse or promote products derived from this software
46  *    without specific prior written permission.
47  *
48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58  * SUCH DAMAGE.
59  *
60  *	@(#)ip_var.h	8.2 (Berkeley) 1/9/95
61  */
62 /*
63  * NOTICE: This file was modified by SPARTA, Inc. in 2007 to introduce
64  * support for mandatory and extensible security protections.  This notice
65  * is included in support of clause 2.2 (b) of the Apple Public License,
66  * Version 2.0.
67  */
68 
69 #ifndef _NETINET_IP_VAR_H_
70 #define _NETINET_IP_VAR_H_
71 #include <sys/appleapiopts.h>
72 
73 #include <netinet/in.h>
74 #include <sys/types.h>
75 
76 /*
77  * Overlay for ip header used by other protocols (tcp, udp).
78  */
79 struct ipovly {
80 	u_char  ih_x1[9];               /* (unused) */
81 	u_char  ih_pr;                  /* protocol */
82 	u_short ih_len;                 /* protocol length */
83 	struct  in_addr ih_src;         /* source internet address */
84 	struct  in_addr ih_dst;         /* destination internet address */
85 };
86 
87 #ifdef BSD_KERNEL_PRIVATE
88 /*
89  * Ip reassembly queue structure.  Each fragment
90  * being reassembled is attached to one of these structures.
91  * They are timed out after ipq_ttl drops to 0, and may also
92  * be reclaimed if memory becomes tight.
93  */
94 struct ipq {
95 	TAILQ_ENTRY(ipq) ipq_list;      /* to other reass headers */
96 	struct mbuf *ipq_frags;         /* to ip headers of fragments */
97 	u_char  ipq_ttl;                /* time for reass q to live */
98 	u_char  ipq_p;                  /* protocol of this fragment */
99 	u_short ipq_id;                 /* sequence id for reassembly */
100 	struct  in_addr ipq_src, ipq_dst;
101 	u_int32_t       ipq_nfrags;     /* # frags in this packet */
102 	uint32_t ipq_csum_flags;        /* checksum flags */
103 	uint32_t ipq_csum;              /* partial checksum value */
104 };
105 
106 /*
107  * Structure stored in mbuf in inpcb.ip_options
108  * and passed to ip_output when ip options are in use.
109  * The actual length of the options (including ipopt_dst)
110  * is in m_len.
111  */
112 #endif /* BSD_KERNEL_PRIVATE */
113 #define MAX_IPOPTLEN    40
114 #ifdef BSD_KERNEL_PRIVATE
115 struct ipoption {
116 	struct  in_addr ipopt_dst;      /* first-hop dst if source routed */
117 	char    ipopt_list[MAX_IPOPTLEN];       /* options proper */
118 };
119 
120 /*
121  * Structure attached to inpcb.ip_moptions and
122  * passed to ip_output when IP multicast options are in use.
123  */
124 struct ip_moptions {
125 	decl_lck_mtx_data(, imo_lock);
126 	uint32_t imo_refcnt;            /* ref count */
127 	uint32_t imo_debug;             /* see ifa_debug flags */
128 	struct  ifnet *imo_multicast_ifp; /* ifp for outgoing multicasts */
129 	u_char  imo_multicast_ttl;      /* TTL for outgoing multicasts */
130 	u_char  imo_multicast_loop;     /* 1 => hear sends if a member */
131 	u_short imo_num_memberships;    /* no. memberships this socket */
132 	u_short imo_max_memberships;    /* max memberships this socket */
133 	struct  in_multi **__counted_by(imo_max_memberships) imo_membership;
134 	/* group memberships */
135 	struct  in_mfilter *__counted_by(imo_max_memberships) imo_mfilters;
136 	/* source filters */
137 	u_int32_t imo_multicast_vif;    /* vif num outgoing multicasts */
138 	struct  in_addr imo_multicast_addr; /* ifindex/addr on MULTICAST_IF */
139 	void (*imo_trace)               /* callback fn for tracing refs */
140 	(struct ip_moptions *, int);
141 };
142 
143 #define IMO_LOCK_ASSERT_HELD(_imo)                                      \
144 	LCK_MTX_ASSERT(&(_imo)->imo_lock, LCK_MTX_ASSERT_OWNED)
145 
146 #define IMO_LOCK_ASSERT_NOTHELD(_imo)                                   \
147 	LCK_MTX_ASSERT(&(_imo)->imo_lock, LCK_MTX_ASSERT_NOTOWNED)
148 
149 #define IMO_LOCK(_imo)                                                  \
150 	lck_mtx_lock(&(_imo)->imo_lock)
151 
152 #define IMO_LOCK_SPIN(_imo)                                             \
153 	lck_mtx_lock_spin(&(_imo)->imo_lock)
154 
155 #define IMO_CONVERT_LOCK(_imo) do {                                     \
156 	IMO_LOCK_ASSERT_HELD(_imo);                                     \
157 	lck_mtx_convert_spin(&(_imo)->imo_lock);                        \
158 } while (0)
159 
160 #define IMO_UNLOCK(_imo)                                                \
161 	lck_mtx_unlock(&(_imo)->imo_lock)
162 
163 #define IMO_ADDREF(_imo)                                                \
164 	imo_addref(_imo, 0)
165 
166 #define IMO_ADDREF_LOCKED(_imo)                                         \
167 	imo_addref(_imo, 1)
168 
169 #define IMO_REMREF(_imo)                                                \
170 	imo_remref(_imo)
171 
172 /*
173  * Drop any existing memberships and source
174  * filters on _imo. The order of operations is
175  * 1. imf_leave the in_mfilter
176  * 2. in_leavegroup the meembership group
177  * 3. imf_purge the filter
178  * 4. INM_REMREF the reference on the membership group.
179  *
180  * The above calls assume valid input; consequently those
181  * are predicated by checking that the membership and
182  * the filter pointers (imn and imf, correspondingly)
183  * are valid.
184  */
185 #define IMO_PURGE_LOCKED(_imo) do {                                 \
186 	IMO_LOCK_ASSERT_HELD((_imo));                                   \
187 	for (int i = 0; i < (_imo)->imo_num_memberships; ++i) {         \
188 	        struct in_mfilter *imf;                                 \
189 	        struct in_multi   *imn;                                 \
190 	        imf = (_imo)->imo_mfilters != NULL                      \
191 	            ? &(_imo)->imo_mfilters[i]                          \
192 	            : NULL;                                             \
193 	        if (imf != NULL) {                                      \
194 	            imf_leave(imf);                                     \
195 	        }                                                       \
196 	        imn = (_imo)->imo_membership[i];                        \
197 	        (_imo)->imo_membership[i] = NULL;                       \
198 	        if (imn != NULL) {                                      \
199 	            (void) in_leavegroup(imn, imf);                     \
200 	        }                                                       \
201 	        if (imf != NULL) {                                      \
202 	            imf_purge(imf);                                     \
203 	        }                                                       \
204 	                if (imn != NULL) {                              \
205 	            INM_REMREF(imn);                                    \
206 	        }                                                       \
207 	}                                                               \
208 	(_imo)->imo_num_memberships = 0;                                \
209 } while (0)
210 
211 /* mbuf tag for ip_forwarding info */
212 struct ip_fwd_tag {
213 	struct sockaddr_in *next_hop;   /* next_hop */
214 };
215 #endif /* BSD_KERNEL_PRIVATE */
216 
217 struct  ipstat {
218 	u_int32_t ips_total;            /* total packets received */
219 	u_int32_t ips_badsum;           /* checksum bad */
220 	u_int32_t ips_tooshort;         /* packet too short */
221 	u_int32_t ips_toosmall;         /* not enough data */
222 	u_int32_t ips_badhlen;          /* ip header length < data size */
223 	u_int32_t ips_badlen;           /* ip length < ip header length */
224 	u_int32_t ips_fragments;        /* fragments received */
225 	u_int32_t ips_fragdropped;      /* frags dropped (dups, out of space) */
226 	u_int32_t ips_fragtimeout;      /* fragments timed out */
227 	u_int32_t ips_forward;          /* packets forwarded */
228 	u_int32_t ips_fastforward;      /* packets fast forwarded */
229 	u_int32_t ips_cantforward;      /* packets rcvd for unreachable dest */
230 	u_int32_t ips_redirectsent;     /* packets forwarded on same net */
231 	u_int32_t ips_noproto;          /* unknown or unsupported protocol */
232 	u_int32_t ips_delivered;        /* datagrams delivered to upper level */
233 	u_int32_t ips_localout;         /* total ip packets generated here */
234 	u_int32_t ips_odropped;         /* lost packets due to nobufs, etc. */
235 	u_int32_t ips_reassembled;      /* total packets reassembled ok */
236 	u_int32_t ips_fragmented;       /* datagrams successfully fragmented */
237 	u_int32_t ips_ofragments;       /* output fragments created */
238 	u_int32_t ips_cantfrag;         /* don't fragment flag was set, etc. */
239 	u_int32_t ips_badoptions;       /* error in option processing */
240 	u_int32_t ips_noroute;          /* packets discarded due to no route */
241 	u_int32_t ips_badvers;          /* ip version != 4 */
242 	u_int32_t ips_rawout;           /* total raw ip packets generated */
243 	u_int32_t ips_toolong;          /* ip length > max ip packet size */
244 	u_int32_t ips_notmember;        /* multicasts for unregistered grps */
245 	u_int32_t ips_nogif;            /* no match gif found */
246 	u_int32_t ips_badaddr;          /* invalid address on header */
247 	u_int32_t ips_pktdropcntrl;     /* pkt dropped, no mbufs for ctl data */
248 	u_int32_t ips_rcv_swcsum;       /* ip hdr swcksum (inbound), packets */
249 	u_int32_t ips_rcv_swcsum_bytes; /* ip hdr swcksum (inbound), bytes */
250 	u_int32_t ips_snd_swcsum;       /* ip hdr swcksum (outbound), packets */
251 	u_int32_t ips_snd_swcsum_bytes; /* ip hdr swcksum (outbound), bytes */
252 	u_int32_t ips_adj;              /* total packets trimmed/adjusted */
253 	u_int32_t ips_adj_hwcsum_clr;   /* hwcksum discarded during adj */
254 	u_int32_t ips_rxc_collisions;   /* rx chaining collisions */
255 	u_int32_t ips_rxc_chained;      /* rx chains */
256 	u_int32_t ips_rxc_notchain;     /* rx bypassed chaining */
257 	u_int32_t ips_rxc_chainsz_gt2;  /* rx chain size greater than 2 */
258 	u_int32_t ips_rxc_chainsz_gt4;  /* rx chain size greater than 4 */
259 	u_int32_t ips_rxc_notlist;      /* count of pkts through ip_input */
260 	u_int32_t ips_raw_sappend_fail; /* sock append failed */
261 	u_int32_t ips_necp_policy_drop; /* NECP policy related drop */
262 	u_int32_t ips_rcv_if_weak_match; /* packets whose receive interface that passed the Weak ES address check */
263 	u_int32_t ips_rcv_if_no_match;  /* packets whose receive interface did not pass the address check */
264 };
265 
266 struct ip_linklocal_stat {
267 	u_int32_t       iplls_in_total;
268 	u_int32_t       iplls_in_badttl;
269 	u_int32_t       iplls_out_total;
270 	u_int32_t       iplls_out_badttl;
271 };
272 
273 #ifdef KERNEL_PRIVATE
274 /* forward declarations for ip_output() */
275 struct ip_out_args;
276 struct ip_moptions;
277 #endif /* KERNEL_PRIVATE */
278 
279 #ifdef BSD_KERNEL_PRIVATE
280 /* flags passed to ip_output as last parameter */
281 #define IP_FORWARDING   0x1             /* most of ip header exists */
282 #define IP_RAWOUTPUT    0x2             /* raw ip header exists */
283 #define IP_NOIPSEC      0x4             /* No IPsec processing */
284 #define IP_ROUTETOIF    SO_DONTROUTE    /* bypass routing tables (0x0010) */
285 #define IP_ALLOWBROADCAST SO_BROADCAST  /* can send broadcast pkts (0x0020) */
286 #define IP_OUTARGS      0x100           /* has ancillary output info */
287 
288 #define IP_HDR_ALIGNED_P(_ip)   ((((uintptr_t)(_ip)) & ((uintptr_t)3)) == 0)
289 #define IP_OFF_IS_ATOMIC(_ip_off) ((_ip_off & (IP_DF | IP_MF | IP_OFFMASK)) == IP_DF)
290 
291 /*
292  * On platforms which require strict alignment (currently for anything but
293  * i386 or x86_64 or arm64), this macro checks whether the pointer to the IP header
294  * is 32-bit aligned, and assert otherwise.
295  */
296 #if defined(__i386__) || defined(__x86_64__) || defined(__arm64__)
297 #define IP_HDR_STRICT_ALIGNMENT_CHECK(_ip) do { } while (0)
298 #else /* !__i386__ && !__x86_64__ && !__arm64__ */
299 #define IP_HDR_STRICT_ALIGNMENT_CHECK(_ip) do {                         \
300 	if (!IP_HDR_ALIGNED_P(_ip)) {                                   \
301 	        panic_plain("\n%s: Unaligned IP header %p\n",           \
302 	            __func__, _ip);                                     \
303 	}                                                               \
304 } while (0)
305 #endif /* !__i386__ && !__x86_64__ && !__arm64__ */
306 
307 struct ip;
308 struct inpcb;
309 struct route;
310 struct sockopt;
311 
312 #include <kern/zalloc.h>
313 #include <net/flowadv.h>
314 
315 /*
316  * Extra information passed to ip_output when IP_OUTARGS is set.
317  *
318  * Upon returning an error to the caller, ip_output may indicate through
319  * ipoa_flags any additional information regarding the error.
320  */
321 struct ip_out_args {
322 	unsigned int    ipoa_boundif;   /* boundif interface index */
323 	struct flowadv  ipoa_flowadv;   /* flow advisory code */
324 	u_int32_t       ipoa_flags;     /* IPOAF output flags (see below) */
325 #define IPOAF_SELECT_SRCIF              0x00000001      /* src interface selection */
326 #define IPOAF_BOUND_IF                  0x00000002      /* boundif value is valid */
327 #define IPOAF_BOUND_SRCADDR             0x00000004      /* bound to src address */
328 #define IPOAF_NO_CELLULAR               0x00000010      /* skip IFT_CELLULAR */
329 #define IPOAF_NO_EXPENSIVE              0x00000020      /* skip IFT_EXPENSIVE */
330 #define IPOAF_AWDL_UNRESTRICTED         0x00000040      /* can send over
331 	                                                 *  AWDL_RESTRICTED */
332 #define IPOAF_QOSMARKING_ALLOWED        0x00000080      /* policy allows Fastlane DSCP marking */
333 #define IPOAF_NO_CONSTRAINED            0x00000400      /* skip IFXF_CONSTRAINED */
334 #define IPOAF_REDO_QOSMARKING_POLICY    0x00002000      /* Re-evaluate QOS marking policy */
335 #define IPOAF_R_IFDENIED                0x00004000      /* denied access to interface */
336 #define IPOAF_MANAGEMENT_ALLOWED        0x00008000      /* access to management interfaces */
337 	int             ipoa_sotc;      /* traffic class for Fastlane DSCP mapping */
338 	int             ipoa_netsvctype; /* network service type */
339 	int32_t         qos_marking_gencount;
340 };
341 
342 #define IPOAF_RET_MASK (IPOAF_R_IFDENIED)
343 
344 extern struct ipstat ipstat;
345 extern int ip_use_randomid;
346 extern u_short ip_id;                   /* ip packet ctr, for ids */
347 extern int ip_defttl;                   /* default IP ttl */
348 extern int ipforwarding;                /* ip forwarding */
349 extern int rfc6864;
350 extern struct protosw *ip_protox[];
351 extern struct pr_usrreqs rip_usrreqs;
352 
353 extern void ip_moptions_init(void);
354 extern struct ip_moptions *ip_allocmoptions(zalloc_flags_t);
355 extern int inp_getmoptions(struct inpcb *, struct sockopt *);
356 extern int inp_setmoptions(struct inpcb *, struct sockopt *);
357 extern void imo_addref(struct ip_moptions *, int);
358 extern void imo_remref(struct ip_moptions *);
359 
360 struct protosw;
361 struct domain;
362 
363 extern int ip_checkrouteralert(struct mbuf *);
364 extern int ip_ctloutput(struct socket *, struct sockopt *sopt);
365 extern void ip_drain(void);
366 extern void ip_init(struct protosw *, struct domain *);
367 extern int ip_output(struct mbuf *, struct mbuf *, struct route *, int,
368     struct ip_moptions *, struct ip_out_args *);
369 extern int ip_output_list(struct mbuf *, int, struct mbuf *, struct route *,
370     int, struct ip_moptions *, struct ip_out_args *);
371 extern void ip_output_checksum(struct ifnet *, struct mbuf *, int, int,
372     uint32_t *);
373 extern struct in_ifaddr *ip_rtaddr(struct in_addr);
374 extern int ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
375     struct mbuf *);
376 extern struct mbuf *ip_srcroute(void);
377 extern void  ip_stripoptions(struct mbuf *);
378 extern u_int16_t ip_randomid(uint64_t);
379 extern int ip_fragment(struct mbuf *, struct ifnet *, uint32_t, int);
380 
381 extern void ip_setsrcifaddr_info(struct mbuf *, uint16_t, struct in_ifaddr *);
382 extern void ip_setdstifaddr_info(struct mbuf *, uint16_t, struct in_ifaddr *);
383 extern int ip_getsrcifaddr_info(struct mbuf *, uint32_t *, uint32_t *);
384 extern int ip_getdstifaddr_info(struct mbuf *, uint32_t *, uint32_t *);
385 
386 extern int rip_ctloutput(struct socket *, struct sockopt *);
387 extern void rip_ctlinput(int, struct sockaddr *, void *, struct ifnet *);
388 extern void rip_init(struct protosw *, struct domain *);
389 extern void rip_input(struct mbuf *, int);
390 extern int rip_output(struct mbuf *, struct socket *, u_int32_t, struct mbuf *);
391 extern int rip_unlock(struct socket *, int, void *);
392 extern int rip_send(struct socket *, int, struct mbuf *, struct sockaddr *,
393     struct mbuf *, struct proc *);
394 
395 extern void tcp_in_cksum_stats(u_int32_t);
396 extern void tcp_out_cksum_stats(u_int32_t);
397 
398 extern void udp_in_cksum_stats(u_int32_t);
399 extern void udp_out_cksum_stats(u_int32_t);
400 
401 extern void tcp_in6_cksum_stats(u_int32_t);
402 extern void tcp_out6_cksum_stats(u_int32_t);
403 
404 extern void udp_in6_cksum_stats(u_int32_t);
405 extern void udp_out6_cksum_stats(u_int32_t);
406 #endif /* BSD_KERNEL_PRIVATE */
407 #ifdef KERNEL_PRIVATE
408 /* for PPP/PPTP */
409 extern int ip_gre_output(struct mbuf *);
410 typedef struct mbuf *(*gre_input_func_t)(struct mbuf *, int, int);
411 extern int ip_gre_register_input(gre_input_func_t);
412 #endif /* KERNEL_PRIVATE */
413 #endif /* !_NETINET_IP_VAR_H_ */
414