1 /* $NetBSD: uipc_mbufdebug.c,v 1.9 2025/02/16 18:49:59 jakllsch Exp $ */ 2 3 /* 4 * Copyright (C) 2017 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: uipc_mbufdebug.c,v 1.9 2025/02/16 18:49:59 jakllsch Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 35 #include <sys/malloc.h> 36 #include <sys/mbuf.h> 37 #include <sys/proc.h> 38 #include <sys/systm.h> 39 40 #include <net/if.h> 41 #include <net/if_arp.h> 42 #include <net/if_ether.h> 43 #include <net/ppp_defs.h> 44 45 #include <netinet/icmp6.h> 46 #include <netinet/if_inarp.h> 47 #include <netinet/in.h> 48 #include <netinet/in_systm.h> 49 #include <netinet/ip.h> 50 #include <netinet/ip6.h> 51 #include <netinet/ip_icmp.h> 52 #include <netinet/tcp.h> 53 #include <netinet/udp.h> 54 55 #define EXAMINE_HEX_LIMIT 128 56 #define EXAMINE_HEX_COL 4 57 58 /* mbuf operations without change of mbuf chain */ 59 static int m_peek_data(const struct mbuf *, int, int, void *); 60 static unsigned int m_peek_len(const struct mbuf *, const char *); 61 62 /* utility */ 63 static char *str_ethaddr(const uint8_t *); 64 static char *str_ipaddr(const struct in_addr *); 65 static char *str_ip6addr(const struct in6_addr *); 66 static const char *str_ipproto(const uint8_t); 67 68 /* header structure for some protocol */ 69 struct pppoehdr { 70 uint8_t vertype; 71 uint8_t code; 72 uint16_t session; 73 uint16_t plen; 74 } __attribute__((__packed__)); 75 76 struct pppoetag { 77 uint16_t tag; 78 uint16_t len; 79 } __attribute__((__packed__)); 80 81 #define PPPOE_TAG_EOL 0x0000 82 #define PPPOE_CODE_PADI 0x09 /* Active Discovery Initiation */ 83 #define PPPOE_CODE_PADO 0x07 /* Active Discovery Offer */ 84 #define PPPOE_CODE_PADR 0x19 /* Active Discovery Request */ 85 #define PPPOE_CODE_PADS 0x65 /* Active Discovery Session confirmation */ 86 #define PPPOE_CODE_PADT 0xA7 /* Active Discovery Terminate */ 87 88 struct ppp_header { 89 uint8_t address; 90 uint8_t control; 91 uint16_t protocol; 92 } __attribute__((__packed__)); 93 94 #define CISCO_MULTICAST 0x8f /* Cisco multicast address */ 95 #define CISCO_UNICAST 0x0f /* Cisco unicast address */ 96 #define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */ 97 98 #ifndef NELEMS 99 #define NELEMS(elem) ((sizeof(elem))/(sizeof((elem)[0]))) 100 #endif 101 102 static int 103 m_peek_data(const struct mbuf *m, int off, int len, void *vp) 104 { 105 unsigned int count; 106 char *cp = vp; 107 108 if (off < 0 || len < 0) 109 return -1; 110 111 while (off > 0) { 112 if (m == 0) 113 return -1; 114 if (off < m->m_len) 115 break; 116 off -= m->m_len; 117 m = m->m_next; 118 } 119 while (len > 0) { 120 if (m == 0) 121 return -1; 122 count = uimin(m->m_len - off, len); 123 memcpy(cp, mtod(m, char *) + off, count); 124 len -= count; 125 cp += count; 126 off = 0; 127 m = m->m_next; 128 } 129 130 return 0; 131 } 132 133 static unsigned int 134 m_peek_len(const struct mbuf *m, const char *modif) 135 { 136 const struct mbuf *m0; 137 unsigned int pktlen; 138 bool opt_c = false; 139 unsigned char ch; 140 141 while (modif && (ch = *(modif++)) != '\0') { 142 switch (ch) { 143 case 'c': 144 opt_c = true; 145 break; 146 } 147 } 148 149 if (opt_c == true) 150 return m->m_len; 151 152 if ((m->m_flags & M_PKTHDR) != 0) 153 return m->m_pkthdr.len; 154 155 pktlen = 0; 156 for (m0 = m; m0 != NULL; m0 = m0->m_next) 157 pktlen += m0->m_len; 158 159 return pktlen; 160 } 161 162 static char * 163 str_ethaddr(const uint8_t *ap) 164 { 165 static char buf[3 * ETHER_ADDR_LEN]; 166 167 return ether_snprintf(buf, sizeof(buf), ap); 168 } 169 170 static char * 171 str_ipaddr(const struct in_addr *ap) 172 { 173 static char buf[INET_ADDRSTRLEN]; 174 175 return IN_PRINT(buf, ap); 176 } 177 178 static char * 179 str_ip6addr(const struct in6_addr *ap) 180 { 181 static char buf[INET6_ADDRSTRLEN]; 182 183 return IN6_PRINT(buf, ap); 184 } 185 186 static const char * 187 str_ipproto(const uint8_t proto) 188 { 189 190 switch (proto) { 191 case IPPROTO_HOPOPTS: 192 return ("IPv6 Hop-by-Hop"); 193 break; 194 case IPPROTO_TCP: 195 return("TCP"); 196 break; 197 case IPPROTO_UDP: 198 return("UDP"); 199 break; 200 case IPPROTO_ICMP: 201 return("ICMP"); 202 break; 203 case IPPROTO_IGMP: 204 return("IGMP"); 205 break; 206 case IPPROTO_ESP: 207 return("ESP"); 208 break; 209 case IPPROTO_AH: 210 return("AH"); 211 break; 212 case IPPROTO_IPV6_ICMP: 213 return("ICMP6"); 214 default: 215 return("unknown"); 216 break; 217 } 218 219 /* not reached */ 220 return NULL; 221 } 222 223 void 224 m_examine_ether(const struct mbuf *m, int off, const char *modif, 225 void (*pr)(const char *, ...)) 226 { 227 struct ether_header eh; 228 unsigned int pktlen; 229 230 pktlen = m_peek_len(m, modif) - off; 231 if (pktlen < sizeof(eh)) { 232 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 233 pktlen, sizeof(eh)); 234 return m_examine_hex(m, off, modif, pr); 235 } 236 237 if (m_peek_data(m, off, sizeof(eh), (void *)(&eh)) < 0) { 238 (*pr)("%s: cannot read header\n", __func__); 239 return m_examine_hex(m, off, modif, pr); 240 } 241 off += sizeof(eh); 242 243 (*pr)("ETHER: DST = %s\n", str_ethaddr(eh.ether_dhost)); 244 (*pr)("ETHER: SRC = %s\n", str_ethaddr(eh.ether_shost)); 245 246 again: 247 (*pr)("ETHER: TYPE = 0x%04x(", ntohs(eh.ether_type)); 248 switch (ntohs(eh.ether_type)) { 249 case ETHERTYPE_VLAN: 250 (*pr)("VLAN)\n"); 251 252 pktlen = m_peek_len(m, modif) - off; 253 if (pktlen < 4) { 254 return m_examine_hex(m, off, modif, pr); 255 } 256 if (m_peek_data(m, off + 2, sizeof(eh.ether_type), (void *)(&eh.ether_type)) < 0) { 257 (*pr)("%s: cannot read header\n", __func__); 258 return m_examine_hex(m, off, modif, pr); 259 } 260 off += 4; 261 goto again; 262 break; 263 case ETHERTYPE_PPPOE: 264 (*pr)("PPPoE)\n"); 265 return m_examine_pppoe(m, off, modif, pr); 266 break; 267 case ETHERTYPE_ARP: 268 (*pr)("ARP)\n"); 269 return m_examine_arp(m, off, modif, pr); 270 break; 271 case ETHERTYPE_IP: 272 (*pr)("IPv4)\n"); 273 return m_examine_ip(m, off, modif, pr); 274 break; 275 case ETHERTYPE_IPV6: 276 (*pr)("IPv6)\n"); 277 return m_examine_ip6(m, off, modif, pr); 278 break; 279 default: 280 (*pr)("unknown)\n"); 281 break; 282 } 283 284 return m_examine_hex(m, off, modif, pr); 285 } 286 287 void 288 m_examine_pppoe(const struct mbuf *m, int off, const char *modif, 289 void (*pr)(const char *, ...)) 290 { 291 struct pppoehdr ph; 292 struct pppoetag pt; 293 unsigned int pktlen; 294 uint8_t vt; 295 296 pktlen = m_peek_len(m, modif) - off; 297 if (pktlen < sizeof(ph)) { 298 (*pr)("%s: too short mbuf chain (%u, %u)\n", __func__, 299 pktlen, sizeof(ph)); 300 return m_examine_hex(m, off, modif, pr); 301 } 302 303 if (m_peek_data(m, off, sizeof(ph), (void *)(&ph)) < 0) { 304 (*pr)("%s: cannot read header\n", __func__); 305 return m_examine_hex(m, off, modif, pr); 306 } 307 off += sizeof(ph); 308 309 while (off + sizeof(pt) > pktlen) { 310 if (m_peek_data(m, off, sizeof(pt), (void *)(&pt)) < 0) { 311 (*pr)("%s: cannot read header\n", __func__); 312 return m_examine_hex(m, off, modif, pr); 313 } 314 off += sizeof(pt); 315 316 if (ntohs(pt.tag) == PPPOE_TAG_EOL) 317 break; 318 off += ntohs(pt.len); 319 } 320 321 vt = ph.vertype; 322 323 (*pr)("PPPoE: Version = %u\n", ((vt >> 4) & 0xff)); 324 (*pr)("PPPoE: Type = %u\n", (vt & 0xff)); 325 (*pr)("PPPoE: Code = %u(", ph.code); 326 switch (ph.code) { 327 case 0: 328 (*pr)("DATA"); 329 break; 330 case PPPOE_CODE_PADI: 331 (*pr)("PADI"); 332 break; 333 case PPPOE_CODE_PADO: 334 (*pr)("PADO"); 335 break; 336 case PPPOE_CODE_PADS: 337 (*pr)("PADS"); 338 break; 339 case PPPOE_CODE_PADT: 340 (*pr)("PADT"); 341 break; 342 default: 343 (*pr)("unknown"); 344 break; 345 } 346 (*pr)(")\n"); 347 348 (*pr)("PPPoE: Session = 0x%04x\n", ntohs(ph.session)); 349 (*pr)("PPPoE: Payload Length = %u\n", ntohs(ph.plen)); 350 351 switch (ph.code) { 352 case PPPOE_CODE_PADI: 353 case PPPOE_CODE_PADO: 354 case PPPOE_CODE_PADS: 355 case PPPOE_CODE_PADT: 356 (*pr)("No parser for PPPoE control frame.\n"); 357 return m_examine_hex(m, off, modif, pr); 358 break; 359 } 360 361 if (ph.code != 0) { 362 (*pr)("Unknown PPPoE code.\n"); 363 return m_examine_hex(m, off, modif, pr); 364 } 365 366 return m_examine_ppp(m, off, modif, pr); 367 } 368 369 void 370 m_examine_ppp(const struct mbuf *m, int off, const char *modif, 371 void (*pr)(const char *, ...)) 372 { 373 struct ppp_header h; 374 unsigned int pktlen; 375 uint16_t protocol; 376 377 pktlen = m_peek_len(m, modif) - off; 378 if (pktlen < sizeof(h)) { 379 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 380 pktlen, sizeof(h)); 381 return m_examine_hex(m, off, modif, pr); 382 } 383 384 if (m_peek_data(m, off, sizeof(h), (void *)(&h)) < 0) { 385 (*pr)("%s: cannot read header\n", __func__); 386 return m_examine_hex(m, off, modif, pr); 387 } 388 off += sizeof(h); 389 390 protocol = ntohs(h.protocol); 391 392 (*pr)("SPPP: Address = %d(", h.address); 393 switch (h.address) { 394 case PPP_ALLSTATIONS: 395 (*pr)("ALLSTATIONS)\n"); 396 (*pr)("SPPP: Protocol = %d(", protocol); 397 switch (protocol) { 398 case PPP_LCP: 399 (*pr)("LCP)\n"); 400 break; 401 case PPP_PAP: 402 (*pr)("PAP)\n"); 403 break; 404 case PPP_CHAP: 405 (*pr)("CHAP)\n"); 406 break; 407 case PPP_IPCP: 408 (*pr)("IPCP)\n"); 409 break; 410 case PPP_IPV6CP: 411 (*pr)("IPV6CP)\n"); 412 break; 413 case PPP_IP: 414 (*pr)("IP)\n"); 415 return m_examine_ip(m, off, modif, pr); 416 break; 417 case PPP_IPV6: 418 (*pr)("IPv6)\n"); 419 return m_examine_ip6(m, off, modif, pr); 420 break; 421 default: 422 (*pr)("unknown)\n"); 423 break; 424 } 425 break; 426 case CISCO_MULTICAST: 427 case CISCO_UNICAST: 428 if (h.address == CISCO_MULTICAST) 429 (*pr)("MULTICAST)\n"); 430 else 431 (*pr)("UNICAST)\n"); 432 433 (*pr)("SPPP: Protocol = %d(", protocol); 434 switch (protocol) { 435 case CISCO_KEEPALIVE: 436 (*pr)("Keepalive)\n"); 437 break; 438 case ETHERTYPE_IP: 439 (*pr)("IP)\n"); 440 return m_examine_ip(m, off, modif, pr); 441 break; 442 case ETHERTYPE_IPV6: 443 (*pr)("IPv6)\n"); 444 return m_examine_ip6(m, off, modif, pr); 445 break; 446 default: 447 (*pr)("unknown)\n"); 448 break; 449 } 450 break; 451 default: 452 (*pr)("unknown)\n", h.address); 453 break; 454 } 455 456 (*pr)("No parser for address %d, protocol %d\n", h.address, protocol); 457 return m_examine_hex(m, off, modif, pr); 458 } 459 460 void 461 m_examine_arp(const struct mbuf *m, int off, const char *modif, 462 void (*pr)(const char *, ...)) 463 { 464 unsigned int pktlen; 465 struct arphdr ar; 466 uint16_t hrd, op; 467 struct in_addr isaddr, itaddr; 468 uint8_t esaddr[ETHER_ADDR_LEN], etaddr[ETHER_ADDR_LEN]; 469 470 pktlen = m_peek_len(m, modif) - off; 471 if (pktlen < sizeof(ar)) { 472 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 473 pktlen, sizeof(ar)); 474 return m_examine_hex(m, off, modif, pr); 475 } 476 477 if (m_peek_data(m, off, sizeof(ar), (void *)(&ar)) < 0) { 478 (*pr)("%s: cannot read header\n", __func__); 479 return m_examine_hex(m, off, modif, pr); 480 } 481 off += sizeof(ar); 482 483 hrd = ntohs(ar.ar_hrd); 484 (*pr)("ARP: AddressType = %u(", hrd); 485 switch (hrd) { 486 case ARPHRD_ETHER: 487 (*pr)("ETHER)\n"); 488 break; 489 case ARPHRD_IEEE802: 490 (*pr)("IEEE802)\n"); 491 break; 492 default: 493 (*pr)("unknown)\n"); 494 return m_examine_hex(m, off, modif, pr); 495 break; 496 } 497 (*pr)("ARP: Protocol Address Format = %u\n", ntohs(ar.ar_pro)); 498 (*pr)("ARP: Protocol Address Length = %u\n", ar.ar_pln); 499 (*pr)("ARP: H/W Address Length = %u\n", ar.ar_hln); 500 op = ntohs(ar.ar_op); 501 (*pr)("ARP: Operation = %u(", op); 502 switch (op) { 503 case ARPOP_REQUEST: 504 (*pr)("REQUEST)\n"); 505 break; 506 case ARPOP_REPLY: 507 (*pr)("REPLY)\n"); 508 break; 509 case ARPOP_REVREQUEST: 510 (*pr)("REVREQUEST)\n"); 511 break; 512 case ARPOP_REVREPLY: 513 (*pr)("REVREPLY)\n"); 514 break; 515 case ARPOP_INVREQUEST: 516 (*pr)("INVREQUEST)\n"); 517 break; 518 case ARPOP_INVREPLY: 519 (*pr)("INVREPLY)\n"); 520 break; 521 } 522 523 if (ar.ar_hln == 0 || ar.ar_pln == 0 || 524 ar.ar_hln != sizeof(esaddr) || ar.ar_pln != sizeof(isaddr)) { 525 (*pr)("Cannot parse.\n"); 526 return m_examine_hex(m, off, modif, pr); 527 } 528 529 if (m_peek_data(m, off, sizeof(esaddr), (void *)(esaddr)) < 0) { 530 (*pr)("Cannot read payload\n"); 531 return m_examine_hex(m, off, modif, pr); 532 } 533 off += sizeof(esaddr); 534 (*pr)("ARP: Ether Src = %s\n", str_ethaddr(esaddr)); 535 536 if (m_peek_data(m, off, sizeof(isaddr), (void *)(&isaddr)) < 0) { 537 (*pr)("Cannot read payload\n"); 538 return m_examine_hex(m, off, modif, pr); 539 } 540 off += sizeof(isaddr); 541 (*pr)("ARP: IP Src = %s\n", str_ipaddr(&isaddr)); 542 543 if (m_peek_data(m, off, sizeof(etaddr), (void *)(etaddr)) < 0) { 544 (*pr)("Cannot read payload\n"); 545 return m_examine_hex(m, off, modif, pr); 546 } 547 off += sizeof(etaddr); 548 (*pr)("ARP: Ether Tgt = %s\n", str_ethaddr(etaddr)); 549 550 if (m_peek_data(m, off, sizeof(itaddr), (void *)(&itaddr)) < 0) { 551 (*pr)("Cannot read payload\n"); 552 return m_examine_hex(m, off, modif, pr); 553 } 554 off += sizeof(itaddr); 555 (*pr)("ARP: IP Tgt = %s\n", str_ipaddr(&itaddr)); 556 557 return m_examine_hex(m, off, modif, pr); 558 } 559 560 void 561 m_examine_ip(const struct mbuf *m, int off, const char *modif, 562 void (*pr)(const char *, ...)) 563 { 564 unsigned int pktlen; 565 struct ip ip; 566 uint16_t offset; 567 568 pktlen = m_peek_len(m, modif) - off; 569 if (pktlen < sizeof(ip)) { 570 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 571 pktlen, sizeof(ip)); 572 return m_examine_hex(m, off, modif, pr); 573 } 574 575 if (m_peek_data(m, off, sizeof(ip), (void *)(&ip)) < 0) { 576 (*pr)("%s: cannot read header\n", __func__); 577 return m_examine_hex(m, off, modif, pr); 578 } 579 off += sizeof(ip); 580 581 (*pr)("IP: Version = %u\n", ip.ip_v); 582 (*pr)("IP: Header Length = %u\n", (ip.ip_hl << 2)); 583 (*pr)("IP: ToS = 0x%02x\n", ip.ip_tos); 584 (*pr)("IP: Packet Length = %u\n", ntohs(ip.ip_len)); 585 (*pr)("IP: ID = %u\n", ntohs(ip.ip_id)); 586 offset = ntohs(ip.ip_off); 587 (*pr)("IP: Offset = %u\n", (offset & IP_OFFMASK)); 588 if (offset & IP_RF) 589 (*pr)("IP: Flag 0x%04x (reserved)\n", IP_RF); 590 if (offset & IP_EF) 591 (*pr)("IP: Flag 0x%04x (evil flag)\n", IP_EF); 592 if (offset & IP_DF) 593 (*pr)("IP: Flag 0x%04x (don't fragment)\n", IP_DF); 594 if (offset & IP_MF) 595 (*pr)("IP: Flag 0x%04x (more fragment)\n", IP_MF); 596 (*pr)("IP: TTL = %u\n", ip.ip_ttl); 597 (*pr)("IP: protocol = %u(%s)\n", ip.ip_p, str_ipproto(ip.ip_p)); 598 (*pr)("IP: checksum = 0x%04x\n", ntohs(ip.ip_sum)); 599 (*pr)("IP: Src = %s\n", str_ipaddr(&ip.ip_src)); 600 (*pr)("IP: Dst = %s\n", str_ipaddr(&ip.ip_dst)); 601 602 switch (ip.ip_p) { 603 case IPPROTO_ICMP: 604 return m_examine_icmp(m, off, modif, pr); 605 break; 606 case IPPROTO_TCP: 607 return m_examine_tcp(m, off, modif, pr); 608 break; 609 case IPPROTO_UDP: 610 return m_examine_udp(m, off, modif, pr); 611 break; 612 default: 613 break; 614 } 615 616 return m_examine_hex(m, off, modif, pr); 617 } 618 619 void 620 m_examine_icmp(const struct mbuf *m, int off, const char *modif, 621 void (*pr)(const char *, ...)) 622 { 623 unsigned int pktlen; 624 struct icmp icmphdr; 625 626 pktlen = m_peek_len(m, modif) - off; 627 if (pktlen < sizeof(icmphdr)) { 628 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 629 pktlen, sizeof(icmphdr)); 630 return m_examine_hex(m, off, modif, pr); 631 } 632 633 if (m_peek_data(m, off, sizeof(icmphdr), (void *)(&icmphdr)) < 0) { 634 (*pr)("%s: cannot read header\n", __func__); 635 return m_examine_hex(m, off, modif, pr); 636 } 637 off += sizeof(icmphdr); 638 639 (*pr)("ICMP: Type = %u(", icmphdr.icmp_type); 640 switch (icmphdr.icmp_type) { 641 case ICMP_ECHOREPLY: 642 (*pr)("Echo Reply)\n"); 643 break; 644 case ICMP_UNREACH: 645 (*pr)("Destination Unreachable)\n"); 646 break; 647 case ICMP_SOURCEQUENCH: 648 (*pr)("Source Quench)\n"); 649 break; 650 case ICMP_REDIRECT: 651 (*pr)("Redirect)\n"); 652 break; 653 case ICMP_TIMXCEED: 654 (*pr)("Time Exceeded)\n"); 655 break; 656 default: 657 (*pr)("unknown)\n"); 658 break; 659 } 660 (*pr)("ICMP: Code = %d\n", icmphdr.icmp_code); 661 662 return m_examine_hex(m, off, modif, pr); 663 } 664 665 void 666 m_examine_ip6(const struct mbuf *m, int off, const char *modif, 667 void (*pr)(const char *, ...)) 668 { 669 unsigned int pktlen; 670 struct ip6_hdr ip6; 671 struct ip6_hbh hbh; 672 int hbhlen; 673 uint32_t flow; 674 uint8_t vfc; 675 uint8_t nxt; 676 677 pktlen = m_peek_len(m, modif) - off; 678 if (pktlen < sizeof(ip6)) { 679 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 680 pktlen, sizeof(ip6)); 681 return m_examine_hex(m, off, modif, pr); 682 } 683 684 if (m_peek_data(m, off, sizeof(ip6), (void *)(&ip6)) < 0) { 685 (*pr)("%s: cannot read header\n", __func__); 686 return m_examine_hex(m, off, modif, pr); 687 } 688 off += sizeof(ip6); 689 690 vfc = ip6.ip6_vfc; 691 (*pr)("IPv6: Version = %u\n", (vfc & IPV6_VERSION_MASK) >> 4); 692 flow = ntohl(ip6.ip6_flow); 693 (*pr)("IPv6: Flow INFO = 0x%07x\n", flow & IPV6_FLOWINFO_MASK); 694 (*pr)("IPv6: Payload Length = %u\n", ntohs(ip6.ip6_plen)); 695 nxt = ip6.ip6_nxt; 696 (*pr)("IPv6: Next Header = %u(%s)\n", nxt, str_ipproto(nxt)); 697 (*pr)("IPv6: Hop Limit = %u\n", ip6.ip6_hlim); 698 (*pr)("IPv6: Src = %s\n", str_ip6addr(&ip6.ip6_src)); 699 (*pr)("IPv6: Dst = %s\n", str_ip6addr(&ip6.ip6_dst)); 700 701 /* Strip Hop-by-Hop options */ 702 if (nxt == IPPROTO_HOPOPTS) { 703 if (m_peek_data(m, off, sizeof(hbh), (void *)(&hbh)) < 0) { 704 (*pr)("Cannot read option\n"); 705 return m_examine_hex(m, off, modif, pr); 706 } 707 hbhlen = (hbh.ip6h_len + 1) << 3; 708 nxt = hbh.ip6h_nxt; 709 off += hbhlen; 710 711 (*pr)("IPv6: Stripped Hop-by-Hop\n"); 712 (*pr)("IPv6: Next Header = %u(%s)\n", nxt, str_ipproto(nxt)); 713 } 714 715 switch (nxt) { 716 case IPPROTO_IPV6_ICMP: 717 return m_examine_icmp6(m, off, modif, pr); 718 break; 719 case IPPROTO_TCP: 720 return m_examine_tcp(m, off, modif, pr); 721 break; 722 case IPPROTO_UDP: 723 return m_examine_udp(m, off, modif, pr); 724 break; 725 default: 726 break; 727 } 728 729 return m_examine_hex(m, off, modif, pr); 730 } 731 732 void 733 m_examine_icmp6(const struct mbuf *m, int off, const char *modif, 734 void (*pr)(const char *, ...)) 735 { 736 unsigned int pktlen; 737 struct icmp6_hdr icmp6; 738 739 pktlen = m_peek_len(m, modif) - off; 740 if (pktlen < sizeof(icmp6)) { 741 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 742 pktlen, sizeof(icmp6)); 743 return m_examine_hex(m, off, modif, pr); 744 } 745 746 if (m_peek_data(m, off, sizeof(icmp6), (void *)(&icmp6)) < 0) { 747 (*pr)("%s: cannot read header\n", __func__); 748 return m_examine_hex(m, off, modif, pr); 749 } 750 off += sizeof(icmp6); 751 752 (*pr)("ICMP6: Type = %u(", icmp6.icmp6_type); 753 switch (icmp6.icmp6_type) { 754 case ICMP6_DST_UNREACH: 755 (*pr)("Destination Unreachable)\n"); 756 break; 757 case ICMP6_PACKET_TOO_BIG: 758 (*pr)("Packet Too Big)\n"); 759 break; 760 case ICMP6_TIME_EXCEEDED: 761 (*pr)("Time Exceeded)\n"); 762 break; 763 case ICMP6_PARAM_PROB: 764 (*pr)("Parameter Problem)\n"); 765 break; 766 case ICMP6_ECHO_REQUEST: 767 (*pr)("Echo Request)\n"); 768 break; 769 case ICMP6_ECHO_REPLY: 770 (*pr)("Echo Reply)\n"); 771 break; 772 773 case MLD_LISTENER_QUERY: 774 (*pr)("MLD Listener Query)\n"); 775 break; 776 case MLD_LISTENER_REPORT: 777 (*pr)("MLD Listener Report)\n"); 778 break; 779 case MLD_LISTENER_DONE: 780 (*pr)("MLD Listener Done)\n"); 781 break; 782 783 case ND_ROUTER_SOLICIT: 784 (*pr)("Router Solicitation)\n"); 785 break; 786 case ND_ROUTER_ADVERT: 787 (*pr)("Router Advertizement)\n"); 788 break; 789 case ND_NEIGHBOR_SOLICIT: 790 (*pr)("Neighbor Solicitation)\n"); 791 break; 792 case ND_NEIGHBOR_ADVERT: 793 (*pr)("Neighbor Advertizement)\n"); 794 break; 795 case ND_REDIRECT: 796 (*pr)("Redirect)\n"); 797 break; 798 799 default: 800 (*pr)("unknown)\n"); 801 break; 802 } 803 (*pr)("ICMP6: Code = %u\n", icmp6.icmp6_code); 804 805 return m_examine_hex(m, off, modif, pr); 806 } 807 808 void 809 m_examine_tcp(const struct mbuf *m, int off, const char *modif, 810 void (*pr)(const char *, ...)) 811 { 812 unsigned int pktlen; 813 struct tcphdr tcp; 814 815 pktlen = m_peek_len(m, modif) - off; 816 if (pktlen < sizeof(tcp)) { 817 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 818 pktlen, sizeof(tcp)); 819 return m_examine_hex(m, off, modif, pr); 820 } 821 822 if (m_peek_data(m, off, sizeof(tcp), (void *)(&tcp)) < 0) { 823 (*pr)("%s: cannot read header\n", __func__); 824 return m_examine_hex(m, off, modif, pr); 825 } 826 off += sizeof(tcp); 827 828 (*pr)("TCP: Src = %u\n", ntohs(tcp.th_sport)); 829 (*pr)("TCP: Dst = %u\n", ntohs(tcp.th_dport)); 830 (*pr)("TCP: Seq. = %u\n", ntohl(tcp.th_seq)); 831 (*pr)("TCP: Ack. = %u\n", ntohl(tcp.th_ack)); 832 (*pr)("TCP: Header Length = %u\n", tcp.th_off << 2); 833 if (tcp.th_flags) { 834 (*pr)("TCP: Flags 0x%02x : ", tcp.th_flags); 835 if (tcp.th_flags & TH_FIN) 836 (*pr)("FIN "); 837 if (tcp.th_flags & TH_SYN) 838 (*pr)("SYN "); 839 if (tcp.th_flags & TH_RST) 840 (*pr)("RST "); 841 if (tcp.th_flags & TH_PUSH) 842 (*pr)("PUSH "); 843 if (tcp.th_flags & TH_URG) 844 (*pr)("URG "); 845 if (tcp.th_flags & TH_ECE) 846 (*pr)("ECE "); 847 if (tcp.th_flags & TH_CWR) 848 (*pr)("CWR "); 849 (*pr)("\n"); 850 } 851 (*pr)("TCP: Windows Size = %u\n", ntohs(tcp.th_win)); 852 (*pr)("TCP: checksum = 0x%04x\n", ntohs(tcp.th_sum)); 853 (*pr)("TCP: Urgent Pointer = %u\n", ntohs(tcp.th_urp)); 854 855 int len; 856 len = (tcp.th_off << 2) - sizeof(struct tcphdr); 857 if (len > 0) { 858 uint8_t *bufp, *op, opt, optlen; 859 860 bufp = malloc(len, M_TEMP, M_DONTWAIT); 861 if ((bufp == NULL) || (m_peek_data(m, off, len, bufp) < 0)) { 862 (*pr)("%s: cannot read TCP option\n", __func__); 863 if (bufp != NULL) 864 free(bufp, M_TEMP); 865 return m_examine_hex(m, off, modif, pr); 866 } 867 off += len; 868 op = bufp; 869 870 while (len > 0) { 871 opt = op[0]; 872 if (opt == TCPOPT_EOL) 873 break; 874 if (opt == TCPOPT_NOP) { 875 (*pr)("TCP: OPTION: NOP\n"); 876 op++; 877 len--; 878 continue; 879 } 880 if (opt == TCPOPT_PAD) { 881 (*pr)("TCP: OPTION: PAD\n"); 882 op++; 883 len--; 884 continue; 885 } 886 optlen = op[1]; 887 if (optlen == 0) 888 break; 889 890 if (opt == TCPOPT_MAXSEG && optlen == TCPOLEN_MAXSEG) { 891 uint16_t mss; 892 893 bcopy(op + 2, &mss, sizeof(mss)); 894 (*pr)("TCP: OPTION: MSS = %d\n", 895 ntohs(mss)); 896 897 op += optlen; 898 len -= optlen; 899 continue; 900 } else if (opt == TCPOPT_WINDOW 901 && optlen == TCPOLEN_WINDOW) { 902 (*pr)("TCP: OPTION: wscale = %d\n", op[2]); 903 op += optlen; 904 len -= optlen; 905 continue; 906 } else if (opt == TCPOPT_SACK_PERMITTED 907 && optlen == TCPOLEN_SACK_PERMITTED) { 908 (*pr)("TCP: OPTION: SACK OK\n"); 909 op += optlen; 910 len -= optlen; 911 continue; 912 } else if (opt == TCPOPT_TIMESTAMP 913 && optlen == TCPOLEN_TIMESTAMP) { 914 uint32_t ts_val, ts_ecr; 915 916 memcpy(&ts_val, op + 2, sizeof(ts_val)); 917 memcpy(&ts_ecr, op + 6, sizeof(ts_ecr)); 918 (*pr)("TCP: OPTION: TIMESTAMP = %u, " 919 "ECR = %u\n", 920 ntohl(ts_val), ntohl(ts_ecr)); 921 op += optlen; 922 len -= optlen; 923 continue; 924 } else { 925 (*pr)("TCP: OPTION: unknown (%d, len = %d)\n", 926 opt, optlen); 927 op += optlen; 928 len -= optlen; 929 continue; 930 } 931 } 932 free(bufp, M_TEMP); 933 } 934 935 if (off < pktlen) 936 m_examine_hex(m, off, modif, pr); 937 938 return; 939 } 940 941 void 942 m_examine_udp(const struct mbuf *m, int off, const char *modif, 943 void (*pr)(const char *, ...)) 944 { 945 unsigned int pktlen; 946 struct udphdr udp; 947 948 pktlen = m_peek_len(m, modif) - off; 949 if (pktlen < sizeof(udp)) { 950 (*pr)("%s: too short mbuf chain (%u < %u)\n", __func__, 951 pktlen, sizeof(udp)); 952 return m_examine_hex(m, off, modif, pr); 953 } 954 955 if (m_peek_data(m, off, sizeof(udp), (void *)(&udp)) < 0) { 956 (*pr)("%s: cannot read header\n", __func__); 957 return m_examine_hex(m, off, modif, pr); 958 } 959 off += sizeof(udp); 960 961 (*pr)("UDP: Src = %u\n", ntohs(udp.uh_sport)); 962 (*pr)("UDP: Dst = %u\n", ntohs(udp.uh_dport)); 963 (*pr)("UDP: Length = %u\n", ntohs(udp.uh_ulen)); 964 965 return m_examine_hex(m, off, modif, pr); 966 } 967 968 void 969 m_examine_hex(const struct mbuf *m, int off, const char *modif, 970 void (*pr)(const char *, ...)) 971 { 972 unsigned int pktlen; 973 int newline = 0; 974 uint8_t v; 975 976 pktlen = m_peek_len(m, modif) - off; 977 if (pktlen > EXAMINE_HEX_LIMIT) 978 pktlen = EXAMINE_HEX_LIMIT; 979 980 if (pktlen == 0) 981 return; 982 983 (*pr)("offset %04d: ", off); 984 while (pktlen > 0) { 985 if (m_peek_data(m, off, sizeof(v), (void *)(&v)) < 0) 986 break; 987 pktlen --; 988 off++; 989 newline++; 990 991 (*pr)("%02x", v); 992 if (pktlen == 0) 993 break; 994 995 if ((newline % EXAMINE_HEX_COL) == 0) { 996 (*pr)("\n"); 997 (*pr)("offset %04d: ", off); 998 } else 999 (*pr)(" "); 1000 } 1001 (*pr)("\n"); 1002 } 1003 1004 void 1005 m_examine(const struct mbuf *m, int af, const char *modif, 1006 void (*pr)(const char *, ...)) 1007 { 1008 if (m == NULL) 1009 return; 1010 1011 if (pr == NULL) 1012 return; 1013 1014 switch (af) { 1015 case AF_UNSPEC: 1016 return m_examine_hex(m, 0, modif, pr); 1017 break; 1018 case AF_ETHER: 1019 return m_examine_ether(m, 0, modif, pr); 1020 break; 1021 case AF_ARP: 1022 return m_examine_arp(m, 0, modif, pr); 1023 break; 1024 case AF_INET: 1025 return m_examine_ip(m, 0, modif, pr); 1026 break; 1027 case AF_INET6: 1028 return m_examine_ip6(m, 0, modif, pr); 1029 break; 1030 default: 1031 (*pr)("No parser for AF %d\n", af); 1032 return m_examine_hex(m, 0, modif, pr); 1033 break; 1034 } 1035 1036 /* not reached */ 1037 return; 1038 } 1039