1 /* $OpenBSD: ipsec_input.c,v 1.53 2001/08/09 15:44:32 angelos Exp $ */ 2 /* 3 * The authors of this code are John Ioannidis (ji@tla.org), 4 * Angelos D. Keromytis (kermit@csd.uch.gr) and 5 * Niels Provos (provos@physnet.uni-hamburg.de). 6 * 7 * This code was written by John Ioannidis for BSD/OS in Athens, Greece, 8 * in November 1995. 9 * 10 * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, 11 * by Angelos D. Keromytis. 12 * 13 * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis 14 * and Niels Provos. 15 * 16 * Additional features in 1999 by Angelos D. Keromytis. 17 * 18 * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, 19 * Angelos D. Keromytis and Niels Provos. 20 * Copyright (c) 2001, Angelos D. Keromytis. 21 * 22 * Permission to use, copy, and modify this software with or without fee 23 * is hereby granted, provided that this entire notice is included in 24 * all copies of any software which is or includes a copy or 25 * modification of this software. 26 * You may use this code under the GNU public license if you so wish. Please 27 * contribute changes back to the authors under this freer than GPL license 28 * so that we may further the use of strong encryption without limitations to 29 * all. 30 * 31 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 32 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 33 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 34 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 35 * PURPOSE. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/protosw.h> 41 #include <sys/mbuf.h> 42 #include <sys/socket.h> 43 #include <sys/sysctl.h> 44 #include <sys/kernel.h> 45 46 #include <net/if.h> 47 #include <net/netisr.h> 48 #include <net/bpf.h> 49 50 #include <netinet/in.h> 51 #include <netinet/in_systm.h> 52 #include <netinet/ip.h> 53 #include <netinet/ip_var.h> 54 #include <netinet/in_var.h> 55 #include <netinet/ip_icmp.h> 56 #include <netinet/tcp.h> 57 #include <netinet/udp.h> 58 59 #ifdef INET6 60 #ifndef INET 61 #include <netinet/in.h> 62 #endif 63 #include <netinet/ip6.h> 64 #include <netinet6/ip6_var.h> 65 #include <netinet6/ip6protosw.h> 66 #endif /* INET6 */ 67 68 #include <netinet/ip_ipsp.h> 69 #include <netinet/ip_esp.h> 70 #include <netinet/ip_ah.h> 71 #include <netinet/ip_ipcomp.h> 72 73 #include <net/if_enc.h> 74 75 #include "bpfilter.h" 76 77 int ipsec_common_input(struct mbuf *, int, int, int, int); 78 void *ipsec_common_ctlinput(int, struct sockaddr *, void *, int); 79 80 #ifdef ENCDEBUG 81 #define DPRINTF(x) if (encdebug) printf x 82 #else 83 #define DPRINTF(x) 84 #endif 85 86 /* sysctl variables */ 87 int esp_enable = 1; 88 int ah_enable = 1; 89 int ipcomp_enable = 0; 90 91 #ifdef INET6 92 extern struct ip6protosw inet6sw[]; 93 extern u_char ip6_protox[]; 94 #endif 95 96 /* 97 * ipsec_common_input() gets called when we receive an IPsec-protected packet 98 * in IPv4 or IPv6. All it does is find the right TDB and call the appropriate 99 * transform. The callback takes care of further processing (like ingress 100 * filtering). 101 */ 102 int 103 ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto) 104 { 105 #define IPSEC_ISTAT(x,y,z) (sproto == IPPROTO_ESP ? (x)++ : \ 106 IPPROTO_AH ? (y)++ : (z)++) 107 108 union sockaddr_union dst_address; 109 struct tdb *tdbp; 110 u_int32_t spi; 111 u_int16_t cpi; 112 int s; 113 114 IPSEC_ISTAT(espstat.esps_input, ahstat.ahs_input, 115 ipcompstat.ipcomps_input); 116 117 if (m == 0) { 118 DPRINTF(("ipsec_common_input(): NULL packet received\n")); 119 IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops, 120 ipcompstat.ipcomps_hdrops); 121 return EINVAL; 122 } 123 124 if ((sproto == IPPROTO_ESP && !esp_enable) || 125 (sproto == IPPROTO_AH && !ah_enable) || 126 (sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { 127 m_freem(m); 128 IPSEC_ISTAT(espstat.esps_pdrops, ahstat.ahs_pdrops, 129 ipcompstat.ipcomps_pdrops); 130 return EOPNOTSUPP; 131 } 132 133 if (m->m_pkthdr.len - skip < 2 * sizeof(u_int32_t)) { 134 m_freem(m); 135 IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops, 136 ipcompstat.ipcomps_hdrops); 137 DPRINTF(("ipsec_common_input(): packet too small\n")); 138 return EINVAL; 139 } 140 141 /* Retrieve the SPI from the relevant IPsec header */ 142 if (sproto == IPPROTO_ESP) 143 m_copydata(m, skip, sizeof(u_int32_t), (caddr_t) &spi); 144 else if (sproto == IPPROTO_AH) 145 m_copydata(m, skip + sizeof(u_int32_t), sizeof(u_int32_t), 146 (caddr_t) &spi); 147 else if (sproto == IPPROTO_IPCOMP) { 148 m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t), 149 (caddr_t) &cpi); 150 spi = ntohl(htons(cpi)); 151 } 152 153 /* 154 * Find tunnel control block and (indirectly) call the appropriate 155 * kernel crypto routine. The resulting mbuf chain is a valid 156 * IP packet ready to go through input processing. 157 */ 158 159 bzero(&dst_address, sizeof(dst_address)); 160 dst_address.sa.sa_family = af; 161 162 switch (af) { 163 #ifdef INET 164 case AF_INET: 165 dst_address.sin.sin_len = sizeof(struct sockaddr_in); 166 m_copydata(m, offsetof(struct ip, ip_dst), 167 sizeof(struct in_addr), 168 (caddr_t) &(dst_address.sin.sin_addr)); 169 break; 170 #endif /* INET */ 171 172 #ifdef INET6 173 case AF_INET6: 174 dst_address.sin6.sin6_len = sizeof(struct sockaddr_in6); 175 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst), 176 sizeof(struct in6_addr), 177 (caddr_t) &(dst_address.sin6.sin6_addr)); 178 break; 179 #endif /* INET6 */ 180 181 default: 182 DPRINTF(("ipsec_common_input(): unsupported protocol " 183 "family %d\n", af)); 184 m_freem(m); 185 IPSEC_ISTAT(espstat.esps_nopf, ahstat.ahs_nopf, 186 ipcompstat.ipcomps_nopf); 187 return EPFNOSUPPORT; 188 } 189 190 s = spltdb(); 191 tdbp = gettdb(spi, &dst_address, sproto); 192 if (tdbp == NULL) { 193 splx(s); 194 DPRINTF(("ipsec_common_input(): could not find SA for " 195 "packet to %s, spi %08x\n", 196 ipsp_address(dst_address), ntohl(spi))); 197 m_freem(m); 198 IPSEC_ISTAT(espstat.esps_notdb, ahstat.ahs_notdb, 199 ipcompstat.ipcomps_notdb); 200 return ENOENT; 201 } 202 203 if (tdbp->tdb_flags & TDBF_INVALID) { 204 splx(s); 205 DPRINTF(("ipsec_common_input(): attempted to use invalid SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto)); 206 m_freem(m); 207 IPSEC_ISTAT(espstat.esps_invalid, ahstat.ahs_invalid, 208 ipcompstat.ipcomps_invalid); 209 return EINVAL; 210 } 211 212 if (tdbp->tdb_xform == NULL) { 213 splx(s); 214 DPRINTF(("ipsec_common_input(): attempted to use uninitialized SA %s/%08x/%u\n", ipsp_address(dst_address), ntohl(spi), tdbp->tdb_sproto)); 215 m_freem(m); 216 IPSEC_ISTAT(espstat.esps_noxform, ahstat.ahs_noxform, 217 ipcompstat.ipcomps_noxform); 218 return ENXIO; 219 } 220 221 if (tdbp->tdb_dst.sa.sa_family == AF_INET && 222 sproto != IPPROTO_IPCOMP) { 223 /* 224 * XXX The fragment conflicts with scoped nature of 225 * IPv6, so do it for only for IPv4 for now. 226 */ 227 m->m_pkthdr.rcvif = &encif[0].sc_if; 228 } 229 230 /* Register first use, setup expiration timer. */ 231 if (tdbp->tdb_first_use == 0) { 232 tdbp->tdb_first_use = time.tv_sec; 233 if (tdbp->tdb_flags & TDBF_FIRSTUSE) 234 timeout_add(&tdbp->tdb_first_tmo, hz * 235 tdbp->tdb_exp_first_use); 236 if (tdbp->tdb_flags & TDBF_SOFT_FIRSTUSE) 237 timeout_add(&tdbp->tdb_sfirst_tmo, hz * 238 tdbp->tdb_soft_first_use); 239 } 240 241 /* 242 * Call appropriate transform and return -- callback takes care of 243 * everything else. 244 */ 245 if ((*(tdbp->tdb_xform->xf_input))(m, tdbp, skip, protoff) == NULL) { 246 splx(s); 247 return EINVAL; 248 } else { 249 splx(s); 250 return 0; 251 } 252 } 253 254 /* 255 * IPsec input callback, called by the transform callback. Takes care of 256 * filtering and other sanity checks on the processed packet. 257 */ 258 int 259 ipsec_common_input_cb(struct mbuf *m, struct tdb *tdbp, int skip, int protoff, 260 struct m_tag *mt) 261 { 262 int prot, af, sproto; 263 264 #if NBPFILTER > 0 265 struct ifnet *bpfif; 266 #endif 267 268 #ifdef INET 269 struct ip *ip, ipn; 270 #endif /* INET */ 271 272 #ifdef INET6 273 struct ip6_hdr *ip6, ip6n; 274 #endif /* INET6 */ 275 struct m_tag *mtag; 276 struct tdb_ident *tdbi; 277 278 af = tdbp->tdb_dst.sa.sa_family; 279 sproto = tdbp->tdb_sproto; 280 281 tdbp->tdb_last_used = time.tv_sec; 282 283 /* Sanity check */ 284 if (m == NULL) { 285 /* The called routine will print a message if necessary */ 286 IPSEC_ISTAT(espstat.esps_badkcr, ahstat.ahs_badkcr, 287 ipcompstat.ipcomps_badkcr); 288 return EINVAL; 289 } 290 291 #ifdef INET 292 /* Fix IPv4 header */ 293 if (tdbp->tdb_dst.sa.sa_family == AF_INET) { 294 if ((m->m_len < skip) && ((m = m_pullup(m, skip)) == NULL)) { 295 DPRINTF(("ipsec_common_input_cb(): processing failed " 296 "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst), 297 ntohl(tdbp->tdb_spi))); 298 IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops, 299 ipcompstat.ipcomps_hdrops); 300 return ENOBUFS; 301 } 302 303 ip = mtod(m, struct ip *); 304 ip->ip_len = htons(m->m_pkthdr.len); 305 HTONS(ip->ip_off); 306 ip->ip_sum = 0; 307 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 308 prot = ip->ip_p; 309 310 /* IP-in-IP encapsulation */ 311 if (prot == IPPROTO_IPIP) { 312 /* ipn will now contain the inner IPv4 header */ 313 m_copydata(m, ip->ip_hl << 2, sizeof(struct ip), 314 (caddr_t) &ipn); 315 316 /* 317 * Check that the inner source address is the same as 318 * the proxy address, if available. 319 */ 320 if ((tdbp->tdb_proxy.sa.sa_family == AF_INET && 321 tdbp->tdb_proxy.sin.sin_addr.s_addr != 322 INADDR_ANY && 323 ipn.ip_src.s_addr != 324 tdbp->tdb_proxy.sin.sin_addr.s_addr) || 325 (tdbp->tdb_proxy.sa.sa_family != AF_INET && 326 tdbp->tdb_proxy.sa.sa_family != 0)) { 327 328 DPRINTF(("ipsec_common_input_cb(): inner " 329 "source address %s doesn't correspond to " 330 "expected proxy source %s, SA %s/%08x\n", 331 inet_ntoa4(ipn.ip_src), 332 ipsp_address(tdbp->tdb_proxy), 333 ipsp_address(tdbp->tdb_dst), 334 ntohl(tdbp->tdb_spi))); 335 336 m_freem(m); 337 IPSEC_ISTAT(espstat.esps_pdrops, 338 ahstat.ahs_pdrops, 339 ipcompstat.ipcomps_pdrops); 340 return EACCES; 341 } 342 } 343 344 #if INET6 345 /* IPv6-in-IP encapsulation. */ 346 if (prot == IPPROTO_IPV6) { 347 /* ip6n will now contain the inner IPv6 header. */ 348 m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr), 349 (caddr_t) &ip6n); 350 351 /* 352 * Check that the inner source address is the same as 353 * the proxy address, if available. 354 */ 355 if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 && 356 !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) && 357 !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, 358 &tdbp->tdb_proxy.sin6.sin6_addr)) || 359 (tdbp->tdb_proxy.sa.sa_family != AF_INET6 && 360 tdbp->tdb_proxy.sa.sa_family != 0)) { 361 362 DPRINTF(("ipsec_common_input_cb(): inner " 363 "source address %s doesn't correspond to " 364 "expected proxy source %s, SA %s/%08x\n", 365 ip6_sprintf(&ip6n.ip6_src), 366 ipsp_address(tdbp->tdb_proxy), 367 ipsp_address(tdbp->tdb_dst), 368 ntohl(tdbp->tdb_spi))); 369 370 m_freem(m); 371 IPSEC_ISTAT(espstat.esps_pdrops, 372 ahstat.ahs_pdrops, 373 ipcompstat.ipcomps_pdrops); 374 return EACCES; 375 } 376 } 377 #endif /* INET6 */ 378 } 379 #endif /* INET */ 380 381 #ifdef INET6 382 /* Fix IPv6 header */ 383 if (af == INET6) 384 { 385 if (m->m_len < sizeof(struct ip6_hdr) && 386 (m = m_pullup(m, sizeof(struct ip6_hdr))) == NULL) { 387 388 DPRINTF(("ipsec_common_input_cb(): processing failed " 389 "for SA %s/%08x\n", ipsp_address(tdbp->tdb_dst), 390 ntohl(tdbp->tdb_spi))); 391 392 IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops, 393 ipcompstat.ipcomps_hdrops); 394 return EACCES; 395 } 396 397 ip6 = mtod(m, struct ip6_hdr *); 398 ip6->ip6_plen = htons(m->m_pkthdr.len - 399 sizeof(struct ip6_hdr)); 400 401 /* Save protocol */ 402 m_copydata(m, protoff, 1, (unsigned char *) &prot); 403 404 #ifdef INET 405 /* IP-in-IP encapsulation */ 406 if (prot == IPPROTO_IPIP) { 407 /* ipn will now contain the inner IPv4 header */ 408 m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn); 409 410 /* 411 * Check that the inner source address is the same as 412 * the proxy address, if available. 413 */ 414 if ((tdbp->tdb_proxy.sa.sa_family == AF_INET && 415 tdbp->tdb_proxy.sin.sin_addr.s_addr != 416 INADDR_ANY && 417 ipn.ip_src.s_addr != 418 tdbp->tdb_proxy.sin.sin_addr.s_addr) || 419 (tdbp->tdb_proxy.sa.sa_family != AF_INET && 420 tdbp->tdb_proxy.sa.sa_family != 0)) { 421 422 DPRINTF(("ipsec_common_input_cb(): inner " 423 "source address %s doesn't correspond to " 424 "expected proxy source %s, SA %s/%08x\n", 425 inet_ntoa4(ipn.ip_src), 426 ipsp_address(tdbp->tdb_proxy), 427 ipsp_address(tdbp->tdb_dst), 428 ntohl(tdbp->tdb_spi))); 429 430 m_freem(m); 431 IPSEC_ISTAT(espstat.esps_pdrops, 432 ahstat.ahs_pdrops, 433 ipcompstat.ipcomps_pdrops); 434 return EACCES; 435 } 436 } 437 #endif /* INET */ 438 439 /* IPv6-in-IP encapsulation */ 440 if (prot == IPPROTO_IPV6) { 441 /* ip6n will now contain the inner IPv6 header. */ 442 m_copydata(m, skip, sizeof(struct ip6_hdr), 443 (caddr_t) &ip6n); 444 445 /* 446 * Check that the inner source address is the same as 447 * the proxy address, if available. 448 */ 449 if ((tdbp->tdb_proxy.sa.sa_family == AF_INET6 && 450 !IN6_IS_ADDR_UNSPECIFIED(&tdbp->tdb_proxy.sin6.sin6_addr) && 451 !IN6_ARE_ADDR_EQUAL(&ip6n.ip6_src, 452 &tdbp->tdb_proxy.sin6.sin6_addr)) || 453 (tdbp->tdb_proxy.sa.sa_family != AF_INET6 && 454 tdbp->tdb_proxy.sa.sa_family != 0)) { 455 456 DPRINTF(("ipsec_common_input_cb(): inner " 457 "source address %s doesn't correspond to " 458 "expected proxy source %s, SA %s/%08x\n", 459 ip6_sprintf(&ip6n.ip6_src), 460 ipsp_address(tdbp->tdb_proxy), 461 ipsp_address(tdbp->tdb_dst), 462 ntohl(tdbp->tdb_spi))); 463 464 m_freem(m); 465 IPSEC_ISTAT(espstat.esps_pdrops, 466 ahstat.ahs_pdrops, 467 ipcompstat.ipcomps_pdrops); 468 return EACCES; 469 } 470 } 471 } 472 #endif /* INET6 */ 473 474 /* 475 * Record what we've done to the packet (under what SA it was 476 * processed). If we've been passed an mtag, it means the packet 477 * was already processed by an ethernet/crypto combo card and 478 * thus has a tag attached with all the right information, but 479 * with a PACKET_TAG_IPSEC_IN_CRYPTO_DONE as opposed to 480 * PACKET_TAG_IPSEC_IN_DONE type; in that case, just change the type. 481 */ 482 if (mt == NULL && tdbp->tdb_sproto != IPPROTO_IPCOMP) { 483 mtag = m_tag_get(PACKET_TAG_IPSEC_IN_DONE, 484 sizeof(struct tdb_ident), M_NOWAIT); 485 if (mtag == NULL) { 486 m_freem(m); 487 DPRINTF(("ipsec_common_input_cb(): failed to " 488 "get tag\n")); 489 IPSEC_ISTAT(espstat.esps_hdrops, ahstat.ahs_hdrops, 490 ipcompstat.ipcomps_hdrops); 491 return ENOMEM; 492 } 493 494 tdbi = (struct tdb_ident *)(mtag + 1); 495 bcopy(&tdbp->tdb_dst, &tdbi->dst, 496 sizeof(union sockaddr_union)); 497 tdbi->proto = tdbp->tdb_sproto; 498 tdbi->spi = tdbp->tdb_spi; 499 500 m_tag_prepend(m, mtag); 501 } 502 else 503 mt->m_tag_id = PACKET_TAG_IPSEC_IN_DONE; 504 505 if (sproto == IPPROTO_ESP) { 506 /* Packet is confidential ? */ 507 if (tdbp->tdb_encalgxform) 508 m->m_flags |= M_CONF; 509 510 /* Check if we had authenticated ESP. */ 511 if (tdbp->tdb_authalgxform) 512 m->m_flags |= M_AUTH; 513 } 514 else if (sproto == IPPROTO_IPCOMP) 515 m->m_flags |= M_COMP; 516 else 517 m->m_flags |= M_AUTH; 518 519 #if NBPFILTER > 0 520 bpfif = &encif[0].sc_if; 521 if (bpfif->if_bpf) { 522 /* 523 * We need to prepend the address family as 524 * a four byte field. Cons up a dummy header 525 * to pacify bpf. This is safe because bpf 526 * will only read from the mbuf (i.e., it won't 527 * try to free it or keep a pointer a to it). 528 */ 529 struct mbuf m1; 530 struct enchdr hdr; 531 532 hdr.af = af; 533 hdr.spi = tdbp->tdb_spi; 534 hdr.flags = m->m_flags & (M_AUTH|M_CONF); 535 536 m1.m_next = m; 537 m1.m_len = ENC_HDRLEN; 538 m1.m_data = (char *) &hdr; 539 540 bpf_mtap(bpfif->if_bpf, &m1); 541 } 542 #endif 543 544 /* Call the appropriate IPsec transform callback. */ 545 switch (af) { 546 #ifdef INET 547 case AF_INET: 548 switch (sproto) 549 { 550 case IPPROTO_ESP: 551 return esp4_input_cb(m); 552 553 case IPPROTO_AH: 554 return ah4_input_cb(m); 555 556 case IPPROTO_IPCOMP: 557 return ipcomp4_input_cb(m); 558 559 default: 560 DPRINTF(("ipsec_common_input_cb(): unknown/unsupported" 561 " security protocol %d\n", sproto)); 562 m_freem(m); 563 return EPFNOSUPPORT; 564 } 565 break; 566 #endif /* INET */ 567 568 #ifdef INET6 569 case AF_INET6: 570 switch (sproto) { 571 case IPPROTO_ESP: 572 return esp6_input_cb(m, skip, protoff); 573 574 case IPPROTO_AH: 575 return ah6_input_cb(m, skip, protoff); 576 577 case IPPROTO_IPCOMP: 578 return ipcomp6_input_cb(m, skip, protoff); 579 580 default: 581 DPRINTF(("ipsec_common_input_cb(): unknown/unsupported" 582 " security protocol %d\n", sproto)); 583 m_freem(m); 584 return EPFNOSUPPORT; 585 } 586 break; 587 #endif /* INET6 */ 588 589 default: 590 DPRINTF(("ipsec_common_input_cb(): unknown/unsupported " 591 "protocol family %d\n", af)); 592 m_freem(m); 593 return EPFNOSUPPORT; 594 } 595 #undef IPSEC_ISTAT 596 } 597 598 int 599 esp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlen, void *newp, 600 size_t newlen) 601 { 602 /* All sysctl names at this level are terminal. */ 603 if (namelen != 1) 604 return ENOTDIR; 605 606 switch (name[0]) { 607 case ESPCTL_ENABLE: 608 return sysctl_int(oldp, oldlen, newp, newlen, &esp_enable); 609 default: 610 return ENOPROTOOPT; 611 } 612 /* NOTREACHED */ 613 } 614 615 int 616 ah_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlen, void *newp, 617 size_t newlen) 618 { 619 /* All sysctl names at this level are terminal. */ 620 if (namelen != 1) 621 return ENOTDIR; 622 623 switch (name[0]) { 624 case AHCTL_ENABLE: 625 return sysctl_int(oldp, oldlen, newp, newlen, &ah_enable); 626 default: 627 return ENOPROTOOPT; 628 } 629 /* NOTREACHED */ 630 } 631 632 int 633 ipcomp_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlen, void *newp, 634 size_t newlen) 635 { 636 /* All sysctl names at this level are terminal. */ 637 if (namelen != 1) 638 return ENOTDIR; 639 640 switch (name[0]) { 641 case IPCOMPCTL_ENABLE: 642 return sysctl_int(oldp, oldlen, newp, newlen, &ipcomp_enable); 643 default: 644 return ENOPROTOOPT; 645 } 646 /* NOTREACHED */ 647 } 648 649 #ifdef INET 650 /* IPv4 AH wrapper. */ 651 void 652 ah4_input(struct mbuf *m, ...) 653 { 654 int skip; 655 656 va_list ap; 657 va_start(ap, m); 658 skip = va_arg(ap, int); 659 va_end(ap); 660 661 ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET, 662 IPPROTO_AH); 663 return; 664 } 665 666 /* IPv4 AH callback. */ 667 int 668 ah4_input_cb(struct mbuf *m, ...) 669 { 670 struct ifqueue *ifq = &ipintrq; 671 int s = splimp(); 672 673 /* 674 * Interface pointer is already in first mbuf; chop off the 675 * `outer' header and reschedule. 676 */ 677 678 if (IF_QFULL(ifq)) { 679 IF_DROP(ifq); 680 ahstat.ahs_qfull++; 681 splx(s); 682 683 m_freem(m); 684 DPRINTF(("ah4_input_cb(): dropped packet because of full " 685 "IP queue\n")); 686 return ENOBUFS; 687 } 688 689 IF_ENQUEUE(ifq, m); 690 schednetisr(NETISR_IP); 691 splx(s); 692 return 0; 693 } 694 695 696 void * 697 ah4_ctlinput(int cmd, struct sockaddr *sa, void *v) 698 { 699 if (sa->sa_family != AF_INET || 700 sa->sa_len != sizeof(struct sockaddr_in)) 701 return (NULL); 702 703 return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_AH)); 704 } 705 706 /* IPv4 ESP wrapper. */ 707 void 708 esp4_input(struct mbuf *m, ...) 709 { 710 int skip; 711 712 va_list ap; 713 va_start(ap, m); 714 skip = va_arg(ap, int); 715 va_end(ap); 716 717 ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET, 718 IPPROTO_ESP); 719 } 720 721 /* IPv4 ESP callback. */ 722 int 723 esp4_input_cb(struct mbuf *m, ...) 724 { 725 struct ifqueue *ifq = &ipintrq; 726 int s = splimp(); 727 728 /* 729 * Interface pointer is already in first mbuf; chop off the 730 * `outer' header and reschedule. 731 */ 732 if (IF_QFULL(ifq)) { 733 IF_DROP(ifq); 734 espstat.esps_qfull++; 735 splx(s); 736 737 m_freem(m); 738 DPRINTF(("esp4_input_cb(): dropped packet because of full " 739 "IP queue\n")); 740 return ENOBUFS; 741 } 742 743 IF_ENQUEUE(ifq, m); 744 schednetisr(NETISR_IP); 745 splx(s); 746 return 0; 747 } 748 749 /* IPv4 IPCOMP wrapper */ 750 void 751 ipcomp4_input(struct mbuf *m, ...) 752 { 753 int skip; 754 va_list ap; 755 va_start(ap, m); 756 skip = va_arg(ap, int); 757 va_end(ap); 758 759 ipsec_common_input(m, skip, offsetof(struct ip, ip_p), AF_INET, 760 IPPROTO_IPCOMP); 761 } 762 763 /* IPv4 IPCOMP callback */ 764 int 765 ipcomp4_input_cb(struct mbuf *m, ...) 766 { 767 struct ifqueue *ifq = &ipintrq; 768 int s = splimp(); 769 770 /* 771 * Interface pointer is already in first mbuf; chop off the 772 * `outer' header and reschedule. 773 */ 774 if (IF_QFULL(ifq)) { 775 IF_DROP(ifq); 776 ipcompstat.ipcomps_qfull++; 777 splx(s); 778 779 m_freem(m); 780 DPRINTF(("ipcomp4_input_cb(): dropped packet because of full IP queue\n")); 781 return ENOBUFS; 782 } 783 784 IF_ENQUEUE(ifq, m); 785 schednetisr(NETISR_IP); 786 splx(s); 787 788 return 0; 789 } 790 791 void * 792 ipsec_common_ctlinput(int cmd, struct sockaddr *sa, void *v, int proto) 793 { 794 extern u_int ip_mtudisc_timeout; 795 struct ip *ip = v; 796 int s; 797 798 if (cmd == PRC_MSGSIZE && ip && ip->ip_v == 4) { 799 struct tdb *tdbp; 800 struct sockaddr_in dst; 801 struct icmp *icp; 802 int hlen = ip->ip_hl << 2; 803 u_int32_t spi, mtu; 804 ssize_t adjust; 805 806 /* Find the right MTU. */ 807 icp = (struct icmp *)((caddr_t) ip - 808 offsetof(struct icmp, icmp_ip)); 809 mtu = ntohs(icp->icmp_nextmtu); 810 811 /* 812 * Ignore the packet, if we do not receive a MTU 813 * or the MTU is too small to be acceptable. 814 */ 815 if (mtu < 296) 816 return (NULL); 817 818 bzero(&dst, sizeof(struct sockaddr_in)); 819 dst.sin_family = AF_INET; 820 dst.sin_len = sizeof(struct sockaddr_in); 821 dst.sin_addr.s_addr = ip->ip_dst.s_addr; 822 823 bcopy((caddr_t)ip + hlen, &spi, sizeof(u_int32_t)); 824 825 s = spltdb(); 826 tdbp = gettdb(spi, (union sockaddr_union *)&dst, proto); 827 if (tdbp == NULL || tdbp->tdb_flags & TDBF_INVALID) { 828 splx(s); 829 return (NULL); 830 } 831 832 /* Walk the chain backswards to the first tdb */ 833 for (; tdbp; tdbp = tdbp->tdb_inext) { 834 if (tdbp->tdb_flags & TDBF_INVALID || 835 (adjust = ipsec_hdrsz(tdbp)) == -1) { 836 splx(s); 837 return (NULL); 838 } 839 840 mtu -= adjust; 841 842 /* Store adjusted MTU in tdb */ 843 tdbp->tdb_mtu = mtu; 844 tdbp->tdb_mtutimeout = time.tv_sec + 845 ip_mtudisc_timeout; 846 } 847 splx(s); 848 return (NULL); 849 } 850 return (NULL); 851 } 852 853 void * 854 esp4_ctlinput(int cmd, struct sockaddr *sa, void *v) 855 { 856 if (sa->sa_family != AF_INET || 857 sa->sa_len != sizeof(struct sockaddr_in)) 858 return (NULL); 859 860 return (ipsec_common_ctlinput(cmd, sa, v, IPPROTO_ESP)); 861 } 862 #endif /* INET */ 863 864 #ifdef INET6 865 /* IPv6 AH wrapper. */ 866 int 867 ah6_input(struct mbuf **mp, int *offp, int proto) 868 { 869 int l = 0; 870 int protoff; 871 struct ip6_ext ip6e; 872 873 if (*offp < sizeof(struct ip6_hdr)) { 874 DPRINTF(("ah6_input(): bad offset\n")); 875 return IPPROTO_DONE; 876 } else if (*offp == sizeof(struct ip6_hdr)) { 877 protoff = offsetof(struct ip6_hdr, ip6_nxt); 878 } else { 879 /* Chase down the header chain... */ 880 protoff = sizeof(struct ip6_hdr); 881 882 do { 883 protoff += l; 884 m_copydata(*mp, protoff, sizeof(ip6e), 885 (caddr_t) &ip6e); 886 887 if (ip6e.ip6e_nxt == IPPROTO_AH) 888 l = (ip6e.ip6e_len + 2) << 2; 889 else 890 l = (ip6e.ip6e_len + 1) << 3; 891 #ifdef DIAGNOSTIC 892 if (l <= 0) 893 panic("ah6_input: l went zero or negative"); 894 #endif 895 } while (protoff + l < *offp); 896 897 /* Malformed packet check */ 898 if (protoff + l != *offp) { 899 DPRINTF(("ah6_input(): bad packet header chain\n")); 900 ahstat.ahs_hdrops++; 901 m_freem(*mp); 902 *mp = NULL; 903 return IPPROTO_DONE; 904 } 905 protoff += offsetof(struct ip6_ext, ip6e_nxt); 906 } 907 ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto); 908 return IPPROTO_DONE; 909 } 910 911 /* IPv6 AH callback. */ 912 int 913 ah6_input_cb(struct mbuf *m, int off, int protoff) 914 { 915 int nxt; 916 u_int8_t nxt8; 917 int nest = 0; 918 919 /* Retrieve new protocol */ 920 m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8); 921 nxt = nxt8; 922 923 /* 924 * see the end of ip6_input for this logic. 925 * IPPROTO_IPV[46] case will be processed just like other ones 926 */ 927 while (nxt != IPPROTO_DONE) { 928 if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { 929 ip6stat.ip6s_toomanyhdr++; 930 goto bad; 931 } 932 933 /* 934 * Protection against faulty packet - there should be 935 * more sanity checks in header chain processing. 936 */ 937 if (m->m_pkthdr.len < off) { 938 ip6stat.ip6s_tooshort++; 939 in6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_truncated); 940 goto bad; 941 } 942 nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt); 943 } 944 return 0; 945 946 bad: 947 m_freem(m); 948 return EINVAL; 949 } 950 951 /* IPv6 ESP wrapper. */ 952 int 953 esp6_input(struct mbuf **mp, int *offp, int proto) 954 { 955 int l = 0; 956 int protoff; 957 struct ip6_ext ip6e; 958 959 if (*offp < sizeof(struct ip6_hdr)) { 960 DPRINTF(("esp6_input(): bad offset\n")); 961 return IPPROTO_DONE; 962 } else if (*offp == sizeof(struct ip6_hdr)) { 963 protoff = offsetof(struct ip6_hdr, ip6_nxt); 964 } else { 965 /* Chase down the header chain... */ 966 protoff = sizeof(struct ip6_hdr); 967 968 do { 969 protoff += l; 970 m_copydata(*mp, protoff, sizeof(ip6e), 971 (caddr_t) &ip6e); 972 973 if (ip6e.ip6e_nxt == IPPROTO_AH) 974 l = (ip6e.ip6e_len + 2) << 2; 975 else 976 l = (ip6e.ip6e_len + 1) << 3; 977 #ifdef DIAGNOSTIC 978 if (l <= 0) 979 panic("esp6_input: l went zero or negative"); 980 #endif 981 } while (protoff + l < *offp); 982 983 /* Malformed packet check */ 984 if (protoff + l != *offp) { 985 DPRINTF(("esp6_input(): bad packet header chain\n")); 986 espstat.esps_hdrops++; 987 m_freem(*mp); 988 *mp = NULL; 989 return IPPROTO_DONE; 990 } 991 protoff += offsetof(struct ip6_ext, ip6e_nxt); 992 } 993 ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto); 994 return IPPROTO_DONE; 995 996 } 997 998 /* IPv6 ESP callback */ 999 int 1000 esp6_input_cb(struct mbuf *m, int skip, int protoff) 1001 { 1002 return ah6_input_cb(m, skip, protoff); 1003 } 1004 1005 /* IPv6 IPcomp wrapper */ 1006 int 1007 ipcomp6_input(struct mbuf **mp, int *offp, int proto) 1008 { 1009 int l = 0; 1010 int protoff; 1011 struct ip6_ext ip6e; 1012 1013 if (*offp < sizeof(struct ip6_hdr)) { 1014 DPRINTF(("ipcomp6_input(): bad offset\n")); 1015 return IPPROTO_DONE; 1016 } else if (*offp == sizeof(struct ip6_hdr)) { 1017 protoff = offsetof(struct ip6_hdr, ip6_nxt); 1018 } else { 1019 /* Chase down the header chain... */ 1020 protoff = sizeof(struct ip6_hdr); 1021 1022 do { 1023 protoff += l; 1024 m_copydata(*mp, protoff, sizeof(ip6e), 1025 (caddr_t) &ip6e); 1026 if (ip6e.ip6e_nxt == IPPROTO_AH) 1027 l = (ip6e.ip6e_len + 2) << 2; 1028 else 1029 l = (ip6e.ip6e_len + 1) << 3; 1030 #ifdef DIAGNOSTIC 1031 if (l <= 0) 1032 panic("ipcomp6_input: l went zero or negative"); 1033 #endif 1034 } while (protoff + l < *offp); 1035 1036 /* Malformed packet check */ 1037 if (protoff + l != *offp) { 1038 DPRINTF(("ipcomp6_input(): bad packet header chain\n")); 1039 ipcompstat.ipcomps_hdrops++; 1040 m_freem(*mp); 1041 *mp = NULL; 1042 return IPPROTO_DONE; 1043 } 1044 1045 protoff += offsetof(struct ip6_ext, ip6e_nxt); 1046 } 1047 ipsec_common_input(*mp, *offp, protoff, AF_INET6, proto); 1048 return IPPROTO_DONE; 1049 } 1050 1051 /* IPv6 IPcomp callback */ 1052 int 1053 ipcomp6_input_cb(struct mbuf *m, int skip, int protoff) 1054 { 1055 return ah6_input_cb(m, skip, protoff); 1056 } 1057 1058 #endif /* INET6 */ 1059 1060 1061 1062