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