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