]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-ppi.c
usr.sbin: Automated cleanup of cdefs and other formatting
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-ppi.c
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 #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
22 typedef struct ppi_header {
23         nd_uint8_t      ppi_ver;        /* Version.  Currently 0 */
24         nd_uint8_t      ppi_flags;      /* Flags. */
25         nd_uint16_t     ppi_len;        /* Length of entire message, including
26                                          * this header and TLV payload. */
27         nd_uint32_t     ppi_dlt;        /* Data Link Type of the captured
28                                          * packet data. */
29 } ppi_header_t;
30
31 #define PPI_HDRLEN      8
32
33 #ifdef DLT_PPI
34
35 static void
36 ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length)
37 {
38         const ppi_header_t *hdr;
39         uint16_t len;
40         uint32_t dlt;
41         const char *dltname;
42
43         hdr = (const ppi_header_t *)bp;
44
45         len = GET_LE_U_2(hdr->ppi_len);
46         dlt = GET_LE_U_4(hdr->ppi_dlt);
47         dltname = pcap_datalink_val_to_name(dlt);
48
49         if (!ndo->ndo_qflag) {
50                 ND_PRINT("V.%u DLT %s (%u) len %u", GET_U_1(hdr->ppi_ver),
51                           (dltname != NULL ? dltname : "UNKNOWN"), dlt,
52                           len);
53         } else {
54                 ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN"));
55         }
56
57         ND_PRINT(", length %u: ", length);
58 }
59
60 /*
61  * This is the top level routine of the printer.  'p' points
62  * to the ether header of the packet, 'h->ts' is the timestamp,
63  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
64  * is the number of bytes actually captured.
65  */
66 void
67 ppi_if_print(netdissect_options *ndo,
68              const struct pcap_pkthdr *h, const u_char *p)
69 {
70         if_printer printer;
71         const ppi_header_t *hdr;
72         u_int caplen = h->caplen;
73         u_int length = h->len;
74         uint16_t len;
75         uint32_t dlt;
76         uint32_t hdrlen;
77         struct pcap_pkthdr nhdr;
78
79         ndo->ndo_protocol = "ppi";
80         if (caplen < sizeof(ppi_header_t)) {
81                 nd_print_trunc(ndo);
82                 ndo->ndo_ll_hdr_len += caplen;
83                 return;
84         }
85
86         hdr = (const ppi_header_t *)p;
87         len = GET_LE_U_2(hdr->ppi_len);
88         if (len < sizeof(ppi_header_t) || len > 65532) {
89                 /* It MUST be between 8 and 65,532 inclusive (spec 3.1.3) */
90                 ND_PRINT(" [length %u < %zu or > 65532]", len,
91                          sizeof(ppi_header_t));
92                 nd_print_invalid(ndo);
93                 ndo->ndo_ll_hdr_len += caplen;
94                 return;
95         }
96         if (caplen < len) {
97                 /*
98                  * If we don't have the entire PPI header, don't
99                  * bother.
100                  */
101                 nd_print_trunc(ndo);
102                 ndo->ndo_ll_hdr_len += caplen;
103                 return;
104         }
105         dlt = GET_LE_U_4(hdr->ppi_dlt);
106
107         if (ndo->ndo_eflag)
108                 ppi_header_print(ndo, p, length);
109
110         length -= len;
111         caplen -= len;
112         p += len;
113
114         printer = lookup_printer(dlt);
115         if (printer != NULL) {
116                 nhdr = *h;
117                 nhdr.caplen = caplen;
118                 nhdr.len = length;
119                 printer(ndo, &nhdr, p);
120                 hdrlen = ndo->ndo_ll_hdr_len;
121         } else {
122                 if (!ndo->ndo_eflag)
123                         ppi_header_print(ndo, (const u_char *)hdr, length + len);
124
125                 if (!ndo->ndo_suppress_default_print)
126                         ND_DEFAULTPRINT(p, caplen);
127                 hdrlen = 0;
128         }
129         ndo->ndo_ll_hdr_len += len + hdrlen;
130 }
131 #endif /* DLT_PPI */