xref: /freebsd/contrib/tcpdump/print-ppi.c (revision 0a7e5f1f)
1cac3dcd5SXin LI /*
2cac3dcd5SXin LI  * Oracle
3cac3dcd5SXin LI  */
43340d773SGleb Smirnoff 
5*ee67461eSJoseph Mingrone /* \summary: Per-Packet Information (DLT_PPI) printer */
6*ee67461eSJoseph Mingrone 
7*ee67461eSJoseph Mingrone /* Specification:
8*ee67461eSJoseph Mingrone  * Per-Packet Information Header Specification - Version 1.0.7
9*ee67461eSJoseph Mingrone  * https://web.archive.org/web/20160328114748/http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf
10*ee67461eSJoseph Mingrone  */
113340d773SGleb Smirnoff 
12*ee67461eSJoseph Mingrone #include <config.h>
13cac3dcd5SXin LI 
14*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
15cac3dcd5SXin LI 
163340d773SGleb Smirnoff #include "netdissect.h"
17cac3dcd5SXin LI #include "extract.h"
183c602fabSXin LI 
19*ee67461eSJoseph Mingrone 
203c602fabSXin LI typedef struct ppi_header {
21*ee67461eSJoseph Mingrone 	nd_uint8_t	ppi_ver;	/* Version.  Currently 0 */
22*ee67461eSJoseph Mingrone 	nd_uint8_t	ppi_flags;	/* Flags. */
23*ee67461eSJoseph Mingrone 	nd_uint16_t	ppi_len;	/* Length of entire message, including
24*ee67461eSJoseph Mingrone 					 * this header and TLV payload. */
25*ee67461eSJoseph Mingrone 	nd_uint32_t	ppi_dlt;	/* Data Link Type of the captured
26*ee67461eSJoseph Mingrone 					 * packet data. */
273c602fabSXin LI } ppi_header_t;
283c602fabSXin LI 
293c602fabSXin LI #define	PPI_HDRLEN	8
30cac3dcd5SXin LI 
31cac3dcd5SXin LI #ifdef DLT_PPI
32cac3dcd5SXin LI 
33*ee67461eSJoseph Mingrone static void
ppi_header_print(netdissect_options * ndo,const u_char * bp,u_int length)343c602fabSXin LI ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
35cac3dcd5SXin LI {
36cac3dcd5SXin LI 	const ppi_header_t *hdr;
373c602fabSXin LI 	uint16_t len;
388bdc5a62SPatrick Kelsey 	uint32_t dlt;
393340d773SGleb Smirnoff 	const char *dltname;
40cac3dcd5SXin LI 
41cac3dcd5SXin LI 	hdr = (const ppi_header_t *)bp;
42cac3dcd5SXin LI 
43*ee67461eSJoseph Mingrone 	len = GET_LE_U_2(hdr->ppi_len);
44*ee67461eSJoseph Mingrone 	dlt = GET_LE_U_4(hdr->ppi_dlt);
453340d773SGleb Smirnoff 	dltname = pcap_datalink_val_to_name(dlt);
46cac3dcd5SXin LI 
47cac3dcd5SXin LI 	if (!ndo->ndo_qflag) {
48*ee67461eSJoseph Mingrone 		ND_PRINT("V.%u DLT %s (%u) len %u", GET_U_1(hdr->ppi_ver),
493340d773SGleb Smirnoff 			  (dltname != NULL ? dltname : "UNKNOWN"), dlt,
50*ee67461eSJoseph Mingrone                           len);
51cac3dcd5SXin LI         } else {
52*ee67461eSJoseph Mingrone 		ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
53cac3dcd5SXin LI         }
54cac3dcd5SXin LI 
55*ee67461eSJoseph Mingrone 	ND_PRINT(", length %u: ", length);
56cac3dcd5SXin LI }
57cac3dcd5SXin LI 
58*ee67461eSJoseph Mingrone /*
59*ee67461eSJoseph Mingrone  * This is the top level routine of the printer.  'p' points
60*ee67461eSJoseph Mingrone  * to the ether header of the packet, 'h->ts' is the timestamp,
61*ee67461eSJoseph Mingrone  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
62*ee67461eSJoseph Mingrone  * is the number of bytes actually captured.
63*ee67461eSJoseph Mingrone  */
64*ee67461eSJoseph Mingrone void
ppi_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)65*ee67461eSJoseph Mingrone ppi_if_print(netdissect_options *ndo,
66cac3dcd5SXin LI 	     const struct pcap_pkthdr *h, const u_char *p)
67cac3dcd5SXin LI {
68cac3dcd5SXin LI 	if_printer printer;
693340d773SGleb Smirnoff 	const ppi_header_t *hdr;
70cac3dcd5SXin LI 	u_int caplen = h->caplen;
71cac3dcd5SXin LI 	u_int length = h->len;
728bdc5a62SPatrick Kelsey 	uint16_t len;
733c602fabSXin LI 	uint32_t dlt;
743340d773SGleb Smirnoff 	uint32_t hdrlen;
753340d773SGleb Smirnoff 	struct pcap_pkthdr nhdr;
76cac3dcd5SXin LI 
77*ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "ppi";
78cac3dcd5SXin LI 	if (caplen < sizeof(ppi_header_t)) {
79*ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
80*ee67461eSJoseph Mingrone 		ndo->ndo_ll_hdr_len += caplen;
81*ee67461eSJoseph Mingrone 		return;
82cac3dcd5SXin LI 	}
838bdc5a62SPatrick Kelsey 
843340d773SGleb Smirnoff 	hdr = (const ppi_header_t *)p;
85*ee67461eSJoseph Mingrone 	len = GET_LE_U_2(hdr->ppi_len);
86*ee67461eSJoseph Mingrone 	if (len < sizeof(ppi_header_t) || len > 65532) {
87*ee67461eSJoseph Mingrone 		/* It MUST be between 8 and 65,532 inclusive (spec 3.1.3) */
88*ee67461eSJoseph Mingrone 		ND_PRINT(" [length %u < %zu or > 65532]", len,
89*ee67461eSJoseph Mingrone 			 sizeof(ppi_header_t));
90*ee67461eSJoseph Mingrone 		nd_print_invalid(ndo);
91*ee67461eSJoseph Mingrone 		ndo->ndo_ll_hdr_len += caplen;
92*ee67461eSJoseph Mingrone 		return;
93*ee67461eSJoseph Mingrone 	}
943340d773SGleb Smirnoff 	if (caplen < len) {
953340d773SGleb Smirnoff 		/*
963340d773SGleb Smirnoff 		 * If we don't have the entire PPI header, don't
973340d773SGleb Smirnoff 		 * bother.
983340d773SGleb Smirnoff 		 */
99*ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
100*ee67461eSJoseph Mingrone 		ndo->ndo_ll_hdr_len += caplen;
101*ee67461eSJoseph Mingrone 		return;
1023340d773SGleb Smirnoff 	}
103*ee67461eSJoseph Mingrone 	dlt = GET_LE_U_4(hdr->ppi_dlt);
104cac3dcd5SXin LI 
105cac3dcd5SXin LI 	if (ndo->ndo_eflag)
106cac3dcd5SXin LI 		ppi_header_print(ndo, p, length);
107cac3dcd5SXin LI 
1088bdc5a62SPatrick Kelsey 	length -= len;
1098bdc5a62SPatrick Kelsey 	caplen -= len;
1108bdc5a62SPatrick Kelsey 	p += len;
111cac3dcd5SXin LI 
112*ee67461eSJoseph Mingrone 	printer = lookup_printer(dlt);
113*ee67461eSJoseph Mingrone 	if (printer != NULL) {
1143340d773SGleb Smirnoff 		nhdr = *h;
1153340d773SGleb Smirnoff 		nhdr.caplen = caplen;
1163340d773SGleb Smirnoff 		nhdr.len = length;
117*ee67461eSJoseph Mingrone 		printer(ndo, &nhdr, p);
118*ee67461eSJoseph Mingrone 		hdrlen = ndo->ndo_ll_hdr_len;
119cac3dcd5SXin LI 	} else {
120cac3dcd5SXin LI 		if (!ndo->ndo_eflag)
1213340d773SGleb Smirnoff 			ppi_header_print(ndo, (const u_char *)hdr, length + len);
122cac3dcd5SXin LI 
123cac3dcd5SXin LI 		if (!ndo->ndo_suppress_default_print)
1243c602fabSXin LI 			ND_DEFAULTPRINT(p, caplen);
1253340d773SGleb Smirnoff 		hdrlen = 0;
126cac3dcd5SXin LI 	}
127*ee67461eSJoseph Mingrone 	ndo->ndo_ll_hdr_len += len + hdrlen;
128cac3dcd5SXin LI }
129cac3dcd5SXin LI #endif /* DLT_PPI */
130