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