xref: /xnu-11417.140.69/bsd/netinet/in_proto.c (revision 43a90889846e00bfb5cf1d255cdc0a701a1e05a4)
1 /*
2  * Copyright (c) 2000-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  * 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  *	@(#)in_proto.c	8.2 (Berkeley) 2/9/95
61  */
62 
63 #include <sys/param.h>
64 #include <sys/kernel.h>
65 #include <sys/socket.h>
66 #include <sys/domain.h>
67 #include <sys/protosw.h>
68 #include <sys/queue.h>
69 #include <sys/sysctl.h>
70 #include <sys/mbuf.h>
71 
72 #include <kern/debug.h>
73 
74 #include <net/if.h>
75 #include <net/route.h>
76 #include <net/kpi_protocol.h>
77 
78 #include <netinet/in.h>
79 #include <netinet/in_var.h>
80 #include <netinet/in_systm.h>
81 #include <netinet/ip.h>
82 #include <netinet/ip_var.h>
83 #include <netinet/ip_icmp.h>
84 #include <netinet/igmp_var.h>
85 #include <netinet/tcp.h>
86 #include <netinet/tcp_timer.h>
87 #include <netinet/tcp_var.h>
88 #include <netinet/tcpip.h>
89 #include <netinet/udp.h>
90 #include <netinet/udp_var.h>
91 #include <netinet/ip_encap.h>
92 
93 /*
94  * TCP/IP protocol family: IP, ICMP, UDP, TCP.
95  */
96 
97 #if IPSEC
98 #include <netinet6/ipsec.h>
99 #include <netinet6/ah.h>
100 #if IPSEC_ESP
101 #include <netinet6/esp.h>
102 #endif
103 #endif /* IPSEC */
104 
105 static void in_dinit(struct domain *);
106 static void ip_proto_input(protocol_family_t, mbuf_t);
107 
108 extern struct domain inetdomain_s;
109 static struct pr_usrreqs nousrreqs;
110 extern struct pr_usrreqs icmp_dgram_usrreqs;
111 extern int icmp_dgram_ctloutput(struct socket *, struct sockopt *);
112 
113 struct domain *inetdomain = NULL;
114 
115 /* Thanks to PPP, this still needs to be exported */
116 lck_mtx_t       *inet_domain_mutex;
117 
118 static struct protosw inetsw[] = {
119 	{
120 		.pr_type =              0,
121 		.pr_protocol =          0,
122 		.pr_init =              ip_init,
123 		.pr_drain =             ip_drain,
124 		.pr_usrreqs =           &nousrreqs,
125 	},
126 	{
127 		.pr_type =              SOCK_DGRAM,
128 		.pr_protocol =          IPPROTO_UDP,
129 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_PROTOLOCK | PR_PCBLOCK |
130     PR_EVCONNINFO | PR_PRECONN_WRITE,
131 		.pr_input =             udp_input,
132 		.pr_ctlinput =          udp_ctlinput,
133 		.pr_ctloutput =         udp_ctloutput,
134 		.pr_init =              udp_init,
135 		.pr_usrreqs =           &udp_usrreqs,
136 		.pr_lock =              udp_lock,
137 		.pr_unlock =            udp_unlock,
138 		.pr_getlock =           udp_getlock,
139 		.pr_update_last_owner = inp_update_last_owner,
140 		.pr_copy_last_owner =   inp_copy_last_owner,
141 	},
142 	{
143 		.pr_type =              SOCK_STREAM,
144 		.pr_protocol =          IPPROTO_TCP,
145 		.pr_flags =             PR_CONNREQUIRED | PR_WANTRCVD | PR_PCBLOCK |
146     PR_PROTOLOCK | PR_DISPOSE | PR_EVCONNINFO |
147     PR_PRECONN_WRITE | PR_DATA_IDEMPOTENT,
148 		.pr_input =             tcp_input,
149 		.pr_ctlinput =          tcp_ctlinput,
150 		.pr_ctloutput =         tcp_ctloutput,
151 		.pr_init =              tcp_init,
152 		.pr_drain =             tcp_drain,
153 		.pr_usrreqs =           &tcp_usrreqs,
154 		.pr_lock =              tcp_lock,
155 		.pr_unlock =            tcp_unlock,
156 		.pr_getlock =           tcp_getlock,
157 		.pr_update_last_owner = inp_update_last_owner,
158 		.pr_copy_last_owner =   inp_copy_last_owner,
159 	},
160 	{
161 		.pr_type =              SOCK_RAW,
162 		.pr_protocol =          IPPROTO_RAW,
163 		.pr_flags =             PR_ATOMIC | PR_ADDR,
164 		.pr_input =             rip_input,
165 		.pr_ctlinput =          rip_ctlinput,
166 		.pr_ctloutput =         rip_ctloutput,
167 		.pr_usrreqs =           &rip_usrreqs,
168 		.pr_unlock =            rip_unlock,
169 		.pr_update_last_owner = inp_update_last_owner,
170 		.pr_copy_last_owner =   inp_copy_last_owner,
171 	},
172 	{
173 		.pr_type =              SOCK_RAW,
174 		.pr_protocol =          IPPROTO_ICMP,
175 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
176 		.pr_input =             icmp_input,
177 		.pr_ctloutput =         rip_ctloutput,
178 		.pr_usrreqs =           &rip_usrreqs,
179 		.pr_unlock =            rip_unlock,
180 		.pr_update_last_owner = inp_update_last_owner,
181 		.pr_copy_last_owner =   inp_copy_last_owner,
182 	},
183 	{
184 		.pr_type =              SOCK_DGRAM,
185 		.pr_protocol =          IPPROTO_ICMP,
186 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
187 		.pr_input =             icmp_input,
188 		.pr_ctloutput =         icmp_dgram_ctloutput,
189 		.pr_usrreqs =           &icmp_dgram_usrreqs,
190 		.pr_unlock =            rip_unlock,
191 		.pr_update_last_owner = inp_update_last_owner,
192 		.pr_copy_last_owner =   inp_copy_last_owner,
193 	},
194 	{
195 		.pr_type =              SOCK_RAW,
196 		.pr_protocol =          IPPROTO_IGMP,
197 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
198 		.pr_input =             igmp_input,
199 		.pr_ctloutput =         rip_ctloutput,
200 		.pr_init =              igmp_init,
201 		.pr_usrreqs =           &rip_usrreqs,
202 		.pr_unlock =            rip_unlock,
203 		.pr_update_last_owner = inp_update_last_owner,
204 		.pr_copy_last_owner =   inp_copy_last_owner,
205 	},
206 	{
207 		.pr_type =              SOCK_RAW,
208 		.pr_protocol =          IPPROTO_GRE,
209 		.pr_flags =             PR_ATOMIC | PR_ADDR,
210 		.pr_input =             gre_input,
211 		.pr_ctlinput =          rip_ctlinput,
212 		.pr_ctloutput =         rip_ctloutput,
213 		.pr_usrreqs =           &rip_usrreqs,
214 		.pr_unlock =            rip_unlock,
215 		.pr_update_last_owner = inp_update_last_owner,
216 		.pr_copy_last_owner =   inp_copy_last_owner,
217 	},
218 #if IPSEC
219 	{
220 		.pr_type =              SOCK_RAW,
221 		.pr_protocol =          IPPROTO_AH,
222 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_PROTOLOCK,
223 		.pr_input =             ah4_input,
224 		.pr_usrreqs =           &nousrreqs,
225 	},
226 #if IPSEC_ESP
227 	{
228 		.pr_type =              SOCK_RAW,
229 		.pr_protocol =          IPPROTO_ESP,
230 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_PROTOLOCK,
231 		.pr_input =             esp4_input,
232 		.pr_usrreqs =           &nousrreqs,
233 	},
234 #endif /* IPSEC_ESP */
235 #endif /* IPSEC */
236 	{
237 		.pr_type =              SOCK_RAW,
238 		.pr_protocol =          IPPROTO_IPV4,
239 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
240 		.pr_input =             encap4_input,
241 		.pr_ctloutput =         rip_ctloutput,
242 		.pr_usrreqs =           &rip_usrreqs,
243 		.pr_unlock =            rip_unlock,
244 		.pr_update_last_owner = inp_update_last_owner,
245 		.pr_copy_last_owner =   inp_copy_last_owner,
246 	},
247 	{
248 		.pr_type =              SOCK_RAW,
249 		.pr_protocol =          IPPROTO_IPV6,
250 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
251 		.pr_input =             encap4_input,
252 		.pr_ctloutput =         rip_ctloutput,
253 		.pr_usrreqs =           &rip_usrreqs,
254 		.pr_unlock =            rip_unlock,
255 		.pr_update_last_owner = inp_update_last_owner,
256 		.pr_copy_last_owner =   inp_copy_last_owner,
257 	},
258 /* raw wildcard */
259 	{
260 		.pr_type =              SOCK_RAW,
261 		.pr_flags =             PR_ATOMIC | PR_ADDR | PR_LASTHDR,
262 		.pr_input =             rip_input,
263 		.pr_ctloutput =         rip_ctloutput,
264 		.pr_init =              rip_init,
265 		.pr_usrreqs =           &rip_usrreqs,
266 		.pr_unlock =            rip_unlock,
267 		.pr_update_last_owner = inp_update_last_owner,
268 		.pr_copy_last_owner =   inp_copy_last_owner,
269 	},
270 };
271 
272 static int in_proto_count = (sizeof(inetsw) / sizeof(struct protosw));
273 
274 struct domain inetdomain_s = {
275 	.dom_family =           PF_INET,
276 	.dom_flags =            DOM_REENTRANT,
277 	.dom_name =             "internet",
278 	.dom_init =             in_dinit,
279 	.dom_rtattach =         in_inithead,
280 	.dom_rtoffset =         32,
281 	.dom_maxrtkey =         sizeof(struct sockaddr_in),
282 	.dom_protohdrlen =      sizeof(struct tcpiphdr),
283 };
284 
285 /* Initialize the PF_INET domain, and add in the pre-defined protos */
286 void
in_dinit(struct domain * dp)287 in_dinit(struct domain *dp)
288 {
289 	struct protosw *pr;
290 	int i;
291 	domain_unguard_t __single unguard;
292 
293 	VERIFY(!(dp->dom_flags & DOM_INITIALIZED));
294 	VERIFY(inetdomain == NULL);
295 
296 	inetdomain = dp;
297 
298 	/*
299 	 * Verify that the maximum possible tcp/ip header will still
300 	 * fit in a small mbuf because m_pullup only puls into 256
301 	 * byte mbuf
302 	 */
303 	_CASSERT((sizeof(struct tcpiphdr) + TCP_MAXOLEN) <= _MHLEN);
304 
305 	/*
306 	 * Attach first, then initialize; ip_init() needs raw IP handler.
307 	 */
308 	for (i = 0, pr = &inetsw[0]; i < in_proto_count; i++, pr++) {
309 		net_add_proto(pr, dp, 0);
310 	}
311 	for (i = 0, pr = &inetsw[0]; i < in_proto_count; i++, pr++) {
312 		net_init_proto(pr, dp);
313 	}
314 
315 	inet_domain_mutex = dp->dom_mtx;
316 
317 	unguard = domain_unguard_deploy();
318 	i = proto_register_input(PF_INET, ip_proto_input, NULL, 1);
319 	if (i != 0) {
320 		panic("%s: failed to register PF_INET protocol: %d",
321 		    __func__, i);
322 		/* NOTREACHED */
323 	}
324 	domain_unguard_release(unguard);
325 }
326 
327 static void
ip_proto_input(protocol_family_t protocol,mbuf_t packet_list)328 ip_proto_input(protocol_family_t protocol, mbuf_t packet_list)
329 {
330 #pragma unused(protocol)
331 
332 	if (packet_list->m_nextpkt != NULL) {
333 		ip_input_process_list(packet_list);
334 	} else {
335 		/*
336 		 * XXX remove this path if ip_input_process_list is proven
337 		 * to be stable and has minimum overhead on most platforms.
338 		 */
339 		ip_input(packet_list);
340 	}
341 }
342 
343 SYSCTL_NODE(_net, PF_INET, inet,
344     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "Internet Family");
345 
346 SYSCTL_NODE(_net_inet, IPPROTO_IP, ip,
347     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "IP");
348 SYSCTL_NODE(_net_inet, IPPROTO_ICMP, icmp,
349     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "ICMP");
350 SYSCTL_NODE(_net_inet, IPPROTO_UDP, udp,
351     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "UDP");
352 SYSCTL_NODE(_net_inet, IPPROTO_TCP, tcp,
353     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "TCP");
354 SYSCTL_NODE(_net_inet, IPPROTO_IGMP, igmp,
355     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "IGMP");
356 #if IPSEC
357 SYSCTL_NODE(_net_inet, IPPROTO_AH, ipsec,
358     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "IPSEC");
359 #endif /* IPSEC */
360 SYSCTL_NODE(_net_inet, IPPROTO_RAW, raw,
361     CTLFLAG_RW | CTLFLAG_LOCKED, 0, "RAW");
362