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