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