]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-nflog.c
ping(8): Fix a mandoc related issue
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-nflog.c
1 /*
2  * Copyright (c) 2013, Petar Alilovic,
3  * Faculty of Electrical Engineering and Computing, University of Zagreb
4  * All rights reserved
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice,
10  *       this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  *       notice, this list of conditions and the following disclaimer in the
13  *       documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
25  * DAMAGE.
26  */
27
28 /* \summary: DLT_NFLOG printer */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <netdissect-stdinc.h>
35
36 #include "netdissect.h"
37
38 #if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H)
39 #include <pcap/nflog.h>
40
41 static const struct tok nflog_values[] = {
42         { AF_INET,              "IPv4" },
43 #ifdef AF_INET6
44         { AF_INET6,             "IPv6" },
45 #endif /*AF_INET6*/
46         { 0,                    NULL }
47 };
48
49 static inline void
50 nflog_hdr_print(netdissect_options *ndo, const nflog_hdr_t *hdr, u_int length)
51 {
52         ND_PRINT((ndo, "version %d, resource ID %d", hdr->nflog_version, ntohs(hdr->nflog_rid)));
53
54         if (!ndo->ndo_qflag) {
55                 ND_PRINT((ndo,", family %s (%d)",
56                                                   tok2str(nflog_values, "Unknown",
57                                                                   hdr->nflog_family),
58                                                   hdr->nflog_family));
59                 } else {
60                 ND_PRINT((ndo,", %s",
61                                                   tok2str(nflog_values,
62                                                                   "Unknown NFLOG (0x%02x)",
63                                                                   hdr->nflog_family)));
64                 }
65
66         ND_PRINT((ndo, ", length %u: ", length));
67 }
68
69 u_int
70 nflog_if_print(netdissect_options *ndo,
71                            const struct pcap_pkthdr *h, const u_char *p)
72 {
73         const nflog_hdr_t *hdr = (const nflog_hdr_t *)p;
74         const nflog_tlv_t *tlv;
75         uint16_t size;
76         uint16_t h_size = sizeof(nflog_hdr_t);
77         u_int caplen = h->caplen;
78         u_int length = h->len;
79
80         if (caplen < (int) sizeof(nflog_hdr_t) || length < (int) sizeof(nflog_hdr_t)) {
81                 ND_PRINT((ndo, "[|nflog]"));
82                 return h_size;
83         }
84
85         if (hdr->nflog_version != 0) {
86                 ND_PRINT((ndo, "version %u (unknown)", hdr->nflog_version));
87                 return h_size;
88         }
89
90         if (ndo->ndo_eflag)
91                 nflog_hdr_print(ndo, hdr, length);
92
93         p += sizeof(nflog_hdr_t);
94         length -= sizeof(nflog_hdr_t);
95         caplen -= sizeof(nflog_hdr_t);
96
97         while (length > 0) {
98                 /* We have some data.  Do we have enough for the TLV header? */
99                 if (caplen < sizeof(nflog_tlv_t) || length < sizeof(nflog_tlv_t)) {
100                         /* No. */
101                         ND_PRINT((ndo, "[|nflog]"));
102                         return h_size;
103                 }
104
105                 tlv = (const nflog_tlv_t *) p;
106                 size = tlv->tlv_length;
107                 if (size % 4 != 0)
108                         size += 4 - size % 4;
109
110                 /* Is the TLV's length less than the minimum? */
111                 if (size < sizeof(nflog_tlv_t)) {
112                         /* Yes. Give up now. */
113                         ND_PRINT((ndo, "[|nflog]"));
114                         return h_size;
115                 }
116
117                 /* Do we have enough data for the full TLV? */
118                 if (caplen < size || length < size) {
119                         /* No. */
120                         ND_PRINT((ndo, "[|nflog]"));
121                         return h_size;
122                 }
123
124                 if (tlv->tlv_type == NFULA_PAYLOAD) {
125                         /*
126                          * This TLV's data is the packet payload.
127                          * Skip past the TLV header, and break out
128                          * of the loop so we print the packet data.
129                          */
130                         p += sizeof(nflog_tlv_t);
131                         h_size += sizeof(nflog_tlv_t);
132                         length -= sizeof(nflog_tlv_t);
133                         caplen -= sizeof(nflog_tlv_t);
134                         break;
135                 }
136
137                 p += size;
138                 h_size += size;
139                 length -= size;
140                 caplen -= size;
141         }
142
143         switch (hdr->nflog_family) {
144
145         case AF_INET:
146                 ip_print(ndo, p, length);
147                 break;
148
149 #ifdef AF_INET6
150         case AF_INET6:
151                 ip6_print(ndo, p, length);
152                 break;
153 #endif /* AF_INET6 */
154
155         default:
156                 if (!ndo->ndo_eflag)
157                         nflog_hdr_print(ndo, hdr,
158                                 length + sizeof(nflog_hdr_t));
159
160                 if (!ndo->ndo_suppress_default_print)
161                         ND_DEFAULTPRINT(p, caplen);
162                 break;
163         }
164
165         return h_size;
166 }
167
168 #endif /* defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H) */