xref: /netbsd-src/external/bsd/tcpdump/dist/print-ppi.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*
2  * Oracle
3  */
4 
5 #include <sys/cdefs.h>
6 #ifndef lint
7 __RCSID("$NetBSD: print-ppi.c,v 1.4 2019/10/01 16:06:16 christos Exp $");
8 #endif
9 
10 /* \summary: Oracle DLT_PPI printer */
11 
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15 
16 #include <netdissect-stdinc.h>
17 
18 #include "netdissect.h"
19 #include "extract.h"
20 
21 typedef struct ppi_header {
22 	uint8_t		ppi_ver;
23 	uint8_t		ppi_flags;
24 	uint16_t	ppi_len;
25 	uint32_t	ppi_dlt;
26 } ppi_header_t;
27 
28 #define	PPI_HDRLEN	8
29 
30 #ifdef DLT_PPI
31 
32 static inline void
33 ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
34 {
35 	const ppi_header_t *hdr;
36 	uint16_t len;
37 	uint32_t dlt;
38 	const char *dltname;
39 
40 	hdr = (const ppi_header_t *)bp;
41 
42 	len = EXTRACT_LE_16BITS(&hdr->ppi_len);
43 	dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt);
44 	dltname = pcap_datalink_val_to_name(dlt);
45 
46 	if (!ndo->ndo_qflag) {
47 		ND_PRINT((ndo, "V.%d DLT %s (%d) len %d", hdr->ppi_ver,
48 			  (dltname != NULL ? dltname : "UNKNOWN"), dlt,
49                           len));
50         } else {
51 		ND_PRINT((ndo, "%s", (dltname != NULL ? dltname : "UNKNOWN")));
52         }
53 
54 	ND_PRINT((ndo, ", length %u: ", length));
55 }
56 
57 static u_int
58 ppi_print(netdissect_options *ndo,
59                const struct pcap_pkthdr *h, const u_char *p)
60 {
61 	if_printer printer;
62 	const ppi_header_t *hdr;
63 	u_int caplen = h->caplen;
64 	u_int length = h->len;
65 	uint16_t len;
66 	uint32_t dlt;
67 	uint32_t hdrlen;
68 	struct pcap_pkthdr nhdr;
69 
70 	if (caplen < sizeof(ppi_header_t)) {
71 		ND_PRINT((ndo, "[|ppi]"));
72 		return (caplen);
73 	}
74 
75 	hdr = (const ppi_header_t *)p;
76 	ND_TCHECK_16BITS(&hdr->ppi_len);
77 	len = EXTRACT_LE_16BITS(&hdr->ppi_len);
78 	if (caplen < len) {
79 		/*
80 		 * If we don't have the entire PPI header, don't
81 		 * bother.
82 		 */
83 		ND_PRINT((ndo, "[|ppi]"));
84 		return (caplen);
85 	}
86 	if (len < sizeof(ppi_header_t)) {
87 		ND_PRINT((ndo, "[|ppi]"));
88 		return (len);
89 	}
90 	ND_TCHECK_32BITS(&hdr->ppi_dlt);
91 	dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt);
92 
93 	if (ndo->ndo_eflag)
94 		ppi_header_print(ndo, p, length);
95 
96 	length -= len;
97 	caplen -= len;
98 	p += len;
99 
100 	if ((printer = lookup_printer(dlt)) != NULL) {
101 		nhdr = *h;
102 		nhdr.caplen = caplen;
103 		nhdr.len = length;
104 		hdrlen = printer(ndo, &nhdr, p);
105 	} else {
106 		if (!ndo->ndo_eflag)
107 			ppi_header_print(ndo, (const u_char *)hdr, length + len);
108 
109 		if (!ndo->ndo_suppress_default_print)
110 			ND_DEFAULTPRINT(p, caplen);
111 		hdrlen = 0;
112 	}
113 	return (len + hdrlen);
114 trunc:
115 	return (caplen);
116 }
117 
118 /*
119  * This is the top level routine of the printer.  'p' points
120  * to the ether header of the packet, 'h->ts' is the timestamp,
121  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
122  * is the number of bytes actually captured.
123  */
124 u_int
125 ppi_if_print(netdissect_options *ndo,
126                const struct pcap_pkthdr *h, const u_char *p)
127 {
128 	return (ppi_print(ndo, h, p));
129 }
130 
131 /*
132  * Local Variables:
133  * c-style: whitesmith
134  * c-basic-offset: 8
135  * End:
136  */
137 
138 #endif /* DLT_PPI */
139