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