xref: /netbsd-src/external/bsd/tcpdump/dist/print-ppi.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
19546e36dSchristos /*
29546e36dSchristos  * Oracle
39546e36dSchristos  */
4784088dfSchristos 
5fdccd7e4Schristos #include <sys/cdefs.h>
6fdccd7e4Schristos #ifndef lint
7*26ba0b50Schristos __RCSID("$NetBSD: print-ppi.c,v 1.6 2024/09/02 16:15:32 christos Exp $");
8fdccd7e4Schristos #endif
9fdccd7e4Schristos 
10c74ad251Schristos /* \summary: Per-Packet Information (DLT_PPI) printer */
11c74ad251Schristos 
12c74ad251Schristos /* Specification:
13c74ad251Schristos  * Per-Packet Information Header Specification - Version 1.0.7
14c74ad251Schristos  * https://web.archive.org/web/20160328114748/http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf
15c74ad251Schristos  */
16dc860a36Sspz 
17c74ad251Schristos #include <config.h>
189546e36dSchristos 
19c74ad251Schristos #include "netdissect-stdinc.h"
209546e36dSchristos 
21784088dfSchristos #include "netdissect.h"
229546e36dSchristos #include "extract.h"
23c47fd378Schristos 
24c74ad251Schristos 
25c47fd378Schristos typedef struct ppi_header {
26c74ad251Schristos 	nd_uint8_t	ppi_ver;	/* Version.  Currently 0 */
27c74ad251Schristos 	nd_uint8_t	ppi_flags;	/* Flags. */
28c74ad251Schristos 	nd_uint16_t	ppi_len;	/* Length of entire message, including
29c74ad251Schristos 					 * this header and TLV payload. */
30c74ad251Schristos 	nd_uint32_t	ppi_dlt;	/* Data Link Type of the captured
31c74ad251Schristos 					 * packet data. */
32c47fd378Schristos } ppi_header_t;
33c47fd378Schristos 
34c47fd378Schristos #define	PPI_HDRLEN	8
359546e36dSchristos 
369546e36dSchristos #ifdef DLT_PPI
379546e36dSchristos 
38c74ad251Schristos static void
39c47fd378Schristos ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
409546e36dSchristos {
419546e36dSchristos 	const ppi_header_t *hdr;
42c47fd378Schristos 	uint16_t len;
433d25ea14Schristos 	uint32_t dlt;
44dc860a36Sspz 	const char *dltname;
459546e36dSchristos 
469546e36dSchristos 	hdr = (const ppi_header_t *)bp;
479546e36dSchristos 
48c74ad251Schristos 	len = GET_LE_U_2(hdr->ppi_len);
49c74ad251Schristos 	dlt = GET_LE_U_4(hdr->ppi_dlt);
50dc860a36Sspz 	dltname = pcap_datalink_val_to_name(dlt);
519546e36dSchristos 
529546e36dSchristos 	if (!ndo->ndo_qflag) {
53c74ad251Schristos 		ND_PRINT("V.%u DLT %s (%u) len %u", GET_U_1(hdr->ppi_ver),
54dc860a36Sspz 			  (dltname != NULL ? dltname : "UNKNOWN"), dlt,
55c74ad251Schristos                           len);
569546e36dSchristos         } else {
57c74ad251Schristos 		ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
589546e36dSchristos         }
599546e36dSchristos 
60c74ad251Schristos 	ND_PRINT(", length %u: ", length);
619546e36dSchristos }
629546e36dSchristos 
63c74ad251Schristos /*
64c74ad251Schristos  * This is the top level routine of the printer.  'p' points
65c74ad251Schristos  * to the ether header of the packet, 'h->ts' is the timestamp,
66c74ad251Schristos  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
67c74ad251Schristos  * is the number of bytes actually captured.
68c74ad251Schristos  */
69c74ad251Schristos void
70c74ad251Schristos ppi_if_print(netdissect_options *ndo,
719546e36dSchristos 	     const struct pcap_pkthdr *h, const u_char *p)
729546e36dSchristos {
739546e36dSchristos 	if_printer printer;
74784088dfSchristos 	const ppi_header_t *hdr;
759546e36dSchristos 	u_int caplen = h->caplen;
769546e36dSchristos 	u_int length = h->len;
773d25ea14Schristos 	uint16_t len;
78c47fd378Schristos 	uint32_t dlt;
79784088dfSchristos 	uint32_t hdrlen;
80784088dfSchristos 	struct pcap_pkthdr nhdr;
819546e36dSchristos 
82c74ad251Schristos 	ndo->ndo_protocol = "ppi";
839546e36dSchristos 	if (caplen < sizeof(ppi_header_t)) {
84c74ad251Schristos 		nd_print_trunc(ndo);
85c74ad251Schristos 		ndo->ndo_ll_hdr_len += caplen;
86c74ad251Schristos 		return;
879546e36dSchristos 	}
883d25ea14Schristos 
89784088dfSchristos 	hdr = (const ppi_header_t *)p;
90c74ad251Schristos 	len = GET_LE_U_2(hdr->ppi_len);
91c74ad251Schristos 	if (len < sizeof(ppi_header_t) || len > 65532) {
92c74ad251Schristos 		/* It MUST be between 8 and 65,532 inclusive (spec 3.1.3) */
93c74ad251Schristos 		ND_PRINT(" [length %u < %zu or > 65532]", len,
94c74ad251Schristos 			 sizeof(ppi_header_t));
95c74ad251Schristos 		nd_print_invalid(ndo);
96c74ad251Schristos 		ndo->ndo_ll_hdr_len += caplen;
97c74ad251Schristos 		return;
98c74ad251Schristos 	}
99784088dfSchristos 	if (caplen < len) {
100784088dfSchristos 		/*
101784088dfSchristos 		 * If we don't have the entire PPI header, don't
102784088dfSchristos 		 * bother.
103784088dfSchristos 		 */
104c74ad251Schristos 		nd_print_trunc(ndo);
105c74ad251Schristos 		ndo->ndo_ll_hdr_len += caplen;
106c74ad251Schristos 		return;
107784088dfSchristos 	}
108c74ad251Schristos 	dlt = GET_LE_U_4(hdr->ppi_dlt);
1099546e36dSchristos 
1109546e36dSchristos 	if (ndo->ndo_eflag)
1119546e36dSchristos 		ppi_header_print(ndo, p, length);
1129546e36dSchristos 
1133d25ea14Schristos 	length -= len;
1143d25ea14Schristos 	caplen -= len;
1153d25ea14Schristos 	p += len;
1169546e36dSchristos 
117c74ad251Schristos 	printer = lookup_printer(dlt);
118c74ad251Schristos 	if (printer != NULL) {
119784088dfSchristos 		nhdr = *h;
120784088dfSchristos 		nhdr.caplen = caplen;
121784088dfSchristos 		nhdr.len = length;
122c74ad251Schristos 		printer(ndo, &nhdr, p);
123c74ad251Schristos 		hdrlen = ndo->ndo_ll_hdr_len;
1249546e36dSchristos 	} else {
1259546e36dSchristos 		if (!ndo->ndo_eflag)
126784088dfSchristos 			ppi_header_print(ndo, (const u_char *)hdr, length + len);
1279546e36dSchristos 
1289546e36dSchristos 		if (!ndo->ndo_suppress_default_print)
129c47fd378Schristos 			ND_DEFAULTPRINT(p, caplen);
130784088dfSchristos 		hdrlen = 0;
1319546e36dSchristos 	}
132c74ad251Schristos 	ndo->ndo_ll_hdr_len += len + hdrlen;
1339546e36dSchristos }
1349546e36dSchristos #endif /* DLT_PPI */
135