1 /* 2 * Oracle 3 */ 4 5 /* \summary: Per-Packet Information (DLT_PPI) printer */ 6 7 /* Specification: 8 * Per-Packet Information Header Specification - Version 1.0.7 9 * https://web.archive.org/web/20160328114748/http://www.cacetech.com/documents/PPI%20Header%20format%201.0.7.pdf 10 */ 11 12 #include <config.h> 13 14 #include "netdissect-stdinc.h" 15 16 #include "netdissect.h" 17 #include "extract.h" 18 19 20 typedef struct ppi_header { 21 nd_uint8_t ppi_ver; /* Version. Currently 0 */ 22 nd_uint8_t ppi_flags; /* Flags. */ 23 nd_uint16_t ppi_len; /* Length of entire message, including 24 * this header and TLV payload. */ 25 nd_uint32_t ppi_dlt; /* Data Link Type of the captured 26 * packet data. */ 27 } ppi_header_t; 28 29 #define PPI_HDRLEN 8 30 31 #ifdef DLT_PPI 32 33 static void 34 ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length) 35 { 36 const ppi_header_t *hdr; 37 uint16_t len; 38 uint32_t dlt; 39 const char *dltname; 40 41 hdr = (const ppi_header_t *)bp; 42 43 len = GET_LE_U_2(hdr->ppi_len); 44 dlt = GET_LE_U_4(hdr->ppi_dlt); 45 dltname = pcap_datalink_val_to_name(dlt); 46 47 if (!ndo->ndo_qflag) { 48 ND_PRINT("V.%u DLT %s (%u) len %u", GET_U_1(hdr->ppi_ver), 49 (dltname != NULL ? dltname : "UNKNOWN"), dlt, 50 len); 51 } else { 52 ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN")); 53 } 54 55 ND_PRINT(", length %u: ", length); 56 } 57 58 /* 59 * This is the top level routine of the printer. 'p' points 60 * to the ether header of the packet, 'h->ts' is the timestamp, 61 * 'h->len' is the length of the packet off the wire, and 'h->caplen' 62 * is the number of bytes actually captured. 63 */ 64 void 65 ppi_if_print(netdissect_options *ndo, 66 const struct pcap_pkthdr *h, const u_char *p) 67 { 68 if_printer printer; 69 const ppi_header_t *hdr; 70 u_int caplen = h->caplen; 71 u_int length = h->len; 72 uint16_t len; 73 uint32_t dlt; 74 uint32_t hdrlen; 75 struct pcap_pkthdr nhdr; 76 77 ndo->ndo_protocol = "ppi"; 78 if (caplen < sizeof(ppi_header_t)) { 79 nd_print_trunc(ndo); 80 ndo->ndo_ll_hdr_len += caplen; 81 return; 82 } 83 84 hdr = (const ppi_header_t *)p; 85 len = GET_LE_U_2(hdr->ppi_len); 86 if (len < sizeof(ppi_header_t) || len > 65532) { 87 /* It MUST be between 8 and 65,532 inclusive (spec 3.1.3) */ 88 ND_PRINT(" [length %u < %zu or > 65532]", len, 89 sizeof(ppi_header_t)); 90 nd_print_invalid(ndo); 91 ndo->ndo_ll_hdr_len += caplen; 92 return; 93 } 94 if (caplen < len) { 95 /* 96 * If we don't have the entire PPI header, don't 97 * bother. 98 */ 99 nd_print_trunc(ndo); 100 ndo->ndo_ll_hdr_len += caplen; 101 return; 102 } 103 dlt = GET_LE_U_4(hdr->ppi_dlt); 104 105 if (ndo->ndo_eflag) 106 ppi_header_print(ndo, p, length); 107 108 length -= len; 109 caplen -= len; 110 p += len; 111 112 printer = lookup_printer(dlt); 113 if (printer != NULL) { 114 nhdr = *h; 115 nhdr.caplen = caplen; 116 nhdr.len = length; 117 printer(ndo, &nhdr, p); 118 hdrlen = ndo->ndo_ll_hdr_len; 119 } else { 120 if (!ndo->ndo_eflag) 121 ppi_header_print(ndo, (const u_char *)hdr, length + len); 122 123 if (!ndo->ndo_suppress_default_print) 124 ND_DEFAULTPRINT(p, caplen); 125 hdrlen = 0; 126 } 127 ndo->ndo_ll_hdr_len += len + hdrlen; 128 } 129 #endif /* DLT_PPI */ 130