1 /* $OpenBSD: print-cnfp.c,v 1.2 1998/06/25 20:26:59 mickey Exp $ */
4 * Copyright (c) 1998 Michael Shalayeff
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
33 /* \summary: Cisco NetFlow protocol printer */
36 * Cisco NetFlow protocol
40 * https://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892
45 #include "netdissect-stdinc.h"
49 #include "netdissect.h"
50 #include "addrtoname.h"
57 nd_uint16_t version
; /* version number */
58 nd_uint16_t count
; /* # of records */
59 nd_uint32_t msys_uptime
;
68 nd_uint16_t input
; /* SNMP index of input interface */
69 nd_uint16_t output
; /* SNMP index of output interface */
70 nd_uint32_t packets
; /* packets in the flow */
71 nd_uint32_t octets
; /* layer 3 octets in the packets of the flow */
72 nd_uint32_t start_time
; /* sys_uptime value at start of flow */
73 nd_uint32_t last_time
; /* sys_uptime value when last packet of flow was received */
74 nd_uint16_t srcport
; /* TCP/UDP source port or equivalent */
75 nd_uint16_t dstport
; /* TCP/UDP source port or equivalent */
76 nd_byte pad1
[2]; /* pad */
77 nd_uint8_t proto
; /* IP protocol type */
78 nd_uint8_t tos
; /* IP type of service */
79 nd_uint8_t tcp_flags
; /* cumulative OR of TCP flags */
80 nd_byte pad
[3]; /* padding */
81 nd_uint32_t reserved
; /* unused */
85 nd_uint16_t version
; /* version number */
86 nd_uint16_t count
; /* # of records */
87 nd_uint32_t msys_uptime
;
90 nd_uint32_t sequence
; /* flow sequence number */
91 nd_uint8_t engine_type
; /* type of flow-switching engine */
92 nd_uint8_t engine_id
; /* slot number of the flow-switching engine */
93 nd_uint16_t sampling_interval
; /* sampling mode and interval */
100 nd_uint16_t input
; /* SNMP index of input interface */
101 nd_uint16_t output
; /* SNMP index of output interface */
102 nd_uint32_t packets
; /* packets in the flow */
103 nd_uint32_t octets
; /* layer 3 octets in the packets of the flow */
104 nd_uint32_t start_time
; /* sys_uptime value at start of flow */
105 nd_uint32_t last_time
; /* sys_uptime value when last packet of flow was received */
106 nd_uint16_t srcport
; /* TCP/UDP source port or equivalent */
107 nd_uint16_t dstport
; /* TCP/UDP source port or equivalent */
108 nd_byte pad1
; /* pad */
109 nd_uint8_t tcp_flags
; /* cumulative OR of TCP flags */
110 nd_uint8_t proto
; /* IP protocol type */
111 nd_uint8_t tos
; /* IP type of service */
112 nd_uint16_t src_as
; /* AS number of the source */
113 nd_uint16_t dst_as
; /* AS number of the destination */
114 nd_uint8_t src_mask
; /* source address mask bits */
115 nd_uint8_t dst_mask
; /* destination address prefix mask bits */
117 nd_ipv4 peer_nexthop
; /* v6: IP address of the nexthop within the peer (FIB)*/
121 nd_uint16_t version
; /* version number */
122 nd_uint16_t count
; /* # of records */
123 nd_uint32_t msys_uptime
;
125 nd_uint32_t utc_nsec
;
126 nd_uint32_t sequence
; /* v5 flow sequence number */
127 nd_uint32_t reserved
; /* v5 only */
134 nd_uint16_t input
; /* SNMP index of input interface */
135 nd_uint16_t output
; /* SNMP index of output interface */
136 nd_uint32_t packets
; /* packets in the flow */
137 nd_uint32_t octets
; /* layer 3 octets in the packets of the flow */
138 nd_uint32_t start_time
; /* sys_uptime value at start of flow */
139 nd_uint32_t last_time
; /* sys_uptime value when last packet of flow was received */
140 nd_uint16_t srcport
; /* TCP/UDP source port or equivalent */
141 nd_uint16_t dstport
; /* TCP/UDP source port or equivalent */
142 nd_byte pad1
; /* pad */
143 nd_uint8_t tcp_flags
; /* cumulative OR of TCP flags */
144 nd_uint8_t proto
; /* IP protocol type */
145 nd_uint8_t tos
; /* IP type of service */
146 nd_uint16_t src_as
; /* AS number of the source */
147 nd_uint16_t dst_as
; /* AS number of the destination */
148 nd_uint8_t src_mask
; /* source address mask bits */
149 nd_uint8_t dst_mask
; /* destination address prefix mask bits */
151 nd_ipv4 peer_nexthop
; /* v6: IP address of the nexthop within the peer (FIB)*/
155 cnfp_v1_print(netdissect_options
*ndo
, const u_char
*cp
)
157 const struct nfhdr_v1
*nh
;
158 const struct nfrec_v1
*nr
;
166 nh
= (const struct nfhdr_v1
*)cp
;
169 ver
= GET_BE_U_2(nh
->version
);
170 nrecs
= GET_BE_U_4(nh
->count
);
173 * This is seconds since the UN*X epoch, and is followed by
174 * nanoseconds. XXX - format it, rather than just dumping the
175 * raw seconds-since-the-Epoch.
177 t
= GET_BE_U_4(nh
->utc_sec
);
180 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver
,
181 GET_BE_U_4(nh
->msys_uptime
)/1000,
182 GET_BE_U_4(nh
->msys_uptime
)%1000,
183 GET_BE_U_4(nh
->utc_sec
), GET_BE_U_4(nh
->utc_nsec
));
185 nr
= (const struct nfrec_v1
*)&nh
[1];
187 ND_PRINT("%2u recs", nrecs
);
189 for (; nrecs
!= 0; nr
++, nrecs
--) {
194 * Make sure we have the entire record.
197 ND_PRINT("\n started %u.%03u, last %u.%03u",
198 GET_BE_U_4(nr
->start_time
)/1000,
199 GET_BE_U_4(nr
->start_time
)%1000,
200 GET_BE_U_4(nr
->last_time
)/1000,
201 GET_BE_U_4(nr
->last_time
)%1000);
203 asbuf
[0] = buf
[0] = '\0';
204 ND_PRINT("\n %s%s%s:%u ",
205 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->src_ina
)),
207 GET_BE_U_2(nr
->srcport
));
209 ND_PRINT("> %s%s%s:%u ",
210 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->dst_ina
)),
212 GET_BE_U_2(nr
->dstport
));
215 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->nhop_ina
)));
217 proto
= GET_U_1(nr
->proto
);
218 if (!ndo
->ndo_nflag
&& (p_name
= netdb_protoname(proto
)) != NULL
)
219 ND_PRINT("%s ", p_name
);
221 ND_PRINT("%u ", proto
);
223 /* tcp flags for tcp only */
224 if (proto
== IPPROTO_TCP
) {
226 flags
= GET_U_1(nr
->tcp_flags
);
227 ND_PRINT("%s%s%s%s%s%s%s",
228 flags
& TH_FIN
? "F" : "",
229 flags
& TH_SYN
? "S" : "",
230 flags
& TH_RST
? "R" : "",
231 flags
& TH_PUSH
? "P" : "",
232 flags
& TH_ACK
? "A" : "",
233 flags
& TH_URG
? "U" : "",
238 ND_PRINT("tos %u, %u (%u octets) %s",
240 GET_BE_U_4(nr
->packets
),
241 GET_BE_U_4(nr
->octets
), buf
);
250 cnfp_v5_print(netdissect_options
*ndo
, const u_char
*cp
)
252 const struct nfhdr_v5
*nh
;
253 const struct nfrec_v5
*nr
;
261 nh
= (const struct nfhdr_v5
*)cp
;
264 ver
= GET_BE_U_2(nh
->version
);
265 nrecs
= GET_BE_U_4(nh
->count
);
268 * This is seconds since the UN*X epoch, and is followed by
269 * nanoseconds. XXX - format it, rather than just dumping the
270 * raw seconds-since-the-Epoch.
272 t
= GET_BE_U_4(nh
->utc_sec
);
275 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver
,
276 GET_BE_U_4(nh
->msys_uptime
)/1000,
277 GET_BE_U_4(nh
->msys_uptime
)%1000,
278 GET_BE_U_4(nh
->utc_sec
), GET_BE_U_4(nh
->utc_nsec
));
280 ND_PRINT("#%u, ", GET_BE_U_4(nh
->sequence
));
281 nr
= (const struct nfrec_v5
*)&nh
[1];
283 ND_PRINT("%2u recs", nrecs
);
285 for (; nrecs
!= 0; nr
++, nrecs
--) {
290 * Make sure we have the entire record.
293 ND_PRINT("\n started %u.%03u, last %u.%03u",
294 GET_BE_U_4(nr
->start_time
)/1000,
295 GET_BE_U_4(nr
->start_time
)%1000,
296 GET_BE_U_4(nr
->last_time
)/1000,
297 GET_BE_U_4(nr
->last_time
)%1000);
299 asbuf
[0] = buf
[0] = '\0';
300 snprintf(buf
, sizeof(buf
), "/%u", GET_U_1(nr
->src_mask
));
301 snprintf(asbuf
, sizeof(asbuf
), ":%u",
302 GET_BE_U_2(nr
->src_as
));
303 ND_PRINT("\n %s%s%s:%u ",
304 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->src_ina
)),
306 GET_BE_U_2(nr
->srcport
));
308 snprintf(buf
, sizeof(buf
), "/%u", GET_U_1(nr
->dst_mask
));
309 snprintf(asbuf
, sizeof(asbuf
), ":%u",
310 GET_BE_U_2(nr
->dst_as
));
311 ND_PRINT("> %s%s%s:%u ",
312 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->dst_ina
)),
314 GET_BE_U_2(nr
->dstport
));
317 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->nhop_ina
)));
319 proto
= GET_U_1(nr
->proto
);
320 if (!ndo
->ndo_nflag
&& (p_name
= netdb_protoname(proto
)) != NULL
)
321 ND_PRINT("%s ", p_name
);
323 ND_PRINT("%u ", proto
);
325 /* tcp flags for tcp only */
326 if (proto
== IPPROTO_TCP
) {
328 flags
= GET_U_1(nr
->tcp_flags
);
329 ND_PRINT("%s%s%s%s%s%s%s",
330 flags
& TH_FIN
? "F" : "",
331 flags
& TH_SYN
? "S" : "",
332 flags
& TH_RST
? "R" : "",
333 flags
& TH_PUSH
? "P" : "",
334 flags
& TH_ACK
? "A" : "",
335 flags
& TH_URG
? "U" : "",
340 ND_PRINT("tos %u, %u (%u octets) %s",
342 GET_BE_U_4(nr
->packets
),
343 GET_BE_U_4(nr
->octets
), buf
);
352 cnfp_v6_print(netdissect_options
*ndo
, const u_char
*cp
)
354 const struct nfhdr_v6
*nh
;
355 const struct nfrec_v6
*nr
;
363 nh
= (const struct nfhdr_v6
*)cp
;
366 ver
= GET_BE_U_2(nh
->version
);
367 nrecs
= GET_BE_U_4(nh
->count
);
370 * This is seconds since the UN*X epoch, and is followed by
371 * nanoseconds. XXX - format it, rather than just dumping the
372 * raw seconds-since-the-Epoch.
374 t
= GET_BE_U_4(nh
->utc_sec
);
377 ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver
,
378 GET_BE_U_4(nh
->msys_uptime
)/1000,
379 GET_BE_U_4(nh
->msys_uptime
)%1000,
380 GET_BE_U_4(nh
->utc_sec
), GET_BE_U_4(nh
->utc_nsec
));
382 ND_PRINT("#%u, ", GET_BE_U_4(nh
->sequence
));
383 nr
= (const struct nfrec_v6
*)&nh
[1];
385 ND_PRINT("%2u recs", nrecs
);
387 for (; nrecs
!= 0; nr
++, nrecs
--) {
392 * Make sure we have the entire record.
395 ND_PRINT("\n started %u.%03u, last %u.%03u",
396 GET_BE_U_4(nr
->start_time
)/1000,
397 GET_BE_U_4(nr
->start_time
)%1000,
398 GET_BE_U_4(nr
->last_time
)/1000,
399 GET_BE_U_4(nr
->last_time
)%1000);
401 asbuf
[0] = buf
[0] = '\0';
402 snprintf(buf
, sizeof(buf
), "/%u", GET_U_1(nr
->src_mask
));
403 snprintf(asbuf
, sizeof(asbuf
), ":%u",
404 GET_BE_U_2(nr
->src_as
));
405 ND_PRINT("\n %s%s%s:%u ",
406 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->src_ina
)),
408 GET_BE_U_2(nr
->srcport
));
410 snprintf(buf
, sizeof(buf
), "/%u", GET_U_1(nr
->dst_mask
));
411 snprintf(asbuf
, sizeof(asbuf
), ":%u",
412 GET_BE_U_2(nr
->dst_as
));
413 ND_PRINT("> %s%s%s:%u ",
414 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->dst_ina
)),
416 GET_BE_U_2(nr
->dstport
));
419 intoa(GET_IPV4_TO_NETWORK_ORDER(nr
->nhop_ina
)));
421 proto
= GET_U_1(nr
->proto
);
422 if (!ndo
->ndo_nflag
&& (p_name
= netdb_protoname(proto
)) != NULL
)
423 ND_PRINT("%s ", p_name
);
425 ND_PRINT("%u ", proto
);
427 /* tcp flags for tcp only */
428 if (proto
== IPPROTO_TCP
) {
430 flags
= GET_U_1(nr
->tcp_flags
);
431 ND_PRINT("%s%s%s%s%s%s%s",
432 flags
& TH_FIN
? "F" : "",
433 flags
& TH_SYN
? "S" : "",
434 flags
& TH_RST
? "R" : "",
435 flags
& TH_PUSH
? "P" : "",
436 flags
& TH_ACK
? "A" : "",
437 flags
& TH_URG
? "U" : "",
442 snprintf(buf
, sizeof(buf
), "(%u<>%u encaps)",
443 (GET_BE_U_2(nr
->flags
) >> 8) & 0xff,
444 (GET_BE_U_2(nr
->flags
)) & 0xff);
445 ND_PRINT("tos %u, %u (%u octets) %s",
447 GET_BE_U_4(nr
->packets
),
448 GET_BE_U_4(nr
->octets
), buf
);
457 cnfp_print(netdissect_options
*ndo
, const u_char
*cp
)
462 * First 2 bytes are the version number.
464 ndo
->ndo_protocol
= "cnfp";
465 ver
= GET_BE_U_2(cp
);
469 cnfp_v1_print(ndo
, cp
);
473 cnfp_v5_print(ndo
, cp
);
477 cnfp_v6_print(ndo
, cp
);
481 ND_PRINT("NetFlow v%x", ver
);