1 /* $OpenBSD: ipsec_output.c,v 1.83 2021/07/21 11:11:41 bluhm Exp $ */ 2 /* 3 * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) 4 * 5 * Copyright (c) 2000-2001 Angelos D. Keromytis. 6 * 7 * Permission to use, copy, and modify this software with or without fee 8 * is hereby granted, provided that this entire notice is included in 9 * all copies of any software which is or includes a copy or 10 * modification of this software. 11 * You may use this code under the GNU public license if you so wish. Please 12 * contribute changes back to the authors under this freer than GPL license 13 * so that we may further the use of strong encryption without limitations to 14 * all. 15 * 16 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 18 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 19 * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 20 * PURPOSE. 21 */ 22 23 #include "pf.h" 24 25 #include <sys/param.h> 26 #include <sys/systm.h> 27 #include <sys/mbuf.h> 28 #include <sys/socket.h> 29 #include <sys/kernel.h> 30 #include <sys/timeout.h> 31 32 #include <net/if.h> 33 #include <net/route.h> 34 35 #include <netinet/in.h> 36 #include <netinet/ip.h> 37 #include <netinet/in_pcb.h> 38 #include <netinet/ip_var.h> 39 40 #if NPF > 0 41 #include <net/pfvar.h> 42 #endif 43 44 #include <netinet/udp.h> 45 #include <netinet/ip_ipip.h> 46 #include <netinet/ip_ah.h> 47 #include <netinet/ip_esp.h> 48 #include <netinet/ip_ipcomp.h> 49 50 #include <crypto/cryptodev.h> 51 #include <crypto/xform.h> 52 53 #ifdef ENCDEBUG 54 #define DPRINTF(fmt, args...) \ 55 do { \ 56 if (encdebug) \ 57 printf("%s: " fmt "\n", __func__, ## args); \ 58 } while (0) 59 #else 60 #define DPRINTF(fmt, args...) \ 61 do { } while (0) 62 #endif 63 64 int udpencap_enable = 1; /* enabled by default */ 65 int udpencap_port = 4500; /* triggers decapsulation */ 66 67 /* 68 * Loop over a tdb chain, taking into consideration protocol tunneling. The 69 * fourth argument is set if the first encapsulation header is already in 70 * place. 71 */ 72 int 73 ipsp_process_packet(struct mbuf *m, struct tdb *tdb, int af, int tunalready) 74 { 75 int hlen, off, error; 76 struct mbuf *mp; 77 #ifdef INET6 78 struct ip6_ext ip6e; 79 int nxt; 80 int dstopt = 0; 81 #endif 82 83 int setdf = 0; 84 struct ip *ip; 85 #ifdef INET6 86 struct ip6_hdr *ip6; 87 #endif /* INET6 */ 88 89 #ifdef ENCDEBUG 90 char buf[INET6_ADDRSTRLEN]; 91 #endif 92 93 /* Check that the transform is allowed by the administrator. */ 94 if ((tdb->tdb_sproto == IPPROTO_ESP && !esp_enable) || 95 (tdb->tdb_sproto == IPPROTO_AH && !ah_enable) || 96 (tdb->tdb_sproto == IPPROTO_IPCOMP && !ipcomp_enable)) { 97 DPRINTF("IPsec outbound packet dropped due to policy " 98 "(check your sysctls)"); 99 error = EHOSTUNREACH; 100 goto drop; 101 } 102 103 /* Sanity check. */ 104 if (!tdb->tdb_xform) { 105 DPRINTF("uninitialized TDB"); 106 error = EHOSTUNREACH; 107 goto drop; 108 } 109 110 /* Check if the SPI is invalid. */ 111 if (tdb->tdb_flags & TDBF_INVALID) { 112 DPRINTF("attempt to use invalid SA %s/%08x/%u", 113 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 114 ntohl(tdb->tdb_spi), tdb->tdb_sproto); 115 error = ENXIO; 116 goto drop; 117 } 118 119 /* Check that the network protocol is supported */ 120 switch (tdb->tdb_dst.sa.sa_family) { 121 case AF_INET: 122 break; 123 124 #ifdef INET6 125 case AF_INET6: 126 break; 127 #endif /* INET6 */ 128 129 default: 130 DPRINTF("attempt to use SA %s/%08x/%u for protocol family %d", 131 ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)), 132 ntohl(tdb->tdb_spi), tdb->tdb_sproto, 133 tdb->tdb_dst.sa.sa_family); 134 error = ENXIO; 135 goto drop; 136 } 137 138 /* 139 * Register first use if applicable, setup relevant expiration timer. 140 */ 141 if (tdb->tdb_first_use == 0) { 142 tdb->tdb_first_use = gettime(); 143 if (tdb->tdb_flags & TDBF_FIRSTUSE) 144 timeout_add_sec(&tdb->tdb_first_tmo, 145 tdb->tdb_exp_first_use); 146 if (tdb->tdb_flags & TDBF_SOFT_FIRSTUSE) 147 timeout_add_sec(&tdb->tdb_sfirst_tmo, 148 tdb->tdb_soft_first_use); 149 } 150 151 /* 152 * Check for tunneling if we don't have the first header in place. 153 * When doing Ethernet-over-IP, we are handed an already-encapsulated 154 * frame, so we don't need to re-encapsulate. 155 */ 156 if (tunalready == 0) { 157 /* 158 * If the target protocol family is different, we know we'll be 159 * doing tunneling. 160 */ 161 if (af == tdb->tdb_dst.sa.sa_family) { 162 if (af == AF_INET) 163 hlen = sizeof(struct ip); 164 165 #ifdef INET6 166 if (af == AF_INET6) 167 hlen = sizeof(struct ip6_hdr); 168 #endif /* INET6 */ 169 170 /* Bring the network header in the first mbuf. */ 171 if (m->m_len < hlen) { 172 if ((m = m_pullup(m, hlen)) == NULL) { 173 error = ENOBUFS; 174 goto drop; 175 } 176 } 177 178 if (af == AF_INET) { 179 ip = mtod(m, struct ip *); 180 181 /* 182 * This is not a bridge packet, remember if we 183 * had IP_DF. 184 */ 185 setdf = ip->ip_off & htons(IP_DF); 186 } 187 188 #ifdef INET6 189 if (af == AF_INET6) 190 ip6 = mtod(m, struct ip6_hdr *); 191 #endif /* INET6 */ 192 } 193 194 /* Do the appropriate encapsulation, if necessary. */ 195 if ((tdb->tdb_dst.sa.sa_family != af) || /* PF mismatch */ 196 (tdb->tdb_flags & TDBF_TUNNELING) || /* Tunneling needed */ 197 (tdb->tdb_xform->xf_type == XF_IP4) || /* ditto */ 198 ((tdb->tdb_dst.sa.sa_family == AF_INET) && 199 (tdb->tdb_dst.sin.sin_addr.s_addr != INADDR_ANY) && 200 (tdb->tdb_dst.sin.sin_addr.s_addr != ip->ip_dst.s_addr)) || 201 #ifdef INET6 202 ((tdb->tdb_dst.sa.sa_family == AF_INET6) && 203 (!IN6_IS_ADDR_UNSPECIFIED(&tdb->tdb_dst.sin6.sin6_addr)) && 204 (!IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, 205 &ip6->ip6_dst))) || 206 #endif /* INET6 */ 207 0) { 208 /* Fix IPv4 header checksum and length. */ 209 if (af == AF_INET) { 210 if (m->m_len < sizeof(struct ip)) 211 if ((m = m_pullup(m, 212 sizeof(struct ip))) == NULL) { 213 error = ENOBUFS; 214 goto drop; 215 } 216 217 ip = mtod(m, struct ip *); 218 ip->ip_len = htons(m->m_pkthdr.len); 219 ip->ip_sum = 0; 220 ip->ip_sum = in_cksum(m, ip->ip_hl << 2); 221 } 222 223 #ifdef INET6 224 /* Fix IPv6 header payload length. */ 225 if (af == AF_INET6) { 226 if (m->m_len < sizeof(struct ip6_hdr)) 227 if ((m = m_pullup(m, 228 sizeof(struct ip6_hdr))) == NULL) { 229 error = ENOBUFS; 230 goto drop; 231 } 232 233 if (m->m_pkthdr.len - sizeof(*ip6) > 234 IPV6_MAXPACKET) { 235 /* No jumbogram support. */ 236 error = ENXIO; /*?*/ 237 goto drop; 238 } 239 ip6 = mtod(m, struct ip6_hdr *); 240 ip6->ip6_plen = htons(m->m_pkthdr.len 241 - sizeof(*ip6)); 242 } 243 #endif /* INET6 */ 244 245 /* Encapsulate -- the last two arguments are unused. */ 246 error = ipip_output(m, tdb, &mp, 0, 0); 247 if ((mp == NULL) && (!error)) 248 error = EFAULT; 249 m = mp; 250 mp = NULL; 251 if (error) 252 goto drop; 253 254 if (tdb->tdb_dst.sa.sa_family == AF_INET && setdf) { 255 if (m->m_len < sizeof(struct ip)) 256 if ((m = m_pullup(m, 257 sizeof(struct ip))) == NULL) { 258 error = ENOBUFS; 259 goto drop; 260 } 261 262 ip = mtod(m, struct ip *); 263 ip->ip_off |= htons(IP_DF); 264 } 265 266 /* Remember that we appended a tunnel header. */ 267 tdb->tdb_flags |= TDBF_USEDTUNNEL; 268 } 269 270 /* We may be done with this TDB */ 271 if (tdb->tdb_xform->xf_type == XF_IP4) 272 return ipsp_process_done(m, tdb); 273 } else { 274 /* 275 * If this is just an IP-IP TDB and we're told there's 276 * already an encapsulation header, move on. 277 */ 278 if (tdb->tdb_xform->xf_type == XF_IP4) 279 return ipsp_process_done(m, tdb); 280 } 281 282 /* Extract some information off the headers. */ 283 switch (tdb->tdb_dst.sa.sa_family) { 284 case AF_INET: 285 ip = mtod(m, struct ip *); 286 hlen = ip->ip_hl << 2; 287 off = offsetof(struct ip, ip_p); 288 break; 289 290 #ifdef INET6 291 case AF_INET6: 292 ip6 = mtod(m, struct ip6_hdr *); 293 hlen = sizeof(struct ip6_hdr); 294 off = offsetof(struct ip6_hdr, ip6_nxt); 295 nxt = ip6->ip6_nxt; 296 /* 297 * chase mbuf chain to find the appropriate place to 298 * put AH/ESP/IPcomp header. 299 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload] 300 */ 301 do { 302 switch (nxt) { 303 case IPPROTO_AH: 304 case IPPROTO_ESP: 305 case IPPROTO_IPCOMP: 306 /* 307 * we should not skip security header added 308 * beforehand. 309 */ 310 goto exitip6loop; 311 312 case IPPROTO_HOPOPTS: 313 case IPPROTO_DSTOPTS: 314 case IPPROTO_ROUTING: 315 /* 316 * if we see 2nd destination option header, 317 * we should stop there. 318 */ 319 if (nxt == IPPROTO_DSTOPTS && dstopt) 320 goto exitip6loop; 321 322 if (nxt == IPPROTO_DSTOPTS) { 323 /* 324 * seen 1st or 2nd destination option. 325 * next time we see one, it must be 2nd. 326 */ 327 dstopt = 1; 328 } else if (nxt == IPPROTO_ROUTING) { 329 /* 330 * if we see destination option next 331 * time, it must be dest2. 332 */ 333 dstopt = 2; 334 } 335 if (m->m_pkthdr.len < hlen + sizeof(ip6e)) { 336 error = EINVAL; 337 goto drop; 338 } 339 /* skip this header */ 340 m_copydata(m, hlen, sizeof(ip6e), 341 (caddr_t)&ip6e); 342 nxt = ip6e.ip6e_nxt; 343 off = hlen + offsetof(struct ip6_ext, ip6e_nxt); 344 /* 345 * we will never see nxt == IPPROTO_AH 346 * so it is safe to omit AH case. 347 */ 348 hlen += (ip6e.ip6e_len + 1) << 3; 349 break; 350 default: 351 goto exitip6loop; 352 } 353 } while (hlen < m->m_pkthdr.len); 354 exitip6loop: 355 break; 356 #endif /* INET6 */ 357 default: 358 error = EINVAL; 359 goto drop; 360 } 361 362 if (m->m_pkthdr.len < hlen) { 363 error = EINVAL; 364 goto drop; 365 } 366 367 ipsecstat_add(ipsec_ouncompbytes, m->m_pkthdr.len); 368 tdb->tdb_ouncompbytes += m->m_pkthdr.len; 369 370 /* Non expansion policy for IPCOMP */ 371 if (tdb->tdb_sproto == IPPROTO_IPCOMP) { 372 if ((m->m_pkthdr.len - hlen) < tdb->tdb_compalgxform->minlen) { 373 /* No need to compress, leave the packet untouched */ 374 ipcompstat_inc(ipcomps_minlen); 375 return ipsp_process_done(m, tdb); 376 } 377 } 378 379 /* Invoke the IPsec transform. */ 380 return (*(tdb->tdb_xform->xf_output))(m, tdb, NULL, hlen, off); 381 382 drop: 383 m_freem(m); 384 return error; 385 } 386 387 /* 388 * IPsec output callback, called directly by the crypto driver. 389 */ 390 void 391 ipsec_output_cb(struct cryptop *crp) 392 { 393 struct tdb_crypto *tc = (struct tdb_crypto *) crp->crp_opaque; 394 struct mbuf *m = (struct mbuf *) crp->crp_buf; 395 struct tdb *tdb = NULL; 396 int error, ilen, olen; 397 398 KERNEL_ASSERT_LOCKED(); 399 400 if (m == NULL) { 401 DPRINTF("bogus returned buffer from crypto"); 402 ipsecstat_inc(ipsec_crypto); 403 goto droponly; 404 } 405 406 NET_LOCK(); 407 tdb = gettdb(tc->tc_rdomain, tc->tc_spi, &tc->tc_dst, tc->tc_proto); 408 if (tdb == NULL) { 409 DPRINTF("TDB is expired while in crypto"); 410 ipsecstat_inc(ipsec_notdb); 411 goto baddone; 412 } 413 414 /* Check for crypto errors. */ 415 if (crp->crp_etype) { 416 if (crp->crp_etype == EAGAIN) { 417 /* Reset the session ID */ 418 if (tdb->tdb_cryptoid != 0) 419 tdb->tdb_cryptoid = crp->crp_sid; 420 NET_UNLOCK(); 421 error = crypto_dispatch(crp); 422 if (error) { 423 DPRINTF("crypto dispatch error %d", error); 424 ipsecstat_inc(ipsec_odrops); 425 tdb->tdb_odrops++; 426 } 427 return; 428 } 429 DPRINTF("crypto error %d", crp->crp_etype); 430 ipsecstat_inc(ipsec_noxform); 431 goto baddone; 432 } 433 434 olen = crp->crp_olen; 435 ilen = crp->crp_ilen; 436 437 /* Release crypto descriptors. */ 438 crypto_freereq(crp); 439 440 switch (tdb->tdb_sproto) { 441 case IPPROTO_ESP: 442 error = esp_output_cb(tdb, tc, m, ilen, olen); 443 break; 444 case IPPROTO_AH: 445 error = ah_output_cb(tdb, tc, m, ilen, olen); 446 break; 447 case IPPROTO_IPCOMP: 448 error = ipcomp_output_cb(tdb, tc, m, ilen, olen); 449 break; 450 default: 451 panic("%s: unknown/unsupported security protocol %d", 452 __func__, tdb->tdb_sproto); 453 } 454 455 NET_UNLOCK(); 456 if (error) { 457 ipsecstat_inc(ipsec_odrops); 458 tdb->tdb_odrops++; 459 } 460 return; 461 462 baddone: 463 NET_UNLOCK(); 464 droponly: 465 if (tdb != NULL) 466 tdb->tdb_odrops++; 467 m_freem(m); 468 free(tc, M_XDATA, 0); 469 crypto_freereq(crp); 470 ipsecstat_inc(ipsec_odrops); 471 } 472 473 /* 474 * Called by the IPsec output transform callbacks, to transmit the packet 475 * or do further processing, as necessary. 476 */ 477 int 478 ipsp_process_done(struct mbuf *m, struct tdb *tdb) 479 { 480 struct ip *ip; 481 #ifdef INET6 482 struct ip6_hdr *ip6; 483 #endif /* INET6 */ 484 struct tdb_ident *tdbi; 485 struct m_tag *mtag; 486 int roff, error; 487 488 tdb->tdb_last_used = gettime(); 489 490 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) { 491 struct mbuf *mi; 492 struct udphdr *uh; 493 int iphlen; 494 495 if (!udpencap_enable || !udpencap_port) { 496 error = ENXIO; 497 goto drop; 498 } 499 500 switch (tdb->tdb_dst.sa.sa_family) { 501 case AF_INET: 502 iphlen = sizeof(struct ip); 503 break; 504 #ifdef INET6 505 case AF_INET6: 506 iphlen = sizeof(struct ip6_hdr); 507 break; 508 #endif /* INET6 */ 509 default: 510 DPRINTF("unknown protocol family (%d)", 511 tdb->tdb_dst.sa.sa_family); 512 error = ENXIO; 513 goto drop; 514 } 515 516 mi = m_makespace(m, iphlen, sizeof(struct udphdr), &roff); 517 if (mi == NULL) { 518 error = ENOMEM; 519 goto drop; 520 } 521 uh = (struct udphdr *)(mtod(mi, caddr_t) + roff); 522 uh->uh_sport = uh->uh_dport = htons(udpencap_port); 523 if (tdb->tdb_udpencap_port) 524 uh->uh_dport = tdb->tdb_udpencap_port; 525 526 uh->uh_ulen = htons(m->m_pkthdr.len - iphlen); 527 uh->uh_sum = 0; 528 #ifdef INET6 529 if (tdb->tdb_dst.sa.sa_family == AF_INET6) 530 m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT; 531 #endif /* INET6 */ 532 espstat_inc(esps_udpencout); 533 } 534 535 switch (tdb->tdb_dst.sa.sa_family) { 536 case AF_INET: 537 /* Fix the header length, for AH processing. */ 538 ip = mtod(m, struct ip *); 539 ip->ip_len = htons(m->m_pkthdr.len); 540 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 541 ip->ip_p = IPPROTO_UDP; 542 break; 543 544 #ifdef INET6 545 case AF_INET6: 546 /* Fix the header length, for AH processing. */ 547 if (m->m_pkthdr.len < sizeof(*ip6)) { 548 error = ENXIO; 549 goto drop; 550 } 551 if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) { 552 /* No jumbogram support. */ 553 error = ENXIO; 554 goto drop; 555 } 556 ip6 = mtod(m, struct ip6_hdr *); 557 ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6)); 558 if ((tdb->tdb_flags & TDBF_UDPENCAP) != 0) 559 ip6->ip6_nxt = IPPROTO_UDP; 560 break; 561 #endif /* INET6 */ 562 563 default: 564 DPRINTF("unknown protocol family (%d)", 565 tdb->tdb_dst.sa.sa_family); 566 error = ENXIO; 567 goto drop; 568 } 569 570 /* 571 * Add a record of what we've done or what needs to be done to the 572 * packet. 573 */ 574 mtag = m_tag_get(PACKET_TAG_IPSEC_OUT_DONE, sizeof(struct tdb_ident), 575 M_NOWAIT); 576 if (mtag == NULL) { 577 DPRINTF("could not allocate packet tag"); 578 error = ENOMEM; 579 goto drop; 580 } 581 582 tdbi = (struct tdb_ident *)(mtag + 1); 583 tdbi->dst = tdb->tdb_dst; 584 tdbi->proto = tdb->tdb_sproto; 585 tdbi->spi = tdb->tdb_spi; 586 tdbi->rdomain = tdb->tdb_rdomain; 587 588 m_tag_prepend(m, mtag); 589 590 ipsecstat_inc(ipsec_opackets); 591 ipsecstat_add(ipsec_obytes, m->m_pkthdr.len); 592 tdb->tdb_opackets++; 593 tdb->tdb_obytes += m->m_pkthdr.len; 594 595 /* If there's another (bundled) TDB to apply, do so. */ 596 if (tdb->tdb_onext) 597 return ipsp_process_packet(m, tdb->tdb_onext, 598 tdb->tdb_dst.sa.sa_family, 0); 599 600 #if NPF > 0 601 /* Add pf tag if requested. */ 602 pf_tag_packet(m, tdb->tdb_tag, -1); 603 pf_pkt_addr_changed(m); 604 #endif 605 if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) 606 m->m_pkthdr.ph_rtableid = tdb->tdb_rdomain_post; 607 608 /* 609 * We're done with IPsec processing, transmit the packet using the 610 * appropriate network protocol (IP or IPv6). SPD lookup will be 611 * performed again there. 612 */ 613 switch (tdb->tdb_dst.sa.sa_family) { 614 case AF_INET: 615 return (ip_output(m, NULL, NULL, IP_RAWOUTPUT, NULL, NULL, 0)); 616 617 #ifdef INET6 618 case AF_INET6: 619 /* 620 * We don't need massage, IPv6 header fields are always in 621 * net endian. 622 */ 623 return (ip6_output(m, NULL, NULL, 0, NULL, NULL)); 624 #endif /* INET6 */ 625 } 626 error = EINVAL; /* Not reached. */ 627 628 drop: 629 m_freem(m); 630 return error; 631 } 632 633 ssize_t 634 ipsec_hdrsz(struct tdb *tdbp) 635 { 636 ssize_t adjust; 637 638 switch (tdbp->tdb_sproto) { 639 case IPPROTO_IPIP: 640 adjust = 0; 641 break; 642 643 case IPPROTO_ESP: 644 if (tdbp->tdb_encalgxform == NULL) 645 return (-1); 646 647 /* Header length */ 648 adjust = 2 * sizeof(u_int32_t) + tdbp->tdb_ivlen; 649 if (tdbp->tdb_flags & TDBF_UDPENCAP) 650 adjust += sizeof(struct udphdr); 651 /* Authenticator */ 652 if (tdbp->tdb_authalgxform != NULL) 653 adjust += tdbp->tdb_authalgxform->authsize; 654 /* Padding */ 655 adjust += MAX(4, tdbp->tdb_encalgxform->blocksize); 656 break; 657 658 case IPPROTO_AH: 659 if (tdbp->tdb_authalgxform == NULL) 660 return (-1); 661 662 adjust = AH_FLENGTH + sizeof(u_int32_t); 663 adjust += tdbp->tdb_authalgxform->authsize; 664 break; 665 666 default: 667 return (-1); 668 } 669 670 if (!(tdbp->tdb_flags & TDBF_TUNNELING) && 671 !(tdbp->tdb_flags & TDBF_USEDTUNNEL)) 672 return (adjust); 673 674 switch (tdbp->tdb_dst.sa.sa_family) { 675 case AF_INET: 676 adjust += sizeof(struct ip); 677 break; 678 #ifdef INET6 679 case AF_INET6: 680 adjust += sizeof(struct ip6_hdr); 681 break; 682 #endif /* INET6 */ 683 } 684 685 return (adjust); 686 } 687 688 void 689 ipsec_adjust_mtu(struct mbuf *m, u_int32_t mtu) 690 { 691 struct tdb_ident *tdbi; 692 struct tdb *tdbp; 693 struct m_tag *mtag; 694 ssize_t adjust; 695 696 NET_ASSERT_LOCKED(); 697 698 for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, NULL); mtag; 699 mtag = m_tag_find(m, PACKET_TAG_IPSEC_OUT_DONE, mtag)) { 700 tdbi = (struct tdb_ident *)(mtag + 1); 701 tdbp = gettdb(tdbi->rdomain, tdbi->spi, &tdbi->dst, 702 tdbi->proto); 703 if (tdbp == NULL) 704 break; 705 706 if ((adjust = ipsec_hdrsz(tdbp)) == -1) 707 break; 708 709 mtu -= adjust; 710 tdbp->tdb_mtu = mtu; 711 tdbp->tdb_mtutimeout = gettime() + ip_mtudisc_timeout; 712 DPRINTF("spi %08x mtu %d adjust %ld mbuf %p", 713 ntohl(tdbp->tdb_spi), tdbp->tdb_mtu, adjust, m); 714 } 715 } 716