]> The Tcpdump Group git mirrors - tcpdump/blob - print-cnfp.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / print-cnfp.c
1 /* $OpenBSD: print-cnfp.c,v 1.2 1998/06/25 20:26:59 mickey Exp $ */
2
3 /*
4 * Copyright (c) 1998 Michael Shalayeff
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Michael Shalayeff.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /* \summary: Cisco NetFlow protocol printer */
34
35 /*
36 * Cisco NetFlow protocol
37 *
38 * See
39 *
40 * https://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892
41 */
42
43 #include <config.h>
44
45 #include "netdissect-stdinc.h"
46
47 #define ND_LONGJMP_FROM_TCHECK
48 #include "netdissect.h"
49 #include "addrtoname.h"
50 #include "extract.h"
51
52 #include "tcp.h"
53 #include "ipproto.h"
54
55 struct nfhdr_v1 {
56 nd_uint16_t version; /* version number */
57 nd_uint16_t count; /* # of records */
58 nd_uint32_t msys_uptime;
59 nd_uint32_t utc_sec;
60 nd_uint32_t utc_nsec;
61 };
62
63 struct nfrec_v1 {
64 nd_ipv4 src_ina;
65 nd_ipv4 dst_ina;
66 nd_ipv4 nhop_ina;
67 nd_uint16_t input; /* SNMP index of input interface */
68 nd_uint16_t output; /* SNMP index of output interface */
69 nd_uint32_t packets; /* packets in the flow */
70 nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
71 nd_uint32_t start_time; /* sys_uptime value at start of flow */
72 nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
73 nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
74 nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
75 nd_byte pad1[2]; /* pad */
76 nd_uint8_t proto; /* IP protocol type */
77 nd_uint8_t tos; /* IP type of service */
78 nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
79 nd_byte pad[3]; /* padding */
80 nd_uint32_t reserved; /* unused */
81 };
82
83 struct nfhdr_v5 {
84 nd_uint16_t version; /* version number */
85 nd_uint16_t count; /* # of records */
86 nd_uint32_t msys_uptime;
87 nd_uint32_t utc_sec;
88 nd_uint32_t utc_nsec;
89 nd_uint32_t sequence; /* flow sequence number */
90 nd_uint8_t engine_type; /* type of flow-switching engine */
91 nd_uint8_t engine_id; /* slot number of the flow-switching engine */
92 nd_uint16_t sampling_interval; /* sampling mode and interval */
93 };
94
95 struct nfrec_v5 {
96 nd_ipv4 src_ina;
97 nd_ipv4 dst_ina;
98 nd_ipv4 nhop_ina;
99 nd_uint16_t input; /* SNMP index of input interface */
100 nd_uint16_t output; /* SNMP index of output interface */
101 nd_uint32_t packets; /* packets in the flow */
102 nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
103 nd_uint32_t start_time; /* sys_uptime value at start of flow */
104 nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
105 nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
106 nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
107 nd_byte pad1; /* pad */
108 nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
109 nd_uint8_t proto; /* IP protocol type */
110 nd_uint8_t tos; /* IP type of service */
111 nd_uint16_t src_as; /* AS number of the source */
112 nd_uint16_t dst_as; /* AS number of the destination */
113 nd_uint8_t src_mask; /* source address mask bits */
114 nd_uint8_t dst_mask; /* destination address prefix mask bits */
115 nd_byte pad2[2];
116 nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/
117 };
118
119 struct nfhdr_v6 {
120 nd_uint16_t version; /* version number */
121 nd_uint16_t count; /* # of records */
122 nd_uint32_t msys_uptime;
123 nd_uint32_t utc_sec;
124 nd_uint32_t utc_nsec;
125 nd_uint32_t sequence; /* v5 flow sequence number */
126 nd_uint32_t reserved; /* v5 only */
127 };
128
129 struct nfrec_v6 {
130 nd_ipv4 src_ina;
131 nd_ipv4 dst_ina;
132 nd_ipv4 nhop_ina;
133 nd_uint16_t input; /* SNMP index of input interface */
134 nd_uint16_t output; /* SNMP index of output interface */
135 nd_uint32_t packets; /* packets in the flow */
136 nd_uint32_t octets; /* layer 3 octets in the packets of the flow */
137 nd_uint32_t start_time; /* sys_uptime value at start of flow */
138 nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */
139 nd_uint16_t srcport; /* TCP/UDP source port or equivalent */
140 nd_uint16_t dstport; /* TCP/UDP source port or equivalent */
141 nd_byte pad1; /* pad */
142 nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */
143 nd_uint8_t proto; /* IP protocol type */
144 nd_uint8_t tos; /* IP type of service */
145 nd_uint16_t src_as; /* AS number of the source */
146 nd_uint16_t dst_as; /* AS number of the destination */
147 nd_uint8_t src_mask; /* source address mask bits */
148 nd_uint8_t dst_mask; /* destination address prefix mask bits */
149 nd_uint16_t flags;
150 nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/
151 };
152
153 static void
154 cnfp_v1_print(netdissect_options *ndo, const u_char *cp)
155 {
156 const struct nfhdr_v1 *nh;
157 const struct nfrec_v1 *nr;
158 const char *p_name;
159 uint8_t proto;
160 u_int nrecs, ver;
161 #if 0
162 time_t t;
163 #endif
164
165 nh = (const struct nfhdr_v1 *)cp;
166
167 ver = GET_BE_U_2(nh->version);
168 nrecs = GET_BE_U_4(nh->count);
169 #if 0
170 /*
171 * This is seconds since the UN*X epoch, and is followed by
172 * nanoseconds. XXX - format it, rather than just dumping the
173 * raw seconds-since-the-Epoch.
174 */
175 t = GET_BE_U_4(nh->utc_sec);
176 #endif
177
178 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
179 GET_BE_U_4(nh->msys_uptime)/1000,
180 GET_BE_U_4(nh->msys_uptime)%1000,
181 GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
182
183 nr = (const struct nfrec_v1 *)&nh[1];
184
185 ND_PRINT("%2u recs", nrecs);
186
187 for (; nrecs != 0; nr++, nrecs--) {
188 ND_PRINT("\n started %u.%03u, last %u.%03u",
189 GET_BE_U_4(nr->start_time)/1000,
190 GET_BE_U_4(nr->start_time)%1000,
191 GET_BE_U_4(nr->last_time)/1000,
192 GET_BE_U_4(nr->last_time)%1000);
193
194 ND_PRINT("\n %s:%u ",
195 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
196 GET_BE_U_2(nr->srcport));
197
198 ND_PRINT("> %s:%u ",
199 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
200 GET_BE_U_2(nr->dstport));
201
202 ND_PRINT(">> %s\n ",
203 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
204
205 proto = GET_U_1(nr->proto);
206 if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
207 ND_PRINT("%s ", p_name);
208 else
209 ND_PRINT("%u ", proto);
210
211 /* tcp flags for tcp only */
212 if (proto == IPPROTO_TCP) {
213 u_int flags;
214 flags = GET_U_1(nr->tcp_flags);
215 if (flags)
216 ND_PRINT("%s ", bittok2str_nosep(tcp_flag_values, "", flags));
217 }
218
219 ND_PRINT("tos %u, %u (%u octets)",
220 GET_U_1(nr->tos),
221 GET_BE_U_4(nr->packets),
222 GET_BE_U_4(nr->octets));
223 /* This was not all of struct nfrec_v1. */
224 ND_TCHECK_SIZE(nr);
225 }
226 }
227
228 static void
229 cnfp_v5_print(netdissect_options *ndo, const u_char *cp)
230 {
231 const struct nfhdr_v5 *nh;
232 const struct nfrec_v5 *nr;
233 const char *p_name;
234 uint8_t proto;
235 u_int nrecs, ver;
236 #if 0
237 time_t t;
238 #endif
239
240 nh = (const struct nfhdr_v5 *)cp;
241
242 ver = GET_BE_U_2(nh->version);
243 nrecs = GET_BE_U_4(nh->count);
244 #if 0
245 /*
246 * This is seconds since the UN*X epoch, and is followed by
247 * nanoseconds. XXX - format it, rather than just dumping the
248 * raw seconds-since-the-Epoch.
249 */
250 t = GET_BE_U_4(nh->utc_sec);
251 #endif
252
253 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
254 GET_BE_U_4(nh->msys_uptime)/1000,
255 GET_BE_U_4(nh->msys_uptime)%1000,
256 GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
257
258 ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence));
259 /* This was not all of struct nfhdr_v5. */
260 ND_TCHECK_SIZE(nh);
261 nr = (const struct nfrec_v5 *)&nh[1];
262
263 ND_PRINT("%2u recs", nrecs);
264
265 for (; nrecs != 0; nr++, nrecs--) {
266 ND_PRINT("\n started %u.%03u, last %u.%03u",
267 GET_BE_U_4(nr->start_time)/1000,
268 GET_BE_U_4(nr->start_time)%1000,
269 GET_BE_U_4(nr->last_time)/1000,
270 GET_BE_U_4(nr->last_time)%1000);
271
272 ND_PRINT("\n %s/%u:%u:%u ",
273 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
274 GET_U_1(nr->src_mask), GET_BE_U_2(nr->src_as),
275 GET_BE_U_2(nr->srcport));
276
277 ND_PRINT("> %s/%u:%u:%u ",
278 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
279 GET_U_1(nr->dst_mask), GET_BE_U_2(nr->dst_as),
280 GET_BE_U_2(nr->dstport));
281
282 ND_PRINT(">> %s\n ",
283 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
284
285 proto = GET_U_1(nr->proto);
286 if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
287 ND_PRINT("%s ", p_name);
288 else
289 ND_PRINT("%u ", proto);
290
291 /* tcp flags for tcp only */
292 if (proto == IPPROTO_TCP) {
293 u_int flags;
294 flags = GET_U_1(nr->tcp_flags);
295 if (flags)
296 ND_PRINT("%s ", bittok2str_nosep(tcp_flag_values, "", flags));
297 }
298
299 ND_PRINT("tos %u, %u (%u octets)",
300 GET_U_1(nr->tos),
301 GET_BE_U_4(nr->packets),
302 GET_BE_U_4(nr->octets));
303 /* This was not all of struct nfrec_v5. */
304 ND_TCHECK_SIZE(nr);
305 }
306 }
307
308 static void
309 cnfp_v6_print(netdissect_options *ndo, const u_char *cp)
310 {
311 const struct nfhdr_v6 *nh;
312 const struct nfrec_v6 *nr;
313 const char *p_name;
314 uint8_t proto;
315 u_int nrecs, ver;
316 #if 0
317 time_t t;
318 #endif
319
320 nh = (const struct nfhdr_v6 *)cp;
321
322 ver = GET_BE_U_2(nh->version);
323 nrecs = GET_BE_U_4(nh->count);
324 #if 0
325 /*
326 * This is seconds since the UN*X epoch, and is followed by
327 * nanoseconds. XXX - format it, rather than just dumping the
328 * raw seconds-since-the-Epoch.
329 */
330 t = GET_BE_U_4(nh->utc_sec);
331 #endif
332
333 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
334 GET_BE_U_4(nh->msys_uptime)/1000,
335 GET_BE_U_4(nh->msys_uptime)%1000,
336 GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec));
337
338 ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence));
339 /* This was not all of struct nfhdr_v6. */
340 ND_TCHECK_SIZE(nh);
341 nr = (const struct nfrec_v6 *)&nh[1];
342
343 ND_PRINT("%2u recs", nrecs);
344
345 for (; nrecs != 0; nr++, nrecs--) {
346 ND_PRINT("\n started %u.%03u, last %u.%03u",
347 GET_BE_U_4(nr->start_time)/1000,
348 GET_BE_U_4(nr->start_time)%1000,
349 GET_BE_U_4(nr->last_time)/1000,
350 GET_BE_U_4(nr->last_time)%1000);
351
352 ND_PRINT("\n %s/%u:%u:%u ",
353 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)),
354 GET_U_1(nr->src_mask), GET_BE_U_2(nr->src_as),
355 GET_BE_U_2(nr->srcport));
356
357 ND_PRINT("> %s/%u:%u:%u ",
358 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)),
359 GET_U_1(nr->dst_mask), GET_BE_U_2(nr->dst_as),
360 GET_BE_U_2(nr->dstport));
361
362 ND_PRINT(">> %s\n ",
363 intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina)));
364
365 proto = GET_U_1(nr->proto);
366 if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL)
367 ND_PRINT("%s ", p_name);
368 else
369 ND_PRINT("%u ", proto);
370
371 /* tcp flags for tcp only */
372 if (proto == IPPROTO_TCP) {
373 u_int flags;
374 flags = GET_U_1(nr->tcp_flags);
375 if (flags)
376 ND_PRINT("%s ", bittok2str_nosep(tcp_flag_values, "", flags));
377 }
378
379 ND_PRINT("tos %u, %u (%u octets) (%u<>%u encaps)",
380 GET_U_1(nr->tos),
381 GET_BE_U_4(nr->packets),
382 GET_BE_U_4(nr->octets),
383 (GET_BE_U_2(nr->flags) >> 8) & 0xff,
384 (GET_BE_U_2(nr->flags)) & 0xff);
385 /* This was not all of struct nfrec_v6. */
386 ND_TCHECK_SIZE(nr);
387 }
388 }
389
390 void
391 cnfp_print(netdissect_options *ndo, const u_char *cp)
392 {
393 int ver;
394
395 /*
396 * First 2 bytes are the version number.
397 */
398 ndo->ndo_protocol = "cnfp";
399 ver = GET_BE_U_2(cp);
400 switch (ver) {
401
402 case 1:
403 cnfp_v1_print(ndo, cp);
404 break;
405
406 case 5:
407 cnfp_v5_print(ndo, cp);
408 break;
409
410 case 6:
411 cnfp_v6_print(ndo, cp);
412 break;
413
414 default:
415 ND_PRINT("NetFlow v%x", ver);
416 break;
417 }
418 }