]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-cnfp.c
Merge lld trunk r300422 and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / 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  *    http://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include "config.h"
45 #endif
46
47 #include <netdissect-stdinc.h>
48
49 #include <stdio.h>
50 #include <string.h>
51
52 #include "netdissect.h"
53 #include "addrtoname.h"
54 #include "extract.h"
55
56 #include "tcp.h"
57 #include "ipproto.h"
58
59 struct nfhdr_v1 {
60         uint16_t        version;        /* version number */
61         uint16_t        count;          /* # of records */
62         uint32_t        msys_uptime;
63         uint32_t        utc_sec;
64         uint32_t        utc_nsec;
65 };
66
67 struct nfrec_v1 {
68         struct in_addr  src_ina;
69         struct in_addr  dst_ina;
70         struct in_addr  nhop_ina;
71         uint16_t        input;          /* SNMP index of input interface */
72         uint16_t        output;         /* SNMP index of output interface */
73         uint32_t        packets;        /* packets in the flow */
74         uint32_t        octets;         /* layer 3 octets in the packets of the flow */
75         uint32_t        start_time;     /* sys_uptime value at start of flow */
76         uint32_t        last_time;      /* sys_uptime value when last packet of flow was received */
77         uint16_t        srcport;        /* TCP/UDP source port or equivalent */
78         uint16_t        dstport;        /* TCP/UDP source port or equivalent */
79         uint16_t        pad1;           /* pad */
80         uint8_t         proto;          /* IP protocol type */
81         uint8_t         tos;            /* IP type of service */
82         uint8_t         tcp_flags;      /* cumulative OR of TCP flags */
83         uint8_t         pad[3];         /* padding */
84         uint32_t        reserved;       /* unused */
85 };
86
87 struct nfhdr_v5 {
88         uint16_t        version;        /* version number */
89         uint16_t        count;          /* # of records */
90         uint32_t        msys_uptime;
91         uint32_t        utc_sec;
92         uint32_t        utc_nsec;
93         uint32_t        sequence;       /* flow sequence number */
94         uint8_t         engine_type;    /* type of flow-switching engine */
95         uint8_t         engine_id;      /* slot number of the flow-switching engine */
96         uint16_t        sampling_interval; /* sampling mode and interval */
97 };
98
99 struct nfrec_v5 {
100         struct in_addr  src_ina;
101         struct in_addr  dst_ina;
102         struct in_addr  nhop_ina;
103         uint16_t        input;          /* SNMP index of input interface */
104         uint16_t        output;         /* SNMP index of output interface */
105         uint32_t        packets;        /* packets in the flow */
106         uint32_t        octets;         /* layer 3 octets in the packets of the flow */
107         uint32_t        start_time;     /* sys_uptime value at start of flow */
108         uint32_t        last_time;      /* sys_uptime value when last packet of flow was received */
109         uint16_t        srcport;        /* TCP/UDP source port or equivalent */
110         uint16_t        dstport;        /* TCP/UDP source port or equivalent */
111         uint8_t         pad1;           /* pad */
112         uint8_t         tcp_flags;      /* cumulative OR of TCP flags */
113         uint8_t         proto;          /* IP protocol type */
114         uint8_t         tos;            /* IP type of service */
115         uint16_t        src_as;         /* AS number of the source */
116         uint16_t        dst_as;         /* AS number of the destination */
117         uint8_t         src_mask;       /* source address mask bits */
118         uint8_t         dst_mask;       /* destination address prefix mask bits */
119         uint16_t        pad2;
120         struct in_addr  peer_nexthop;   /* v6: IP address of the nexthop within the peer (FIB)*/
121 };
122
123 struct nfhdr_v6 {
124         uint16_t        version;        /* version number */
125         uint16_t        count;          /* # of records */
126         uint32_t        msys_uptime;
127         uint32_t        utc_sec;
128         uint32_t        utc_nsec;
129         uint32_t        sequence;       /* v5 flow sequence number */
130         uint32_t        reserved;       /* v5 only */
131 };
132
133 struct nfrec_v6 {
134         struct in_addr  src_ina;
135         struct in_addr  dst_ina;
136         struct in_addr  nhop_ina;
137         uint16_t        input;          /* SNMP index of input interface */
138         uint16_t        output;         /* SNMP index of output interface */
139         uint32_t        packets;        /* packets in the flow */
140         uint32_t        octets;         /* layer 3 octets in the packets of the flow */
141         uint32_t        start_time;     /* sys_uptime value at start of flow */
142         uint32_t        last_time;      /* sys_uptime value when last packet of flow was received */
143         uint16_t        srcport;        /* TCP/UDP source port or equivalent */
144         uint16_t        dstport;        /* TCP/UDP source port or equivalent */
145         uint8_t         pad1;           /* pad */
146         uint8_t         tcp_flags;      /* cumulative OR of TCP flags */
147         uint8_t         proto;          /* IP protocol type */
148         uint8_t         tos;            /* IP type of service */
149         uint16_t        src_as;         /* AS number of the source */
150         uint16_t        dst_as;         /* AS number of the destination */
151         uint8_t         src_mask;       /* source address mask bits */
152         uint8_t         dst_mask;       /* destination address prefix mask bits */
153         uint16_t        flags;
154         struct in_addr  peer_nexthop;   /* v6: IP address of the nexthop within the peer (FIB)*/
155 };
156
157 static void
158 cnfp_v1_print(netdissect_options *ndo, const u_char *cp)
159 {
160         register const struct nfhdr_v1 *nh;
161         register const struct nfrec_v1 *nr;
162         struct protoent *pent;
163         int nrecs, ver;
164 #if 0
165         time_t t;
166 #endif
167
168         nh = (const struct nfhdr_v1 *)cp;
169         ND_TCHECK(*nh);
170
171         ver = EXTRACT_16BITS(&nh->version);
172         nrecs = EXTRACT_32BITS(&nh->count);
173 #if 0
174         /*
175          * This is seconds since the UN*X epoch, and is followed by
176          * nanoseconds.  XXX - format it, rather than just dumping the
177          * raw seconds-since-the-Epoch.
178          */
179         t = EXTRACT_32BITS(&nh->utc_sec);
180 #endif
181
182         ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
183                EXTRACT_32BITS(&nh->msys_uptime)/1000,
184                EXTRACT_32BITS(&nh->msys_uptime)%1000,
185                EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec)));
186
187         nr = (const struct nfrec_v1 *)&nh[1];
188
189         ND_PRINT((ndo, "%2u recs", nrecs));
190
191         for (; nrecs != 0; nr++, nrecs--) {
192                 char buf[20];
193                 char asbuf[20];
194
195                 /*
196                  * Make sure we have the entire record.
197                  */
198                 ND_TCHECK(*nr);
199                 ND_PRINT((ndo, "\n  started %u.%03u, last %u.%03u",
200                        EXTRACT_32BITS(&nr->start_time)/1000,
201                        EXTRACT_32BITS(&nr->start_time)%1000,
202                        EXTRACT_32BITS(&nr->last_time)/1000,
203                        EXTRACT_32BITS(&nr->last_time)%1000));
204
205                 asbuf[0] = buf[0] = '\0';
206                 ND_PRINT((ndo, "\n    %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf,
207                         EXTRACT_16BITS(&nr->srcport)));
208
209                 ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf,
210                         EXTRACT_16BITS(&nr->dstport)));
211
212                 ND_PRINT((ndo, ">> %s\n    ", intoa(nr->nhop_ina.s_addr)));
213
214                 pent = getprotobynumber(nr->proto);
215                 if (!pent || ndo->ndo_nflag)
216                         ND_PRINT((ndo, "%u ", nr->proto));
217                 else
218                         ND_PRINT((ndo, "%s ", pent->p_name));
219
220                 /* tcp flags for tcp only */
221                 if (pent && pent->p_proto == IPPROTO_TCP) {
222                         int flags;
223                         flags = nr->tcp_flags;
224                         ND_PRINT((ndo, "%s%s%s%s%s%s%s",
225                                 flags & TH_FIN  ? "F" : "",
226                                 flags & TH_SYN  ? "S" : "",
227                                 flags & TH_RST  ? "R" : "",
228                                 flags & TH_PUSH ? "P" : "",
229                                 flags & TH_ACK  ? "A" : "",
230                                 flags & TH_URG  ? "U" : "",
231                                 flags           ? " " : ""));
232                 }
233
234                 buf[0]='\0';
235                 ND_PRINT((ndo, "tos %u, %u (%u octets) %s",
236                        nr->tos,
237                        EXTRACT_32BITS(&nr->packets),
238                        EXTRACT_32BITS(&nr->octets), buf));
239         }
240         return;
241
242 trunc:
243         ND_PRINT((ndo, "[|cnfp]"));
244         return;
245 }
246
247 static void
248 cnfp_v5_print(netdissect_options *ndo, const u_char *cp)
249 {
250         register const struct nfhdr_v5 *nh;
251         register const struct nfrec_v5 *nr;
252         struct protoent *pent;
253         int nrecs, ver;
254 #if 0
255         time_t t;
256 #endif
257
258         nh = (const struct nfhdr_v5 *)cp;
259         ND_TCHECK(*nh);
260
261         ver = EXTRACT_16BITS(&nh->version);
262         nrecs = EXTRACT_32BITS(&nh->count);
263 #if 0
264         /*
265          * This is seconds since the UN*X epoch, and is followed by
266          * nanoseconds.  XXX - format it, rather than just dumping the
267          * raw seconds-since-the-Epoch.
268          */
269         t = EXTRACT_32BITS(&nh->utc_sec);
270 #endif
271
272         ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
273                EXTRACT_32BITS(&nh->msys_uptime)/1000,
274                EXTRACT_32BITS(&nh->msys_uptime)%1000,
275                EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec)));
276
277         ND_PRINT((ndo, "#%u, ", EXTRACT_32BITS(&nh->sequence)));
278         nr = (const struct nfrec_v5 *)&nh[1];
279
280         ND_PRINT((ndo, "%2u recs", nrecs));
281
282         for (; nrecs != 0; nr++, nrecs--) {
283                 char buf[20];
284                 char asbuf[20];
285
286                 /*
287                  * Make sure we have the entire record.
288                  */
289                 ND_TCHECK(*nr);
290                 ND_PRINT((ndo, "\n  started %u.%03u, last %u.%03u",
291                        EXTRACT_32BITS(&nr->start_time)/1000,
292                        EXTRACT_32BITS(&nr->start_time)%1000,
293                        EXTRACT_32BITS(&nr->last_time)/1000,
294                        EXTRACT_32BITS(&nr->last_time)%1000));
295
296                 asbuf[0] = buf[0] = '\0';
297                 snprintf(buf, sizeof(buf), "/%u", nr->src_mask);
298                 snprintf(asbuf, sizeof(asbuf), ":%u",
299                         EXTRACT_16BITS(&nr->src_as));
300                 ND_PRINT((ndo, "\n    %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf,
301                         EXTRACT_16BITS(&nr->srcport)));
302
303                 snprintf(buf, sizeof(buf), "/%d", nr->dst_mask);
304                 snprintf(asbuf, sizeof(asbuf), ":%u",
305                          EXTRACT_16BITS(&nr->dst_as));
306                 ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf,
307                         EXTRACT_16BITS(&nr->dstport)));
308
309                 ND_PRINT((ndo, ">> %s\n    ", intoa(nr->nhop_ina.s_addr)));
310
311                 pent = getprotobynumber(nr->proto);
312                 if (!pent || ndo->ndo_nflag)
313                         ND_PRINT((ndo, "%u ", nr->proto));
314                 else
315                         ND_PRINT((ndo, "%s ", pent->p_name));
316
317                 /* tcp flags for tcp only */
318                 if (pent && pent->p_proto == IPPROTO_TCP) {
319                         int flags;
320                         flags = nr->tcp_flags;
321                         ND_PRINT((ndo, "%s%s%s%s%s%s%s",
322                                 flags & TH_FIN  ? "F" : "",
323                                 flags & TH_SYN  ? "S" : "",
324                                 flags & TH_RST  ? "R" : "",
325                                 flags & TH_PUSH ? "P" : "",
326                                 flags & TH_ACK  ? "A" : "",
327                                 flags & TH_URG  ? "U" : "",
328                                 flags           ? " " : ""));
329                 }
330
331                 buf[0]='\0';
332                 ND_PRINT((ndo, "tos %u, %u (%u octets) %s",
333                        nr->tos,
334                        EXTRACT_32BITS(&nr->packets),
335                        EXTRACT_32BITS(&nr->octets), buf));
336         }
337         return;
338
339 trunc:
340         ND_PRINT((ndo, "[|cnfp]"));
341         return;
342 }
343
344 static void
345 cnfp_v6_print(netdissect_options *ndo, const u_char *cp)
346 {
347         register const struct nfhdr_v6 *nh;
348         register const struct nfrec_v6 *nr;
349         struct protoent *pent;
350         int nrecs, ver;
351 #if 0
352         time_t t;
353 #endif
354
355         nh = (const struct nfhdr_v6 *)cp;
356         ND_TCHECK(*nh);
357
358         ver = EXTRACT_16BITS(&nh->version);
359         nrecs = EXTRACT_32BITS(&nh->count);
360 #if 0
361         /*
362          * This is seconds since the UN*X epoch, and is followed by
363          * nanoseconds.  XXX - format it, rather than just dumping the
364          * raw seconds-since-the-Epoch.
365          */
366         t = EXTRACT_32BITS(&nh->utc_sec);
367 #endif
368
369         ND_PRINT((ndo, "NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver,
370                EXTRACT_32BITS(&nh->msys_uptime)/1000,
371                EXTRACT_32BITS(&nh->msys_uptime)%1000,
372                EXTRACT_32BITS(&nh->utc_sec), EXTRACT_32BITS(&nh->utc_nsec)));
373
374         ND_PRINT((ndo, "#%u, ", EXTRACT_32BITS(&nh->sequence)));
375         nr = (const struct nfrec_v6 *)&nh[1];
376
377         ND_PRINT((ndo, "%2u recs", nrecs));
378
379         for (; nrecs != 0; nr++, nrecs--) {
380                 char buf[20];
381                 char asbuf[20];
382
383                 /*
384                  * Make sure we have the entire record.
385                  */
386                 ND_TCHECK(*nr);
387                 ND_PRINT((ndo, "\n  started %u.%03u, last %u.%03u",
388                        EXTRACT_32BITS(&nr->start_time)/1000,
389                        EXTRACT_32BITS(&nr->start_time)%1000,
390                        EXTRACT_32BITS(&nr->last_time)/1000,
391                        EXTRACT_32BITS(&nr->last_time)%1000));
392
393                 asbuf[0] = buf[0] = '\0';
394                 snprintf(buf, sizeof(buf), "/%u", nr->src_mask);
395                 snprintf(asbuf, sizeof(asbuf), ":%u",
396                         EXTRACT_16BITS(&nr->src_as));
397                 ND_PRINT((ndo, "\n    %s%s%s:%u ", intoa(nr->src_ina.s_addr), buf, asbuf,
398                         EXTRACT_16BITS(&nr->srcport)));
399
400                 snprintf(buf, sizeof(buf), "/%d", nr->dst_mask);
401                 snprintf(asbuf, sizeof(asbuf), ":%u",
402                          EXTRACT_16BITS(&nr->dst_as));
403                 ND_PRINT((ndo, "> %s%s%s:%u ", intoa(nr->dst_ina.s_addr), buf, asbuf,
404                         EXTRACT_16BITS(&nr->dstport)));
405
406                 ND_PRINT((ndo, ">> %s\n    ", intoa(nr->nhop_ina.s_addr)));
407
408                 pent = getprotobynumber(nr->proto);
409                 if (!pent || ndo->ndo_nflag)
410                         ND_PRINT((ndo, "%u ", nr->proto));
411                 else
412                         ND_PRINT((ndo, "%s ", pent->p_name));
413
414                 /* tcp flags for tcp only */
415                 if (pent && pent->p_proto == IPPROTO_TCP) {
416                         int flags;
417                         flags = nr->tcp_flags;
418                         ND_PRINT((ndo, "%s%s%s%s%s%s%s",
419                                 flags & TH_FIN  ? "F" : "",
420                                 flags & TH_SYN  ? "S" : "",
421                                 flags & TH_RST  ? "R" : "",
422                                 flags & TH_PUSH ? "P" : "",
423                                 flags & TH_ACK  ? "A" : "",
424                                 flags & TH_URG  ? "U" : "",
425                                 flags           ? " " : ""));
426                 }
427
428                 buf[0]='\0';
429                 snprintf(buf, sizeof(buf), "(%u<>%u encaps)",
430                          (EXTRACT_16BITS(&nr->flags) >> 8) & 0xff,
431                          (EXTRACT_16BITS(&nr->flags)) & 0xff);
432                 ND_PRINT((ndo, "tos %u, %u (%u octets) %s",
433                        nr->tos,
434                        EXTRACT_32BITS(&nr->packets),
435                        EXTRACT_32BITS(&nr->octets), buf));
436         }
437         return;
438
439 trunc:
440         ND_PRINT((ndo, "[|cnfp]"));
441         return;
442 }
443
444 void
445 cnfp_print(netdissect_options *ndo, const u_char *cp)
446 {
447         int ver;
448
449         /*
450          * First 2 bytes are the version number.
451          */
452         ND_TCHECK2(*cp, 2);
453         ver = EXTRACT_16BITS(cp);
454         switch (ver) {
455
456         case 1:
457                 cnfp_v1_print(ndo, cp);
458                 break;
459
460         case 5:
461                 cnfp_v5_print(ndo, cp);
462                 break;
463
464         case 6:
465                 cnfp_v6_print(ndo, cp);
466                 break;
467
468         default:
469                 ND_PRINT((ndo, "NetFlow v%x", ver));
470                 break;
471         }
472         return;
473
474 trunc:
475         ND_PRINT((ndo, "[|cnfp]"));
476         return;
477 }