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