xref: /netbsd-src/external/bsd/tcpdump/dist/print-ppi.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*
2  * Oracle
3  */
4 
5 #include <sys/cdefs.h>
6 #ifndef lint
7 __RCSID("$NetBSD: print-ppi.c,v 1.3 2017/02/05 04:05:05 spz 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 	len = EXTRACT_LE_16BITS(&hdr->ppi_len);
77 	if (caplen < len) {
78 		/*
79 		 * If we don't have the entire PPI header, don't
80 		 * bother.
81 		 */
82 		ND_PRINT((ndo, "[|ppi]"));
83 		return (caplen);
84 	}
85 	if (len < sizeof(ppi_header_t)) {
86 		ND_PRINT((ndo, "[|ppi]"));
87 		return (len);
88 	}
89 	dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt);
90 
91 	if (ndo->ndo_eflag)
92 		ppi_header_print(ndo, p, length);
93 
94 	length -= len;
95 	caplen -= len;
96 	p += len;
97 
98 	if ((printer = lookup_printer(dlt)) != NULL) {
99 		nhdr = *h;
100 		nhdr.caplen = caplen;
101 		nhdr.len = length;
102 		hdrlen = printer(ndo, &nhdr, p);
103 	} else {
104 		if (!ndo->ndo_eflag)
105 			ppi_header_print(ndo, (const u_char *)hdr, length + len);
106 
107 		if (!ndo->ndo_suppress_default_print)
108 			ND_DEFAULTPRINT(p, caplen);
109 		hdrlen = 0;
110 	}
111 	return (len + hdrlen);
112 }
113 
114 /*
115  * This is the top level routine of the printer.  'p' points
116  * to the ether header of the packet, 'h->ts' is the timestamp,
117  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
118  * is the number of bytes actually captured.
119  */
120 u_int
121 ppi_if_print(netdissect_options *ndo,
122                const struct pcap_pkthdr *h, const u_char *p)
123 {
124 	return (ppi_print(ndo, h, p));
125 }
126 
127 /*
128  * Local Variables:
129  * c-style: whitesmith
130  * c-basic-offset: 8
131  * End:
132  */
133 
134 #endif /* DLT_PPI */
135