1/* $NetBSD: in_proto.c,v 1.131 2022/09/03 02:53:18 thorpej Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32/* 33 * Copyright (c) 1982, 1986, 1993 34 * The Regents of the University of California. All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. 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/cdefs.h> 64__KERNEL_RCSID(0, "$NetBSD: in_proto.c,v 1.131 2022/09/03 02:53:18 thorpej Exp $"); 65 66#ifdef _KERNEL_OPT 67#include "opt_mrouting.h" 68#include "opt_inet.h" 69#include "opt_ipsec.h" 70#include "opt_pim.h" 71#include "opt_gateway.h" 72#include "opt_dccp.h" 73#include "opt_sctp.h" 74#include "opt_compat_netbsd.h" 75#include "opt_net_mpsafe.h" 76#endif 77 78#include <sys/param.h> 79#include <sys/socket.h> 80#include <sys/protosw.h> 81#include <sys/domain.h> 82#include <sys/mbuf.h> 83 84#include <net/if.h> 85 86#include <netinet/in.h> 87#include <netinet/in_systm.h> 88#include <netinet/in_var.h> 89#include <netinet/ip.h> 90#include <netinet/ip_var.h> 91#include <netinet/ip_icmp.h> 92#include <netinet/in_ifattach.h> 93#include <netinet/in_pcb.h> 94#include <netinet/in_proto.h> 95 96#ifdef INET6 97#ifndef INET 98#include <netinet/in.h> 99#endif 100#include <netinet/ip6.h> 101#endif 102 103#include <netinet/igmp_var.h> 104#ifdef PIM 105#include <netinet/pim_var.h> 106#endif 107#include <netinet/tcp.h> 108#include <netinet/tcp_fsm.h> 109#include <netinet/tcp_seq.h> 110#include <netinet/tcp_timer.h> 111#include <netinet/tcp_var.h> 112#include <netinet/tcp_debug.h> 113#include <netinet/udp.h> 114#include <netinet/udp_var.h> 115#include <netinet/ip_encap.h> 116 117#ifdef DCCP 118#include <netinet/dccp.h> 119#include <netinet/dccp_var.h> 120#endif 121 122#ifdef SCTP 123#include <netinet/sctp.h> 124#include <netinet/sctp_var.h> 125#endif 126 127/* 128 * TCP/IP protocol family: IP, ICMP, UDP, TCP. 129 */ 130 131#ifdef IPSEC 132#include <netipsec/ipsec.h> 133#include <netipsec/key.h> 134#endif /* IPSEC */ 135 136#include "carp.h" 137#if NCARP > 0 138#include <netinet/ip_carp.h> 139#endif 140 141#include "pfsync.h" 142#if NPFSYNC > 0 143#include <net/pfvar.h> 144#include <net/if_pfsync.h> 145#endif 146 147DOMAIN_DEFINE(inetdomain); /* forward declare and add to link set */ 148 149/* Wrappers to acquire kernel_lock. */ 150 151PR_WRAP_CTLINPUT(rip_ctlinput) 152PR_WRAP_CTLINPUT(udp_ctlinput) 153PR_WRAP_CTLINPUT(tcp_ctlinput) 154 155#define rip_ctlinput rip_ctlinput_wrapper 156#define udp_ctlinput udp_ctlinput_wrapper 157#define tcp_ctlinput tcp_ctlinput_wrapper 158 159PR_WRAP_CTLOUTPUT(rip_ctloutput) 160PR_WRAP_CTLOUTPUT(udp_ctloutput) 161PR_WRAP_CTLOUTPUT(tcp_ctloutput) 162 163#define rip_ctloutput rip_ctloutput_wrapper 164#define udp_ctloutput udp_ctloutput_wrapper 165#define tcp_ctloutput tcp_ctloutput_wrapper 166 167#ifdef DCCP 168PR_WRAP_CTLINPUT(dccp_ctlinput) 169PR_WRAP_CTLOUTPUT(dccp_ctloutput) 170 171#define dccp_ctlinput dccp_ctlinput_wrapper 172#define dccp_ctloutput dccp_ctloutput_wrapper 173#endif 174 175#ifdef SCTP 176PR_WRAP_CTLINPUT(sctp_ctlinput) 177PR_WRAP_CTLOUTPUT(sctp_ctloutput) 178 179#define sctp_ctlinput sctp_ctlinput_wrapper 180#define sctp_ctloutput sctp_ctloutput_wrapper 181#endif 182 183#ifdef NET_MPSAFE 184PR_WRAP_INPUT(udp_input) 185PR_WRAP_INPUT(tcp_input) 186#ifdef DCCP 187PR_WRAP_INPUT(dccp_input) 188#endif 189#ifdef SCTP 190PR_WRAP_INPUT(sctp_input) 191#endif 192PR_WRAP_INPUT(rip_input) 193#if NPFSYNC > 0 194PR_WRAP_INPUT(pfsync_input) 195#endif 196PR_WRAP_INPUT(igmp_input) 197#ifdef PIM 198PR_WRAP_INPUT(pim_input) 199#endif 200 201#define udp_input udp_input_wrapper 202#define tcp_input tcp_input_wrapper 203#define dccp_input dccp_input_wrapper 204#define sctp_input sctp_input_wrapper 205#define rip_input rip_input_wrapper 206#define pfsync_input pfsync_input_wrapper 207#define igmp_input igmp_input_wrapper 208#define pim_input pim_input_wrapper 209#endif 210 211#if defined(IPSEC) 212 213#ifdef IPSEC_RUMPKERNEL 214/* 215 * .pr_input = ipsec4_common_input won't be resolved on loading 216 * the ipsec shared library. We need a wrapper anyway. 217 */ 218static void 219ipsec4_common_input_wrapper(struct mbuf *m, int off, int proto) 220{ 221 222 if (ipsec_enabled) { 223 ipsec4_common_input(m, off, proto); 224 } else { 225 m_freem(m); 226 } 227} 228#define ipsec4_common_input ipsec4_common_input_wrapper 229 230/* The ctlinput functions may not be loaded */ 231#define IPSEC_WRAP_CTLINPUT(name) \ 232static void * \ 233name##_wrapper(int a, const struct sockaddr *b, void *c)\ 234{ \ 235 void *rv; \ 236 KERNEL_LOCK(1, NULL); \ 237 if (ipsec_enabled) \ 238 rv = name(a, b, c); \ 239 else \ 240 rv = NULL; \ 241 KERNEL_UNLOCK_ONE(NULL); \ 242 return rv; \ 243} 244IPSEC_WRAP_CTLINPUT(ah4_ctlinput) 245IPSEC_WRAP_CTLINPUT(esp4_ctlinput) 246 247#else /* !IPSEC_RUMPKERNEL */ 248 249PR_WRAP_CTLINPUT(ah4_ctlinput) 250PR_WRAP_CTLINPUT(esp4_ctlinput) 251 252#endif /* !IPSEC_RUMPKERNEL */ 253 254#define ah4_ctlinput ah4_ctlinput_wrapper 255#define esp4_ctlinput esp4_ctlinput_wrapper 256 257#endif /* IPSEC */ 258 259const struct protosw inetsw[] = { 260{ .pr_domain = &inetdomain, 261 .pr_init = ip_init, 262 .pr_fasttimo = ip_fasttimo, 263 .pr_slowtimo = ip_slowtimo, 264 .pr_drain = ip_drainstub, 265}, 266{ .pr_type = SOCK_RAW, 267 .pr_domain = &inetdomain, 268 .pr_protocol = IPPROTO_ICMP, 269 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 270 .pr_input = icmp_input, 271 .pr_ctlinput = rip_ctlinput, 272 .pr_ctloutput = rip_ctloutput, 273 .pr_usrreqs = &rip_usrreqs, 274 .pr_init = icmp_init, 275}, 276{ .pr_type = SOCK_DGRAM, 277 .pr_domain = &inetdomain, 278 .pr_protocol = IPPROTO_UDP, 279 .pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF, 280 .pr_input = udp_input, 281 .pr_ctlinput = udp_ctlinput, 282 .pr_ctloutput = udp_ctloutput, 283 .pr_usrreqs = &udp_usrreqs, 284 .pr_init = udp_init, 285}, 286{ .pr_type = SOCK_STREAM, 287 .pr_domain = &inetdomain, 288 .pr_protocol = IPPROTO_TCP, 289 .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_LISTEN|PR_ABRTACPTDIS|PR_PURGEIF, 290 .pr_input = tcp_input, 291 .pr_ctlinput = tcp_ctlinput, 292 .pr_ctloutput = tcp_ctloutput, 293 .pr_usrreqs = &tcp_usrreqs, 294 .pr_init = tcp_init, 295 .pr_fasttimo = tcp_fasttimo, 296 .pr_drain = tcp_drainstub, 297}, 298#ifdef DCCP 299{ .pr_type = SOCK_CONN_DGRAM, 300 .pr_domain = &inetdomain, 301 .pr_protocol = IPPROTO_DCCP, 302 .pr_flags = PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC|PR_LISTEN|PR_ABRTACPTDIS, 303 .pr_input = dccp_input, 304 .pr_ctlinput = dccp_ctlinput, 305 .pr_ctloutput = dccp_ctloutput, 306 .pr_usrreqs = &dccp_usrreqs, 307 .pr_init = dccp_init, 308}, 309#endif 310#ifdef SCTP 311{ .pr_type = SOCK_DGRAM, 312 .pr_domain = &inetdomain, 313 .pr_protocol = IPPROTO_SCTP, 314 .pr_flags = PR_ADDR_OPT|PR_WANTRCVD, 315 .pr_input = sctp_input, 316 .pr_ctlinput = sctp_ctlinput, 317 .pr_ctloutput = sctp_ctloutput, 318 .pr_usrreqs = &sctp_usrreqs, 319 .pr_init = sctp_init, 320 .pr_drain = sctp_drain 321}, 322{ .pr_type = SOCK_SEQPACKET, 323 .pr_domain = &inetdomain, 324 .pr_protocol = IPPROTO_SCTP, 325 .pr_flags = PR_ADDR_OPT|PR_WANTRCVD, 326 .pr_input = sctp_input, 327 .pr_ctlinput = sctp_ctlinput, 328 .pr_ctloutput = sctp_ctloutput, 329 .pr_usrreqs = &sctp_usrreqs, 330 .pr_drain = sctp_drain 331}, 332{ .pr_type = SOCK_STREAM, 333 .pr_domain = &inetdomain, 334 .pr_protocol = IPPROTO_SCTP, 335 .pr_flags = PR_CONNREQUIRED|PR_ADDR_OPT|PR_WANTRCVD|PR_LISTEN, 336 .pr_input = sctp_input, 337 .pr_ctlinput = sctp_ctlinput, 338 .pr_ctloutput = sctp_ctloutput, 339 .pr_usrreqs = &sctp_usrreqs, 340 .pr_drain = sctp_drain 341}, 342#endif /* SCTP */ 343{ .pr_type = SOCK_RAW, 344 .pr_domain = &inetdomain, 345 .pr_protocol = IPPROTO_RAW, 346 .pr_flags = PR_ATOMIC|PR_ADDR|PR_PURGEIF, 347 .pr_input = rip_input, 348 .pr_ctlinput = rip_ctlinput, 349 .pr_ctloutput = rip_ctloutput, 350 .pr_usrreqs = &rip_usrreqs, 351}, 352#ifdef GATEWAY 353{ .pr_domain = &inetdomain, 354 .pr_protocol = IPPROTO_IP, 355 .pr_slowtimo = ipflow_slowtimo, 356 .pr_init = ipflow_poolinit, 357}, 358#endif /* GATEWAY */ 359#ifdef IPSEC 360{ .pr_type = SOCK_RAW, 361 .pr_domain = &inetdomain, 362 .pr_protocol = IPPROTO_AH, 363 .pr_flags = PR_ATOMIC|PR_ADDR, 364 .pr_input = ipsec4_common_input, 365 .pr_ctlinput = ah4_ctlinput, 366}, 367{ .pr_type = SOCK_RAW, 368 .pr_domain = &inetdomain, 369 .pr_protocol = IPPROTO_ESP, 370 .pr_flags = PR_ATOMIC|PR_ADDR, 371 .pr_input = ipsec4_common_input, 372 .pr_ctlinput = esp4_ctlinput, 373}, 374{ .pr_type = SOCK_RAW, 375 .pr_domain = &inetdomain, 376 .pr_protocol = IPPROTO_IPCOMP, 377 .pr_flags = PR_ATOMIC|PR_ADDR, 378 .pr_input = ipsec4_common_input, 379}, 380#endif /* IPSEC */ 381{ .pr_type = SOCK_RAW, 382 .pr_domain = &inetdomain, 383 .pr_protocol = IPPROTO_IPV4, 384 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 385 .pr_input = encap4_input, 386 .pr_ctlinput = rip_ctlinput, 387 .pr_ctloutput = rip_ctloutput, 388 .pr_usrreqs = &rip_usrreqs, 389 .pr_init = encap_init, 390}, 391#ifdef INET6 392{ .pr_type = SOCK_RAW, 393 .pr_domain = &inetdomain, 394 .pr_protocol = IPPROTO_IPV6, 395 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 396 .pr_input = encap4_input, 397 .pr_ctlinput = rip_ctlinput, 398 .pr_ctloutput = rip_ctloutput, 399 .pr_usrreqs = &rip_usrreqs, 400 .pr_init = encap_init, 401}, 402#endif /* INET6 */ 403#if NCARP > 0 404{ .pr_type = SOCK_RAW, 405 .pr_domain = &inetdomain, 406 .pr_protocol = IPPROTO_CARP, 407 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 408 .pr_input = carp_proto_input, 409 .pr_ctloutput = rip_ctloutput, 410 .pr_usrreqs = &rip_usrreqs, 411 .pr_init = carp_init, 412}, 413#endif /* NCARP > 0 */ 414{ .pr_type = SOCK_RAW, 415 .pr_domain = &inetdomain, 416 .pr_protocol = IPPROTO_L2TP, 417 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 418 .pr_input = encap4_input, 419 .pr_ctlinput = rip_ctlinput, 420 .pr_ctloutput = rip_ctloutput, 421 .pr_usrreqs = &rip_usrreqs, /*XXX*/ 422 .pr_init = encap_init, 423}, 424#if NPFSYNC > 0 425{ .pr_type = SOCK_RAW, 426 .pr_domain = &inetdomain, 427 .pr_protocol = IPPROTO_PFSYNC, 428 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 429 .pr_input = pfsync_input, 430 .pr_ctloutput = rip_ctloutput, 431 .pr_usrreqs = &rip_usrreqs, 432}, 433#endif /* NPFSYNC > 0 */ 434{ .pr_type = SOCK_RAW, 435 .pr_domain = &inetdomain, 436 .pr_protocol = IPPROTO_IGMP, 437 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 438 .pr_input = igmp_input, 439 .pr_ctloutput = rip_ctloutput, 440 .pr_ctlinput = rip_ctlinput, 441 .pr_usrreqs = &rip_usrreqs, 442 .pr_fasttimo = igmp_fasttimo, 443 .pr_slowtimo = igmp_slowtimo, 444 .pr_init = igmp_init, 445}, 446#ifdef PIM 447{ .pr_type = SOCK_RAW, 448 .pr_domain = &inetdomain, 449 .pr_protocol = IPPROTO_PIM, 450 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 451 .pr_input = pim_input, 452 .pr_ctloutput = rip_ctloutput, 453 .pr_ctlinput = rip_ctlinput, 454 .pr_usrreqs = &rip_usrreqs, 455}, 456#endif /* PIM */ 457/* raw wildcard */ 458{ .pr_type = SOCK_RAW, 459 .pr_domain = &inetdomain, 460 .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, 461 .pr_input = rip_input, 462 .pr_ctloutput = rip_ctloutput, 463 .pr_ctlinput = rip_ctlinput, 464 .pr_usrreqs = &rip_usrreqs, 465 .pr_init = rip_init, 466}, 467}; 468 469const struct sockaddr_in in_any = { 470 .sin_len = sizeof(struct sockaddr_in) 471 , .sin_family = AF_INET 472 , .sin_port = 0 473 , .sin_addr = {.s_addr = 0 /* INADDR_ANY */} 474}; 475 476struct domain inetdomain = { 477 .dom_family = PF_INET, .dom_name = "internet", .dom_init = NULL, 478 .dom_externalize = NULL, .dom_dispose = NULL, 479 .dom_protosw = inetsw, 480 .dom_protoswNPROTOSW = &inetsw[__arraycount(inetsw)], 481 .dom_rtattach = rt_inithead, 482 .dom_rtoffset = 32, 483 .dom_maxrtkey = sizeof(struct ip_pack4), 484 .dom_if_up = in_if_up, 485 .dom_if_down = in_if_down, 486 .dom_ifattach = in_domifattach, 487 .dom_ifdetach = in_domifdetach, 488 .dom_if_link_state_change = in_if_link_state_change, 489 .dom_link = { NULL }, 490 .dom_mowner = MOWNER_INIT("",""), 491 .dom_sa_cmpofs = offsetof(struct sockaddr_in, sin_addr), 492 .dom_sa_cmplen = sizeof(struct in_addr), 493 .dom_sa_any = (const struct sockaddr *)&in_any, 494 .dom_sockaddr_const_addr = sockaddr_in_const_addr, 495 .dom_sockaddr_addr = sockaddr_in_addr, 496}; 497 498u_char ip_protox[IPPROTO_MAX]; 499 500static void 501sockaddr_in_addrlen(const struct sockaddr *sa, socklen_t *slenp) 502{ 503 socklen_t slen; 504 505 if (slenp == NULL) 506 return; 507 508 slen = sockaddr_getlen(sa); 509 *slenp = (socklen_t)MIN(sizeof(struct in_addr), 510 slen - MIN(slen, offsetof(struct sockaddr_in, sin_addr))); 511} 512 513const void * 514sockaddr_in_const_addr(const struct sockaddr *sa, socklen_t *slenp) 515{ 516 const struct sockaddr_in *sin; 517 518 sockaddr_in_addrlen(sa, slenp); 519 sin = (const struct sockaddr_in *)sa; 520 return &sin->sin_addr; 521} 522 523void * 524sockaddr_in_addr(struct sockaddr *sa, socklen_t *slenp) 525{ 526 struct sockaddr_in *sin; 527 528 sockaddr_in_addrlen(sa, slenp); 529 sin = (struct sockaddr_in *)sa; 530 return &sin->sin_addr; 531} 532 533int 534sockaddr_in_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2) 535{ 536 uint_fast8_t len; 537 const uint_fast8_t addrofs = offsetof(struct sockaddr_in, sin_addr), 538 addrend = addrofs + sizeof(struct in_addr); 539 int rc; 540 const struct sockaddr_in *sin1, *sin2; 541 542 sin1 = satocsin(sa1); 543 sin2 = satocsin(sa2); 544 545 len = MIN(addrend, MIN(sin1->sin_len, sin2->sin_len)); 546 547 if (len > addrofs && 548 (rc = memcmp(&sin1->sin_addr, &sin2->sin_addr, 549 len - addrofs)) != 0) 550 return rc; 551 552 return sin1->sin_len - sin2->sin_len; 553} 554