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 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 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