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