1 /* Copyright (c) 2002-2019 InMon Corp. Licensed under the terms of the InMon sFlow licence: */
2 /* http://www.inmon.com/technology/sflowlicense.txt */
3
4 #if defined(__cplusplus)
5 extern "C" {
6 #endif
7
8 #ifdef _WIN32
9 #include "config_windows.h"
10 #else
11 #include "config.h"
12 #endif
13
14 #include <stdio.h>
15 #include <stdarg.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <errno.h>
19 #include <sys/types.h>
20 #include <fcntl.h>
21 #include <time.h>
22 #include <setjmp.h>
23 #include <ctype.h>
24 #include <search.h>
25
26 #ifdef _WIN32
27 #else
28 #include <stdint.h>
29 #include <unistd.h>
30 #include <netdb.h>
31 #include <sys/socket.h>
32 #include <sys/time.h>
33 #include <sys/poll.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/in.h>
36 #include <inttypes.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39 #endif
40
41 #include "sflow.h" /* sFlow v5 */
42 #include "sflow_v2v4.h" /* sFlow v2/4 */
43
44 /* If the platform is Linux, enable the source-spoofing feature too. */
45 #ifdef linux
46 #define SPOOFSOURCE 1
47 #endif
48
49 /*
50 #ifdef DARWIN
51 #include <architecture/byte_order.h>
52 #define bswap_16(x) NXSwapShort(x)
53 #define bswap_32(x) NXSwapInt(x)
54 #else
55 #include <byteswap.h>
56 #endif
57 */
58
59 /* just do it in a portable way... */
MyByteSwap32(uint32_t n)60 static uint32_t MyByteSwap32(uint32_t n) {
61 return (((n & 0x000000FF)<<24) +
62 ((n & 0x0000FF00)<<8) +
63 ((n & 0x00FF0000)>>8) +
64 ((n & 0xFF000000)>>24));
65 }
MyByteSwap16(uint16_t n)66 static uint16_t MyByteSwap16(uint16_t n) {
67 return ((n >> 8) | (n << 8));
68 }
69
70 #ifndef PRIu64
71 # ifdef _WIN32
72 # define PRIu64 "I64u"
73 # else
74 # define PRIu64 "llu"
75 # endif
76 #endif
77
78 #define YES 1
79 #define NO 0
80
81 /* define my own IP header struct - to ease portability */
82 struct myiphdr
83 {
84 uint8_t version_and_headerLen;
85 uint8_t tos;
86 uint16_t tot_len;
87 uint16_t id;
88 uint16_t frag_off;
89 uint8_t ttl;
90 uint8_t protocol;
91 uint16_t check;
92 uint32_t saddr;
93 uint32_t daddr;
94 };
95
96 /* ip6 header if no option headers */
97 struct myip6hdr {
98 uint8_t version_and_priority;
99 uint8_t priority_and_label1;
100 uint8_t label2;
101 uint8_t label3;
102 uint16_t payloadLength;
103 uint8_t nextHeader;
104 uint8_t ttl;
105 struct in6_addr saddr;
106 struct in6_addr daddr;
107 };
108
109 /* same for tcp */
110 struct mytcphdr
111 {
112 uint16_t th_sport; /* source port */
113 uint16_t th_dport; /* destination port */
114 uint32_t th_seq; /* sequence number */
115 uint32_t th_ack; /* acknowledgement number */
116 uint8_t th_off_and_unused;
117 uint8_t th_flags;
118 uint16_t th_win; /* window */
119 uint16_t th_sum; /* checksum */
120 uint16_t th_urp; /* urgent pointer */
121 };
122
123 /* and UDP */
124 struct myudphdr {
125 uint16_t uh_sport; /* source port */
126 uint16_t uh_dport; /* destination port */
127 uint16_t uh_ulen; /* udp length */
128 uint16_t uh_sum; /* udp checksum */
129 };
130
131 /* and ICMP */
132 struct myicmphdr
133 {
134 uint8_t type; /* message type */
135 uint8_t code; /* type sub-code */
136 /* ignore the rest */
137 };
138
139 #ifdef SPOOFSOURCE
140 #define SPOOFSOURCE_SENDPACKET_SIZE 2000
141 struct mySendPacket {
142 struct myiphdr ip;
143 struct myudphdr udp;
144 uint8_t data[SPOOFSOURCE_SENDPACKET_SIZE];
145 };
146 #endif
147
148 /* tcpdump file format */
149
150 struct pcap_file_header {
151 uint32_t magic;
152 uint16_t version_major;
153 uint16_t version_minor;
154 uint32_t thiszone; /* gmt to local correction */
155 uint32_t sigfigs; /* accuracy of timestamps */
156 uint32_t snaplen; /* max length saved portion of each pkt */
157 uint32_t linktype; /* data link type (DLT_*) */
158 };
159
160 struct pcap_pkthdr {
161 uint32_t ts_sec; /* time stamp - used to be struct timeval, but time_t can be 64 bits now */
162 uint32_t ts_usec;
163 uint32_t caplen; /* length of portion present */
164 uint32_t len; /* length this packet (off wire) */
165 /* some systems expect to see more information here. For example,
166 * on some versions of RedHat Linux, there are three extra fields:
167 * int index;
168 * unsigned short protocol;
169 * unsigned char pkt_type;
170 */
171 };
172
173 typedef struct _SFForwardingTarget {
174 struct _SFForwardingTarget *nxt;
175 struct sockaddr_in addr;
176 int sock;
177 } SFForwardingTarget;
178
179 typedef struct _SFForwardingTarget6 {
180 struct _SFForwardingTarget6 *nxt;
181 struct sockaddr_in6 addr;
182 int sock;
183 } SFForwardingTarget6;
184
185 typedef union _SFSockAddr {
186 struct sockaddr_in sa4;
187 struct sockaddr_in6 sa6;
188 } SFSockAddr;
189
190 typedef enum { SFLFMT_FULL=0,
191 SFLFMT_PCAP,
192 SFLFMT_PCAP_DISCARD,
193 SFLFMT_LINE,
194 SFLFMT_LINE_CUSTOM,
195 SFLFMT_NETFLOW,
196 SFLFMT_FWD,
197 SFLFMT_CLF,
198 SFLFMT_SCRIPT,
199 SFLFMT_JSON,
200 } EnumSFLFormat;
201
202 #define SA_MAX_PCAP_PKT 65536
203 #define SA_MAX_SFLOW_PKT_SIZ 65536
204
205 #define SA_MAX_FIELDNAME_LEN 64
206 #define SA_MAX_FIELD_PREFIX 4
207
208 #define MAX_STRBUF_LEN 2048
209 typedef struct {
210 int cap;
211 int len;
212 char str[MAX_STRBUF_LEN];
213 } SFStr;
214
215 typedef enum { SFSCOPE_NONE, SFSCOPE_DATAGRAM, SFSCOPE_SAMPLE } EnumSFScope;
216
217 typedef struct _SFFieldList {
218 int n;
219 char **fields;
220 SFStr *values;
221 /* dynamic info */
222 char *fieldScope;
223 int sampleFields;
224 } SFFieldList;
225
226 typedef struct _SFConfig {
227 /* sflow(R) options */
228 uint16_t sFlowInputPort;
229 /* netflow(TM) options */
230 uint16_t netFlowOutputPort;
231 SFLAddress netFlowOutputIP;
232 SFSockAddr netFlowOutputSA;
233 int netFlowOutputSocket;
234 uint16_t netFlowPeerAS;
235 int disableNetFlowScale;
236 uint16_t netFlowVersion;
237 /* tcpdump options */
238 char *readPcapFileName;
239 FILE *readPcapFile;
240 struct pcap_file_header readPcapHdr;
241 char *writePcapFile;
242 EnumSFLFormat outputFormat;
243 int jsonIndent;
244 int jsonStart;
245 int jsonListStart;
246 int outputDepth;
247 SFFieldList outputFieldList;
248 EnumSFScope currentFieldScope;
249 int pcapSwap;
250
251 #ifdef SPOOFSOURCE
252 int spoofSource;
253 uint16_t ipid;
254 struct mySendPacket sendPkt;
255 uint32_t packetLen;
256 #endif
257
258 SFForwardingTarget *forwardingTargets;
259 SFForwardingTarget6 *forwardingTargets6;
260
261 /* vlan filtering */
262 int gotVlanFilter;
263 #define FILTER_MAX_VLAN 4096
264 uint8_t vlanFilter[FILTER_MAX_VLAN + 1];
265
266 /* content stripping */
267 int removeContent;
268
269 /* options to restrict IP socket / bind */
270 int listen4;
271 int listen6;
272 int listenControlled;
273
274 /* general options */
275 int keepGoing;
276 int allowDNS;
277 } SFConfig;
278
279 /* make the options structure global to the program */
280 static SFConfig sfConfig;
281
282 /* define a separate global we can use to construct the common-log-file format */
283 typedef struct _SFCommonLogFormat {
284 #define SFLFMT_CLF_MAX_LINE 2000
285 #define SFLFMT_CLF_MAX_CLIENT_LEN 64
286 int valid;
287 char client[SFLFMT_CLF_MAX_CLIENT_LEN];
288 char http_log[SFLFMT_CLF_MAX_LINE];
289 } SFCommonLogFormat;
290
291 static SFCommonLogFormat sfCLF;
292 static const char *SFHTTP_method_names[] = { "-", "OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT" };
293
294 typedef struct _SFSample {
295 /* the raw pdu */
296 uint8_t *rawSample;
297 uint32_t rawSampleLen;
298 uint8_t *endp;
299 time_t pcapTimestamp;
300 time_t readTimestamp;
301
302 /* decode cursor */
303 uint32_t *datap;
304
305 /* datagram fields */
306 SFLAddress sourceIP;
307 SFLAddress agent_addr;
308 uint32_t agentSubId;
309 uint32_t datagramVersion;
310 uint32_t sysUpTime;
311 uint32_t sequenceNo;
312
313 /* per-element fields */
314 struct {
315 uint32_t prefixCount;
316 char *fieldPrefix[SA_MAX_FIELD_PREFIX];
317
318 uint32_t sampleType;
319 uint32_t elementType;
320 uint32_t ds_class;
321 uint32_t ds_index;
322
323 /* generic interface counter sample */
324 SFLIf_counters ifCounters;
325
326 /* data-source stream info */
327 uint32_t samplesGenerated;
328 uint32_t meanSkipCount;
329 uint32_t samplePool;
330 uint32_t dropEvents;
331
332 /* the sampled header */
333 uint32_t sampledPacketSize;
334 uint32_t packet_data_tag;
335 uint32_t headerProtocol;
336 uint8_t *header;
337 uint32_t headerLen;
338 uint32_t stripped;
339
340 /* header decode */
341 int gotIPV4;
342 int gotIPV4Struct;
343 int offsetToIPV4;
344 int gotIPV6;
345 int gotIPV6Struct;
346 int offsetToIPV6;
347 int offsetToPayload;
348 SFLAddress ipsrc;
349 SFLAddress ipdst;
350 uint32_t dcd_ipProtocol;
351 uint32_t dcd_ipTos;
352 uint32_t dcd_ipTTL;
353 uint32_t dcd_sport;
354 uint32_t dcd_dport;
355 uint32_t dcd_tcpFlags;
356 uint32_t ip_fragmentOffset;
357 uint32_t udp_pduLen;
358
359 /* ports */
360 uint32_t inputPortFormat;
361 uint32_t outputPortFormat;
362 uint32_t inputPort;
363 uint32_t outputPort;
364
365 /* ethernet */
366 uint32_t eth_type;
367 uint32_t eth_len;
368 uint8_t eth_src[8];
369 uint8_t eth_dst[8];
370
371 /* vlan */
372 uint32_t in_vlan;
373 uint32_t in_priority;
374 uint32_t internalPriority;
375 uint32_t out_vlan;
376 uint32_t out_priority;
377 int vlanFilterReject;
378
379 /* extended data fields */
380 uint32_t num_extended;
381 uint32_t extended_data_tag;
382 #define SASAMPLE_EXTENDED_DATA_SWITCH 1
383 #define SASAMPLE_EXTENDED_DATA_ROUTER 4
384 #define SASAMPLE_EXTENDED_DATA_GATEWAY 8
385 #define SASAMPLE_EXTENDED_DATA_USER 16
386 #define SASAMPLE_EXTENDED_DATA_URL 32
387 #define SASAMPLE_EXTENDED_DATA_MPLS 64
388 #define SASAMPLE_EXTENDED_DATA_NAT 128
389 #define SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL 256
390 #define SASAMPLE_EXTENDED_DATA_MPLS_VC 512
391 #define SASAMPLE_EXTENDED_DATA_MPLS_FTN 1024
392 #define SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC 2048
393 #define SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL 4096
394 #define SASAMPLE_EXTENDED_DATA_NAT_PORT 8192
395
396 /* IP forwarding info */
397 SFLAddress nextHop;
398 uint32_t srcMask;
399 uint32_t dstMask;
400
401 /* BGP info */
402 SFLAddress bgp_nextHop;
403 uint32_t my_as;
404 uint32_t src_as;
405 uint32_t src_peer_as;
406 uint32_t dst_as_path_len;
407 uint32_t *dst_as_path;
408 /* note: version 4 dst as path segments just get printed, not stored here, however
409 * the dst_peer and dst_as are filled in, since those are used for netflow encoding
410 */
411 uint32_t dst_peer_as;
412 uint32_t dst_as;
413
414 uint32_t communities_len;
415 uint32_t *communities;
416 uint32_t localpref;
417
418 /* mpls */
419 SFLAddress mpls_nextHop;
420
421 /* nat */
422 SFLAddress nat_src;
423 SFLAddress nat_dst;
424
425 /* counter blocks */
426 uint32_t statsSamplingInterval;
427 uint32_t counterBlockVersion;
428 } s;
429
430 /* exception handler context */
431 jmp_buf env;
432
433 #define ERROUT stderr
434
435 #ifdef DEBUG
436 # define SFABORT(s, r) abort()
437 # undef ERROUT
438 # define ERROUT stdout
439 #else
440 # define SFABORT(s, r) longjmp((s)->env, (r))
441 #endif
442
443 #define SF_ABORT_EOS 1
444 #define SF_ABORT_DECODE_ERROR 2
445 #define SF_ABORT_LENGTH_ERROR 3
446
447 } SFSample;
448
449 /* Cisco netflow version 5 record format */
450
451 typedef struct _NFFlow5 {
452 uint32_t srcIP;
453 uint32_t dstIP;
454 uint32_t nextHop;
455 uint16_t if_in;
456 uint16_t if_out;
457 uint32_t frames;
458 uint32_t bytes;
459 uint32_t firstTime;
460 uint32_t lastTime;
461 uint16_t srcPort;
462 uint16_t dstPort;
463 uint8_t pad1;
464 uint8_t tcpFlags;
465 uint8_t ipProto;
466 uint8_t ipTos;
467 uint16_t srcAS;
468 uint16_t dstAS;
469 uint8_t srcMask; /* No. bits */
470 uint8_t dstMask; /* No. bits */
471 uint16_t pad2;
472 } NFFlow5;
473
474 typedef struct _NFFlowHdr5 {
475 uint16_t version;
476 uint16_t count;
477 uint32_t sysUpTime;
478 uint32_t unixSeconds;
479 uint32_t unixNanoSeconds;
480 uint32_t flowSequence;
481 uint8_t engineType;
482 uint8_t engineId;
483 uint16_t sampling_interval;
484 } NFFlowHdr5;
485
486 typedef struct _NFFlowPkt5 {
487 NFFlowHdr5 hdr;
488 NFFlow5 flow; /* normally an array, but here we always send just 1 at a time */
489 } NFFlowPkt5;
490
491 /* Cisco NetFlow version 9 format */
492
493 /* NetFlow v9/ipfix element ids */
494
495 #define ID_SRC_IP 8
496 #define ID_DST_IP 12
497 #define ID_NEXT_HOP 15
498 #define ID_IF_IN 10
499 #define ID_IF_OUT 14
500 #define ID_PACKETS 2
501 #define ID_BYTES 1
502 #define ID_FIRST_SWITCHED 22
503 #define ID_LAST_SWITCHED 21
504 #define ID_SRC_PORT 7
505 #define ID_DST_PORT 11
506 #define ID_TCP_FLAGS 6
507 #define ID_PROTOCOL 4
508 #define ID_TOS 5
509 #define ID_SRC_AS 16
510 #define ID_DST_AS 17
511 #define ID_SRC_MASK 9
512 #define ID_DST_MASK 13
513 #define ID_SAMPLING_INTERVAL 34
514
515 /* NetFlow v9/ipfix element sizes */
516
517 #define SZ_SRC_IP 4
518 #define SZ_DST_IP 4
519 #define SZ_NEXT_HOP 4
520 #define SZ_IF_IN 4
521 #define SZ_IF_OUT 4
522 #define SZ_PACKETS 4
523 #define SZ_BYTES 4
524 #define SZ_FIRST_SWITCHED 4
525 #define SZ_LAST_SWITCHED 4
526 #define SZ_SRC_PORT 2
527 #define SZ_DST_PORT 2
528 #define SZ_TCP_FLAGS 1
529 #define SZ_PROTOCOL 1
530 #define SZ_TOS 1
531 #define SZ_SRC_AS 4
532 #define SZ_DST_AS 4
533 #define SZ_SRC_MASK 1
534 #define SZ_DST_MASK 1
535 #define SZ_SAMPLING_INTERVAL 4
536
537 /* NetFlow v9/ipfix element type */
538
539 typedef struct _NFField9 {
540 uint16_t id;
541 uint16_t sz;
542 } __attribute__ ((packed)) NFField9;
543
544 /* NetFlow v9/ipfix (id, sz) pairs for each element */
545
546 static const NFField9 nfField9[] = {
547 { ID_SRC_IP, SZ_SRC_IP },
548 { ID_DST_IP, SZ_DST_IP },
549 { ID_NEXT_HOP, SZ_NEXT_HOP },
550 { ID_IF_IN, SZ_IF_IN },
551 { ID_IF_OUT, SZ_IF_OUT },
552 { ID_PACKETS, SZ_PACKETS },
553 { ID_BYTES, SZ_BYTES },
554 { ID_FIRST_SWITCHED, SZ_FIRST_SWITCHED },
555 { ID_LAST_SWITCHED, SZ_LAST_SWITCHED },
556 { ID_SRC_PORT, SZ_SRC_PORT },
557 { ID_DST_PORT, SZ_DST_PORT },
558 { ID_TCP_FLAGS, SZ_TCP_FLAGS },
559 { ID_PROTOCOL, SZ_PROTOCOL },
560 { ID_TOS, SZ_TOS },
561 { ID_SRC_AS, SZ_SRC_AS },
562 { ID_DST_AS, SZ_DST_AS },
563 { ID_SRC_MASK, SZ_SRC_MASK },
564 { ID_DST_MASK, SZ_DST_MASK },
565 { ID_SAMPLING_INTERVAL, SZ_SAMPLING_INTERVAL }
566 };
567
568 /* The NetFlow v9 flow will be shaped similarly to v5,
569 * but we move sampling interval from the v5 header into
570 * the flow dataset and expand the interface field widths. */
571
572 typedef struct _NFFlow9 {
573 uint32_t srcIP;
574 uint32_t dstIP;
575 uint32_t nextHop;
576 uint32_t if_in;
577 uint32_t if_out;
578 uint32_t packets;
579 uint32_t bytes;
580 uint32_t firstTime;
581 uint32_t lastTime;
582 uint16_t srcPort;
583 uint16_t dstPort;
584 uint8_t tcpFlags;
585 uint8_t ipProto;
586 uint8_t ipTos;
587 uint32_t srcAS;
588 uint32_t dstAS;
589 uint8_t srcMask;
590 uint8_t dstMask;
591 uint32_t samplingInterval;
592 } __attribute__ ((packed)) NFFlow9;
593
594
595 /* NetFlow v9 template flowset */
596
597 typedef struct _NFTemplateFlowSet9 {
598 uint16_t setId;
599 uint16_t length;
600 uint16_t templateId;
601 uint16_t fieldCount;
602 NFField9 field[19];
603 } __attribute__ ((packed)) NFTemplateFlowSet9;
604
605
606 /* NetFlow v9 data flowset */
607
608 typedef struct _NFDataFlowSet9 {
609 uint16_t templateId;
610 uint16_t length;
611 NFFlow9 flow;
612 } __attribute__ ((packed)) NFDataFlowSet9;
613
614
615 /* NetFlow v9 flow packet header */
616
617 typedef struct _NFFlowHeader9 {
618 uint16_t version;
619 uint16_t count;
620 uint32_t sysUpTime;
621 uint32_t unixSeconds;
622 uint32_t flowSequence;
623 uint32_t sourceId;
624 } __attribute__ ((packed)) NFFlowHeader9;
625
626
627 /* NetFlow v9 flow packet */
628
629 typedef struct _NFFlowPkt9 {
630 NFFlowHeader9 hdr;
631 NFTemplateFlowSet9 tmpl;
632 NFDataFlowSet9 data;
633 } __attribute__ ((packed)) NFFlowPkt9;
634
635
636 /* NetFLow packet can be either v5 or v9 */
637
638 typedef struct _NFFlowPkt {
639 union {
640 NFFlowPkt5 v5;
641 NFFlowPkt9 v9;
642 };
643 } __attribute__ ((packed)) NFFlowPkt;
644
645
646 /* NetFlow functions to send datagrams */
647 static void sendNetFlowV5Datagram(SFSample *sample);
648 static void sendNetFlowV9Datagram(SFSample *sample);
649 static void (*sendNetFlowDatagram)(SFSample *sample) = sendNetFlowV5Datagram;
650
651 static void readFlowSample_header(SFSample *sample);
652 static void readFlowSample(SFSample *sample, int expanded);
653
654 /*_________________---------------------------__________________
655 _________________ heap allocation __________________
656 -----------------___________________________------------------
657 */
my_calloc(size_t bytes)658 void *my_calloc(size_t bytes) {
659 void *mem = calloc(1, bytes);
660 if(mem == NULL) {
661 fprintf(ERROUT, "calloc(%"PRIu64") failed: %s\n", (uint64_t)bytes, strerror(errno));
662 exit(-1);
663 }
664 return mem;
665 }
666
my_free(void * ptr)667 void my_free(void *ptr) {
668 if(ptr) {
669 free(ptr);
670 }
671 }
672
673 /*_________________---------------------------__________________
674 _________________ string buffer __________________
675 -----------------___________________________------------------
676 use string buffer scratchpad to avoid snprintf() idiosyncracies
677 */
678
SFStr_init(SFStr * sb)679 static void SFStr_init(SFStr *sb) {
680 sb->cap = MAX_STRBUF_LEN;
681 sb->len = 0;
682 sb->str[0] = '\0';
683 }
684
SFStr_str(SFStr * sb)685 static char *SFStr_str(SFStr *sb) {
686 return sb->str;
687 }
688
SFStr_len(SFStr * sb)689 static int SFStr_len(SFStr *sb) {
690 return sb->len;
691 }
692
SFStr_append(SFStr * sb,char * str)693 static int SFStr_append(SFStr *sb, char *str) {
694 if(str == NULL)
695 return YES;
696 int slen = strlen(str);
697 int copylen = strlen(str);
698 if((sb->len + copylen) >= sb->cap)
699 copylen = sb->cap - sb->len - 1;
700 if(copylen > 0) {
701 memcpy(sb->str + sb->len, str, copylen);
702 sb->len += copylen;
703 sb->str[sb->len] = '\0';
704 }
705 return (copylen == slen);
706 }
707
708 /* hex printing tends to be one of the performance bottlenecks,
709 so take the trouble to optimize it just a little */
710
711 static u_int8_t HexLookupL[513]= {
712 "000102030405060708090a0b0c0d0e0f"
713 "101112131415161718191a1b1c1d1e1f"
714 "202122232425262728292a2b2c2d2e2f"
715 "303132333435363738393a3b3c3d3e3f"
716 "404142434445464748494a4b4c4d4e4f"
717 "505152535455565758595a5b5c5d5e5f"
718 "606162636465666768696a6b6c6d6e6f"
719 "707172737475767778797a7b7c7d7e7f"
720 "808182838485868788898a8b8c8d8e8f"
721 "909192939495969798999a9b9c9d9e9f"
722 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
723 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
724 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
725 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
726 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
727 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
728 };
729
730 static uint8_t HexLookupU[513]= {
731 "000102030405060708090A0B0C0D0E0F"
732 "101112131415161718191A1B1C1D1E1F"
733 "202122232425262728292A2B2C2D2E2F"
734 "303132333435363738393A3B3C3D3E3F"
735 "404142434445464748494A4B4C4D4E4F"
736 "505152535455565758595A5B5C5D5E5F"
737 "606162636465666768696A6B6C6D6E6F"
738 "707172737475767778797A7B7C7D7E7F"
739 "808182838485868788898A8B8C8D8E8F"
740 "909192939495969798999A9B9C9D9E9F"
741 "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"
742 "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"
743 "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"
744 "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"
745 "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"
746 "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"
747 };
748
SFStr_append_hex(SFStr * sb,u_char * hex,int nbytes,int prefix,int upper,char sep)749 static int SFStr_append_hex(SFStr *sb, u_char *hex, int nbytes, int prefix, int upper, char sep) {
750 if(prefix) {
751 if((sb->cap - sb->len) < 3)
752 return NO;
753 sb->str[sb->len++] = '0';
754 sb->str[sb->len++] = 'x';
755 }
756 int hexPerByte = 2;
757 if(sep) hexPerByte++;
758 int roomForBytes = (sb->cap - sb->len - 1) / hexPerByte;
759 if(nbytes > roomForBytes)
760 nbytes = roomForBytes;
761
762 uint16_t *lookup = (uint16_t *)(upper ? HexLookupU : HexLookupL);
763
764 for(int ii = 0; ii < nbytes; ii++) {
765 if(sep && ii) sb->str[sb->len++] = sep;
766 uint16_t word = ntohs(lookup[hex[ii]]);
767 sb->str[sb->len++] = word >> 8;
768 sb->str[sb->len++] = word & 0xFF;
769 }
770
771 sb->str[sb->len] = '\0';
772 return (nbytes < roomForBytes);
773 }
774
SFStr_append_array32(SFStr * sb,uint32_t * array32,int n,int net_byte_order,char sep)775 static int SFStr_append_array32(SFStr *sb, uint32_t *array32, int n, int net_byte_order, char sep) {
776 for(int i = 0; i < n; i++) {
777 char ibuf[32];
778 uint32_t val32 = array32[i];
779 if(net_byte_order)
780 val32 = ntohl(val32);
781 sprintf(ibuf, "%u", val32);
782 int ilen = strlen(ibuf);
783 if((sb->len + 1 + ilen) >= sb->cap)
784 return NO;
785 if(i > 0)
786 sb->str[sb->len++] = sep;
787 memcpy(sb->str + sb->len, ibuf, ilen);
788 sb->len += ilen;
789 sb->str[sb->len] = '\0';
790 }
791 return YES;
792 }
793
SFStr_append_U32(SFStr * sb,char * fmt,uint32_t val32)794 static int SFStr_append_U32(SFStr *sb, char *fmt, uint32_t val32) {
795 char ibuf[200];
796 sprintf(ibuf, fmt, val32);
797 return SFStr_append(sb, ibuf);
798 }
799
SFStr_append_U64(SFStr * sb,char * fmt,uint64_t val64)800 static int SFStr_append_U64(SFStr *sb, char *fmt, uint64_t val64) {
801 char ibuf[200];
802 sprintf(ibuf, fmt, val64);
803 return SFStr_append(sb, ibuf);
804 return YES;
805 }
806
SFStr_append_double(SFStr * sb,char * fmt,double vald)807 static int SFStr_append_double(SFStr *sb, char *fmt, double vald) {
808 char ibuf[200];
809 sprintf(ibuf, fmt, vald);
810 return SFStr_append(sb, ibuf);
811 return YES;
812 }
813
SFStr_append_mac(SFStr * sb,uint8_t * mac)814 static int SFStr_append_mac(SFStr *sb, uint8_t *mac) {
815 return SFStr_append_hex(sb, mac, 6, NO, NO, 0);
816 }
817
SFStr_append_ip(SFStr * sb,uint8_t * ip)818 static int SFStr_append_ip(SFStr *sb, uint8_t *ip) {
819 uint32_t array32[4];
820 for(int i = 0; i < 4; i++)
821 array32[i] = ip[i];
822 return SFStr_append_array32(sb, array32, 4, NO, '.');
823 }
824
SFStr_append_ip6(SFStr * sb,uint8_t * ip6)825 static int SFStr_append_ip6(SFStr *sb, uint8_t *ip6) {
826 for(int i = 0; i < 16; i += 2) {
827 if(i > 0
828 && SFStr_append(sb, ":") == NO)
829 return NO;
830 if(SFStr_append_hex(sb, (ip6+i), 2, NO, NO, 0) == NO)
831 return NO;
832 }
833 return YES;
834 }
835
SFStr_append_address(SFStr * sb,SFLAddress * address)836 static int SFStr_append_address(SFStr *sb, SFLAddress *address) {
837 if(address->type == SFLADDRESSTYPE_IP_V4)
838 return SFStr_append_ip(sb, (uint8_t *)&address->address.ip_v4.addr);
839 if(address->type == SFLADDRESSTYPE_IP_V6)
840 return SFStr_append_ip6(sb, address->address.ip_v6.addr);
841 return SFStr_append(sb, "-");
842 }
843
SFStr_append_UUID(SFStr * sb,uint8_t * uuid)844 static int SFStr_append_UUID(SFStr *sb, uint8_t *uuid) {
845 SFStr_append_hex(sb, uuid, 4, NO, NO, 0);
846 SFStr_append(sb, "-");
847 SFStr_append_hex(sb, uuid+4, 2, NO, NO, 0);
848 SFStr_append(sb, "-");
849 SFStr_append_hex(sb, uuid+6, 2, NO, NO, 0);
850 SFStr_append(sb, "-");
851 SFStr_append_hex(sb, uuid+8, 2, NO, NO, 0);
852 SFStr_append(sb, "-");
853 return SFStr_append_hex(sb, uuid+10, 6, NO, NO, 0);
854 }
855
SFStr_append_tag(SFStr * sb,uint32_t tag)856 static int SFStr_append_tag(SFStr *sb, uint32_t tag) {
857 uint32_t parts[2];
858 parts[0] = (tag >> 12);
859 parts[1] = (tag & 0x00000FFF);
860 return SFStr_append_array32(sb, parts, 2, NO, ':');
861 }
862
SFStr_append_timestamp(SFStr * sb,time_t ts)863 static int SFStr_append_timestamp(SFStr *sb, time_t ts) {
864 char tstr[200];
865 /* ISO8601 compatible localtime */
866 strftime(tstr, 200, "%Y-%m-%dT%H:%M:%S%z", localtime(&ts));
867 return SFStr_append(sb, tstr);
868 }
869
SFStr_append_dataSource(SFStr * sb,uint32_t ds_class,uint32_t ds_index)870 static int SFStr_append_dataSource(SFStr *sb, uint32_t ds_class, uint32_t ds_index) {
871 char buf[200];
872 sprintf(buf, "%u:%u", ds_class, ds_index);
873 return SFStr_append(sb, buf);
874 }
875
SFStr_copy(SFStr * sb,char * to,int capacity)876 static int SFStr_copy(SFStr *sb, char *to, int capacity) {
877 int max = capacity - 1;
878 int bytes = max > sb->len ? sb->len : max;
879 memcpy(to, sb->str, bytes);
880 to[bytes] = '\0';
881 return bytes;
882 }
883
884 /*_________________---------------------------__________________
885 _________________ print functions __________________
886 -----------------___________________________------------------
887 */
888
printAddress(SFLAddress * address,SFStr * sb)889 static char *printAddress(SFLAddress *address, SFStr *sb) {
890 SFStr_init(sb);
891 SFStr_append_address(sb, address);
892 return SFStr_str(sb);
893 }
894
printMAC(uint8_t * mac,SFStr * sb)895 static char *printMAC(uint8_t *mac, SFStr *sb) {
896 SFStr_init(sb);
897 SFStr_append_mac(sb, mac);
898 return SFStr_str(sb);
899 }
900
printTag(uint32_t tag,SFStr * sb)901 static char *printTag(uint32_t tag, SFStr *sb) {
902 SFStr_init(sb);
903 SFStr_append_tag(sb, tag);
904 return SFStr_str(sb);
905 }
906
printTimestamp(time_t ts,SFStr * sb)907 static char *printTimestamp(time_t ts, SFStr *sb) {
908 SFStr_init(sb);
909 SFStr_append_timestamp(sb, ts);
910 return SFStr_str(sb);
911 }
912
printOUI(uint8_t * oui,SFStr * sb)913 static char *printOUI(uint8_t *oui, SFStr *sb) {
914 SFStr_init(sb);
915 SFStr_append_hex(sb, oui, 3, NO, YES, '-');
916 return SFStr_str(sb);
917 }
918
printDataSource(uint32_t ds_class,uint32_t ds_index,SFStr * sb)919 static char *printDataSource(uint32_t ds_class, uint32_t ds_index, SFStr *sb) {
920 SFStr_init(sb);
921 SFStr_append_dataSource(sb, ds_class, ds_index);
922 return SFStr_str(sb);
923 }
924
printOutputPort_v2v4(uint32_t outputPort,SFStr * sb)925 static char *printOutputPort_v2v4(uint32_t outputPort, SFStr *sb) {
926 SFStr_init(sb);
927 if(outputPort & 0x80000000) {
928 uint32_t numOutputs = outputPort & 0x7fffffff;
929 if(numOutputs > 0)
930 SFStr_append_U32(sb, "multiple %d", numOutputs);
931 else
932 SFStr_append(sb, "multiple >1");
933 }
934 else SFStr_append_U32(sb, "%u", outputPort);
935 return SFStr_str(sb);
936 }
937
printInOutPort(uint32_t port,uint32_t format,SFStr * sb)938 static char *printInOutPort(uint32_t port, uint32_t format, SFStr *sb) {
939 SFStr_init(sb);
940 switch(format) {
941 case 3: SFStr_append_U32(sb, "format==3 %u", port); break;
942 case 2: SFStr_append_U32(sb, "multiple %u", port); break;
943 case 1: SFStr_append_U32(sb, "dropCode %u", port); break;
944 case 0: SFStr_append_U32(sb, "%u", port); break;
945 }
946 return SFStr_str(sb);
947 }
948
949 /*_________________---------------------------__________________
950 _________________ JSON utils __________________
951 -----------------___________________________------------------
952 */
953
json_indent()954 static void json_indent() {
955 if(sfConfig.jsonIndent) {
956 putchar('\n');
957 for(int ii=0; ii<sfConfig.outputDepth; ii++)
958 putchar(' ');
959 }
960 }
961
json_start(char * fname,char bracket)962 static void json_start(char *fname, char bracket) {
963 if(sfConfig.jsonStart) {
964 sfConfig.jsonStart = NO;
965 }
966 else if(sfConfig.jsonListStart == NO) {
967 putchar(',');
968 json_indent();
969 }
970 if(fname)
971 printf("\"%s\":", fname);
972 putchar(bracket);
973 sfConfig.outputDepth++;
974 /* indicate start of list */
975 sfConfig.jsonListStart = YES;
976 }
977
json_end(char bracket)978 static void json_end(char bracket) {
979 sfConfig.outputDepth--;
980 json_indent();
981 printf("%c", bracket);
982 /* clear list-start flag in case array/obj was emtpy */
983 sfConfig.jsonListStart = NO;
984 }
985
json_start_ob(char * fname)986 static void json_start_ob(char *fname) { json_start(fname, '{'); }
json_start_ar(char * fname)987 static void json_start_ar(char *fname) { json_start(fname, '['); }
json_end_ob()988 static void json_end_ob() { json_end('}'); }
json_end_ar()989 static void json_end_ar() { json_end(']'); }
990
991 /*_________________---------------------------__________________
992 _________________ sf_log __________________
993 -----------------___________________________------------------
994 */
995
sf_logf_pushPrefix(SFSample * sample,char * prefix)996 static void sf_logf_pushPrefix(SFSample *sample, char *prefix) {
997 if(sample->s.prefixCount < SA_MAX_FIELD_PREFIX)
998 sample->s.fieldPrefix[sample->s.prefixCount++] = prefix;
999 else {
1000 fprintf(ERROUT, "reached field prefix limit with %s\n", prefix);
1001 SFABORT(sample, SF_ABORT_DECODE_ERROR);
1002 }
1003 }
1004
sf_logf_popPrefix(SFSample * sample)1005 static void sf_logf_popPrefix(SFSample *sample) {
1006 if(sample->s.prefixCount > 0)
1007 --sample->s.prefixCount;
1008 else {
1009 fprintf(ERROUT, "no prefix to pop\n");
1010 SFABORT(sample, SF_ABORT_DECODE_ERROR);
1011 }
1012 }
1013
printPrefix(SFSample * sample,SFStr * sb)1014 static char *printPrefix(SFSample *sample, SFStr *sb) {
1015 uint32_t ii;
1016 SFStr_init(sb);
1017 for(ii = 0; ii < sample->s.prefixCount; ii++)
1018 SFStr_append(sb, sample->s.fieldPrefix[ii]);
1019 return SFStr_str(sb);
1020 }
1021
sf_log_context(SFSample * sample)1022 static void sf_log_context(SFSample *sample) {
1023 SFStr agentIP, tag1, tag2, nowstr;
1024 time_t now = sample->pcapTimestamp ?: sample->readTimestamp;
1025 printf("%s %s %u %u %u:%u %s %s ",
1026 printTimestamp(now, &nowstr),
1027 printAddress(&sample->agent_addr, &agentIP),
1028 sample->agentSubId,
1029 sample->sequenceNo,
1030 sample->s.ds_class,
1031 sample->s.ds_index,
1032 printTag(sample->s.sampleType, &tag1),
1033 printTag(sample->s.elementType, &tag2));
1034 }
1035
sf_log(SFSample * sample,char * fmt,...)1036 static void sf_log(SFSample *sample, char *fmt, ...) {
1037 /* don't print anything here unless exporting in FULL or SCRIPT formats */
1038
1039 /* scripts like to have all the context on every line */
1040 if(sfConfig.outputFormat == SFLFMT_SCRIPT)
1041 sf_log_context(sample);
1042
1043 if(sfConfig.outputFormat == SFLFMT_FULL
1044 || sfConfig.outputFormat == SFLFMT_SCRIPT) {
1045 va_list args;
1046 va_start(args, fmt);
1047 if(vprintf(fmt, args) < 0) {
1048 exit(-40);
1049 }
1050 }
1051 }
1052
sf_logf(SFSample * sample,char * fieldName,char * val)1053 static void sf_logf(SFSample *sample, char *fieldName, char *val)
1054 {
1055 /* This log-field variant prints for the FULL, SCRIPT and JSON formats. */
1056 SFStr prefix;
1057
1058 /* scripts like to have all the context on every line */
1059 if(sfConfig.outputFormat == SFLFMT_SCRIPT)
1060 sf_log_context(sample);
1061
1062 if(sfConfig.outputFormat == SFLFMT_FULL
1063 || sfConfig.outputFormat == SFLFMT_SCRIPT) {
1064 if(printf("%s%s %s\n", printPrefix(sample, &prefix), fieldName, val) < 0)
1065 exit(-40);
1066 }
1067
1068 if(sfConfig.outputFormat == SFLFMT_JSON) {
1069 if(sfConfig.jsonListStart == NO)
1070 putchar(',');
1071 else
1072 sfConfig.jsonListStart = NO;
1073
1074 json_indent();
1075 /* always print as JSON strings, since value may be 64-bit integer */
1076 if(printf("\"%s%s\":\"%s\"", printPrefix(sample, &prefix), fieldName, val) < 0)
1077 exit(-40);
1078 }
1079
1080 if(sfConfig.outputFormat == SFLFMT_LINE_CUSTOM) {
1081 /* build key */
1082 SFStr buf;
1083 int slot;
1084 char *field = fieldName;
1085 if(sample->s.prefixCount) {
1086 SFStr_init(&buf);
1087 SFStr_append(&buf, printPrefix(sample, &prefix));
1088 SFStr_append(&buf, fieldName);
1089 field = SFStr_str(&buf);
1090 }
1091 /* see if we want this field */
1092 ENTRY e, *ep;
1093 e.key = field;
1094 ep = hsearch(e, FIND);
1095 if(ep) {
1096 /* yes, store value in slot */
1097 int slot = *(int*)ep->data;
1098 SFStr *value = &sfConfig.outputFieldList.values[slot];
1099 SFStr_init(value);
1100 SFStr_append(value, val);
1101 /* and remember it's scope */
1102 sfConfig.outputFieldList.fieldScope[slot] = sfConfig.currentFieldScope;
1103 /* and count the number of sample fields seen */
1104 if(sfConfig.currentFieldScope == SFSCOPE_SAMPLE)
1105 sfConfig.outputFieldList.sampleFields++;
1106 }
1107 }
1108 }
1109
sf_logf_U32_formatted(SFSample * sample,char * fieldPrefix,char * fieldName,char * fmt,uint32_t val32)1110 static void sf_logf_U32_formatted(SFSample *sample, char *fieldPrefix, char *fieldName, char *fmt, uint32_t val32) {
1111 SFStr buf;
1112 SFStr_init(&buf);
1113 SFStr_append_U32(&buf, fmt, val32);
1114 sf_logf_pushPrefix(sample, fieldPrefix);
1115 sf_logf(sample, fieldName, SFStr_str(&buf));
1116 sf_logf_popPrefix(sample);
1117 }
1118
sf_logf_U64_formatted(SFSample * sample,char * fieldPrefix,char * fieldName,char * fmt,uint64_t val64)1119 static void sf_logf_U64_formatted(SFSample *sample, char *fieldPrefix, char *fieldName, char *fmt, uint64_t val64) {
1120 SFStr buf;
1121 SFStr_init(&buf);
1122 SFStr_append_U64(&buf, fmt, val64);
1123 sf_logf_pushPrefix(sample, fieldPrefix);
1124 sf_logf(sample, fieldName, SFStr_str(&buf));
1125 sf_logf_popPrefix(sample);
1126 }
1127
sf_logf_double_formatted(SFSample * sample,char * fieldPrefix,char * fieldName,char * fmt,double vald)1128 static void sf_logf_double_formatted(SFSample *sample, char *fieldPrefix, char *fieldName, char *fmt, double vald) {
1129 SFStr buf;
1130 SFStr_init(&buf);
1131 SFStr_append_double(&buf, fmt, vald);
1132 sf_logf_pushPrefix(sample, fieldPrefix);
1133 sf_logf(sample, fieldName, SFStr_str(&buf));
1134 sf_logf_popPrefix(sample);
1135 }
1136
1137 /* shortcuts for convenience */
1138
sf_logf_U32(SFSample * sample,char * fieldName,uint32_t val32)1139 static void sf_logf_U32(SFSample *sample, char *fieldName, uint32_t val32) {
1140 sf_logf_U32_formatted(sample, NULL, fieldName, "%u", val32);
1141 }
1142
sf_logf_U64(SFSample * sample,char * fieldName,uint64_t val64)1143 static void sf_logf_U64(SFSample *sample, char *fieldName, uint64_t val64) {
1144 sf_logf_U64_formatted(sample, NULL, fieldName, "%"PRIu64, val64);
1145 }
1146
1147 /*_________________---------------------------__________________
1148 _________________ URLEncode __________________
1149 -----------------___________________________------------------
1150 */
1151
URLEncode(char * in,char * out,int outlen)1152 char *URLEncode(char *in, char *out, int outlen)
1153 {
1154 register char c, *r = in, *w = out;
1155 int maxlen = (strlen(in) * 3) + 1;
1156 if(outlen < maxlen) return "URLEncode: not enough space";
1157 uint16_t *lookup = (uint16_t *)HexLookupU;
1158 while ((c = *r++)) {
1159 if(isalnum(c)) *w++ = c;
1160 else if(isspace(c)) *w++ = '+';
1161 else {
1162 uint16_t word = lookup[c];
1163 *w++ = '%';
1164 *w++ = word >> 8;
1165 *w++ = word & 255;
1166 }
1167 }
1168 *w++ = '\0';
1169 return out;
1170 }
1171
1172 /*_________________---------------------------__________________
1173 _________________ sampleFilterOK __________________
1174 -----------------___________________________------------------
1175 */
1176
sampleFilterOK(SFSample * sample)1177 int sampleFilterOK(SFSample *sample)
1178 {
1179 /* the vlan filter will only reject a sample if both in_vlan and out_vlan are rejected. If the
1180 vlan was not reported in an SFLExtended_Switch struct, but was only picked up from the 802.1q header
1181 then the out_vlan will be 0, so to be sure you are rejecting vlan 1, you may need to reject both
1182 vlan 0 and vlan 1. */
1183 return(sfConfig.gotVlanFilter == NO
1184 || sfConfig.vlanFilter[sample->s.in_vlan]
1185 || sfConfig.vlanFilter[sample->s.out_vlan]);
1186 }
1187
1188 /*_________________---------------------------__________________
1189 _________________ writeFlowLine __________________
1190 -----------------___________________________------------------
1191 */
1192
writeFlowLine(SFSample * sample)1193 static void writeFlowLine(SFSample *sample)
1194 {
1195 SFStr agentIP, srcMAC, dstMAC, srcIP, dstIP;
1196 /* source */
1197 if(printf("FLOW,%s,%d,%d,",
1198 printAddress(&sample->agent_addr, &agentIP),
1199 sample->s.inputPort,
1200 sample->s.outputPort) < 0) {
1201 exit(-41);
1202 }
1203 /* layer 2 */
1204 if(printf("%s,%s,0x%04x,%d,%d",
1205 printMAC(sample->s.eth_src, &srcMAC),
1206 printMAC(sample->s.eth_dst, &dstMAC),
1207 sample->s.eth_type,
1208 sample->s.in_vlan,
1209 sample->s.out_vlan) < 0) {
1210 exit(-42);
1211 }
1212 /* layer 3/4 */
1213 if(printf(",%s,%s,%d,0x%02x,%d,%d,%d,0x%02x",
1214 printAddress(&sample->s.ipsrc, &srcIP),
1215 printAddress(&sample->s.ipdst, &dstIP),
1216 sample->s.dcd_ipProtocol,
1217 sample->s.dcd_ipTos,
1218 sample->s.dcd_ipTTL,
1219 sample->s.dcd_sport,
1220 sample->s.dcd_dport,
1221 sample->s.dcd_tcpFlags) < 0) {
1222 exit(-43);
1223 }
1224 /* bytes */
1225 if(printf(",%d,%d,%d\n",
1226 sample->s.sampledPacketSize,
1227 sample->s.sampledPacketSize - sample->s.stripped - sample->s.offsetToIPV4,
1228 sample->s.meanSkipCount) < 0) {
1229 exit(-44);
1230 }
1231 }
1232
1233 /*_________________---------------------------__________________
1234 _________________ writeLineCustom __________________
1235 -----------------___________________________------------------
1236 */
1237
writeLineCustom(SFSample * sample)1238 static void writeLineCustom(SFSample *sample)
1239 {
1240 /* don't print anything if we didn't match any sample-level fields */
1241 if(sfConfig.outputFieldList.sampleFields == 0)
1242 return;
1243
1244 for(int ii = 0; ii < sfConfig.outputFieldList.n; ii++) {
1245 if(ii>0)
1246 printf(",");
1247 char *field = sfConfig.outputFieldList.fields[ii];
1248 SFStr *val = &sfConfig.outputFieldList.values[ii];
1249 if(val->len)
1250 printf("%s", SFStr_str(val));
1251 }
1252 printf("\n");
1253 }
1254
1255 /*_________________---------------------------__________________
1256 _________________ clearLineCustom __________________
1257 -----------------___________________________------------------
1258 */
1259
clearLineCustom(SFSample * sample,EnumSFScope scope)1260 static void clearLineCustom(SFSample *sample, EnumSFScope scope)
1261 {
1262 for(int ii = 0; ii < sfConfig.outputFieldList.n; ii++) {
1263 if(sfConfig.outputFieldList.fieldScope[ii] == scope) {
1264 SFStr *val = &sfConfig.outputFieldList.values[ii];
1265 SFStr_init(val);
1266 }
1267 }
1268 sfConfig.outputFieldList.sampleFields = 0;
1269 }
1270
1271 /*_________________---------------------------__________________
1272 _________________ writeCountersLine __________________
1273 -----------------___________________________------------------
1274 */
1275
writeCountersLine(SFSample * sample)1276 static void writeCountersLine(SFSample *sample)
1277 {
1278 /* source */
1279 SFStr agentIP;
1280 if(printf("CNTR,%s,", printAddress(&sample->agent_addr, &agentIP)) < 0) {
1281 exit(-45);
1282 }
1283 if(printf("%u,%u,%"PRIu64",%u,%u,%"PRIu64",%u,%u,%u,%u,%u,%u,%"PRIu64",%u,%u,%u,%u,%u,%u\n",
1284 sample->s.ifCounters.ifIndex,
1285 sample->s.ifCounters.ifType,
1286 sample->s.ifCounters.ifSpeed,
1287 sample->s.ifCounters.ifDirection,
1288 sample->s.ifCounters.ifStatus,
1289 sample->s.ifCounters.ifInOctets,
1290 sample->s.ifCounters.ifInUcastPkts,
1291 sample->s.ifCounters.ifInMulticastPkts,
1292 sample->s.ifCounters.ifInBroadcastPkts,
1293 sample->s.ifCounters.ifInDiscards,
1294 sample->s.ifCounters.ifInErrors,
1295 sample->s.ifCounters.ifInUnknownProtos,
1296 sample->s.ifCounters.ifOutOctets,
1297 sample->s.ifCounters.ifOutUcastPkts,
1298 sample->s.ifCounters.ifOutMulticastPkts,
1299 sample->s.ifCounters.ifOutBroadcastPkts,
1300 sample->s.ifCounters.ifOutDiscards,
1301 sample->s.ifCounters.ifOutErrors,
1302 sample->s.ifCounters.ifPromiscuousMode) < 0) {
1303 exit(-46);
1304 }
1305 }
1306
1307 /*_________________---------------------------__________________
1308 _________________ receiveError __________________
1309 -----------------___________________________------------------
1310 */
1311
receiveError(SFSample * sample,char * errm,int hexdump)1312 static void receiveError(SFSample *sample, char *errm, int hexdump)
1313 {
1314 SFStr ipbuf;
1315 SFStr hex;
1316 char *msg = "";
1317 uint32_t markOffset = (uint8_t *)sample->datap - sample->rawSample;
1318 fprintf(ERROUT, "%s (source IP = %s)\n",
1319 errm ?: "ERROR", printAddress(&sample->sourceIP, &ipbuf));
1320 if(hexdump) {
1321 int lineN = 16;
1322 for(int ii = 0; ii < sample->rawSampleLen; ) {
1323 SFStr_init(&hex);
1324 int toEnd = sample->rawSampleLen - ii;
1325 int toEOL = toEnd < lineN ? toEnd : lineN;
1326 int toMark = markOffset - ii;
1327 if(toMark >= 0 && toMark < toEOL) {
1328 SFStr_append_hex(&hex, sample->rawSample + ii, toMark, NO, NO, '-');
1329 ii += toMark;
1330 SFStr_append(&hex, "-<*>-");
1331 toEOL -= toMark;
1332 }
1333 SFStr_append_hex(&hex, sample->rawSample + ii, toEOL, NO, NO, '-');
1334 ii += toEOL;
1335 fprintf(stderr, "%s\n", SFStr_str(&hex));
1336 }
1337 }
1338 SFABORT(sample, SF_ABORT_DECODE_ERROR);
1339 }
1340
1341 /*_________________---------------------------__________________
1342 _________________ lengthCheck __________________
1343 -----------------___________________________------------------
1344 */
1345
lengthCheck(SFSample * sample,char * description,uint8_t * start,int len)1346 static void lengthCheck(SFSample *sample, char *description, uint8_t *start, int len) {
1347 uint32_t actualLen = (uint8_t *)sample->datap - start;
1348 uint32_t adjustedLen = ((len + 3) >> 2) << 2;
1349 if(actualLen != adjustedLen) {
1350 fprintf(ERROUT, "%s length error (expected %d, found %d)\n", description, len, actualLen);
1351 SFABORT(sample, SF_ABORT_LENGTH_ERROR);
1352 }
1353 }
1354
1355 /*_________________---------------------------__________________
1356 _________________ decodeLinkLayer __________________
1357 -----------------___________________________------------------
1358 store the offset to the start of the ipv4 header in the sequence_number field
1359 or -1 if not found. Decode the 802.1d if it's there.
1360 */
1361
1362 #define NFT_ETHHDR_SIZ 14
1363 #define NFT_8022_SIZ 3
1364 #define NFT_MAX_8023_LEN 1500
1365
1366 #define NFT_MIN_SIZ (NFT_ETHHDR_SIZ + sizeof(struct myiphdr))
1367
decodeLinkLayer(SFSample * sample)1368 static void decodeLinkLayer(SFSample *sample)
1369 {
1370 uint8_t *start = sample->s.header;
1371 uint8_t *end = start + sample->s.headerLen;
1372 uint8_t *ptr = start;
1373 uint16_t type_len;
1374 uint32_t vlanDepth=0;
1375 SFStr buf;
1376
1377 /* assume not found */
1378 sample->s.gotIPV4 = NO;
1379 sample->s.gotIPV6 = NO;
1380
1381 if((end - ptr) < NFT_ETHHDR_SIZ) return; /* not enough for an Ethernet header */
1382
1383 sf_logf(sample, "dstMAC", printMAC(ptr, &buf));
1384 memcpy(sample->s.eth_dst, ptr, 6);
1385 ptr += 6;
1386 sf_logf(sample, "srcMAC", printMAC(ptr, &buf));
1387 memcpy(sample->s.eth_src, ptr, 6);
1388 ptr += 6;
1389 type_len = (ptr[0] << 8) + ptr[1];
1390 ptr += 2;
1391
1392 while(type_len == 0x8100
1393 || type_len == 0x88A8
1394 || type_len == 0x9100
1395 || type_len == 0x9200
1396 || type_len == 0x9300) {
1397 if((end - ptr) < 4) return; /* not enough for an 802.1Q header */
1398 /* VLAN - next two bytes */
1399 uint32_t vlanData = (ptr[0] << 8) + ptr[1];
1400 uint32_t vlan = vlanData & 0x0fff;
1401 uint32_t priority = vlanData >> 13;
1402 ptr += 2;
1403 /* _____________________________________ */
1404 /* | pri | c | vlan-id | */
1405 /* ------------------------------------- */
1406 /* [priority = 3bits] [Canonical Format Flag = 1bit] [vlan-id = 12 bits] */
1407 if(vlanDepth == 0) {
1408 sf_logf_U32(sample, "decodedVLAN", vlan);
1409 sf_logf_U32(sample, "decodedPriority", priority);
1410 }
1411 else {
1412 /* 802.1AD / Q-in-Q: indicate VLAN depth */
1413 char dotQField[64];
1414 sprintf(dotQField, "decodedVLAN.%u", vlanDepth);
1415 sf_logf_U32(sample, dotQField, vlan);
1416 sprintf(dotQField, "decodedPriority.%u", vlanDepth);
1417 sf_logf_U32(sample, dotQField, priority);
1418 }
1419 sample->s.in_vlan = vlan;
1420 /* now get the type_len again (next two bytes) */
1421 type_len = (ptr[0] << 8) + ptr[1];
1422 ptr += 2;
1423 vlanDepth++;
1424 }
1425
1426 /* now we're just looking for IP */
1427 if((end - start) < sizeof(struct myiphdr)) return; /* not enough for an IPv4 header (or IPX, or SNAP) */
1428
1429 /* peek for IPX */
1430 if(type_len == 0x0200 || type_len == 0x0201 || type_len == 0x0600) {
1431 #define IPX_HDR_LEN 30
1432 #define IPX_MAX_DATA 546
1433 int ipxChecksum = (ptr[0] == 0xff && ptr[1] == 0xff);
1434 int ipxLen = (ptr[2] << 8) + ptr[3];
1435 if(ipxChecksum &&
1436 ipxLen >= IPX_HDR_LEN &&
1437 ipxLen <= (IPX_HDR_LEN + IPX_MAX_DATA))
1438 /* we don't do anything with IPX here */
1439 return;
1440 }
1441 if(type_len <= NFT_MAX_8023_LEN) {
1442 /* assume 802.3+802.2 header */
1443 /* check for SNAP */
1444 if(ptr[0] == 0xAA &&
1445 ptr[1] == 0xAA &&
1446 ptr[2] == 0x03) {
1447 ptr += 3;
1448 if(ptr[0] != 0 ||
1449 ptr[1] != 0 ||
1450 ptr[2] != 0) {
1451 sf_logf(sample, "VSNAP_OUI", printOUI(ptr, &buf));
1452 return; /* no further decode for vendor-specific protocol */
1453 }
1454 ptr += 3;
1455 /* OUI == 00-00-00 means the next two bytes are the ethernet type (RFC 2895) */
1456 type_len = (ptr[0] << 8) + ptr[1];
1457 ptr += 2;
1458 }
1459 else {
1460 if (ptr[0] == 0x06 &&
1461 ptr[1] == 0x06 &&
1462 (ptr[2] & 0x01)) {
1463 /* IP over 8022 */
1464 ptr += 3;
1465 /* force the type_len to be IP so we can inline the IP decode below */
1466 type_len = 0x0800;
1467 }
1468 else return;
1469 }
1470 }
1471
1472 /* assume type_len is an ethernet-type now */
1473 sample->s.eth_type = type_len;
1474
1475 if(type_len == 0x0800) {
1476 /* IPV4 - check again that we have enough header bytes */
1477 if((end - ptr) < sizeof(struct myiphdr)) return;
1478 /* look at first byte of header.... */
1479 /* ___________________________ */
1480 /* | version | hdrlen | */
1481 /* --------------------------- */
1482 if((*ptr >> 4) != 4) return; /* not version 4 */
1483 if((*ptr & 15) < 5) return; /* not IP (hdr len must be 5 quads or more) */
1484 /* survived all the tests - store the offset to the start of the ip header */
1485 sample->s.gotIPV4 = YES;
1486 sample->s.offsetToIPV4 = (ptr - start);
1487 }
1488
1489 if(type_len == 0x86DD) {
1490 /* IPV6 */
1491 /* look at first byte of header.... */
1492 if((*ptr >> 4) != 6) return; /* not version 6 */
1493 /* survived all the tests - store the offset to the start of the ip6 header */
1494 sample->s.gotIPV6 = YES;
1495 sample->s.offsetToIPV6 = (ptr - start);
1496 }
1497 }
1498
1499 /*_________________---------------------------__________________
1500 _________________ decode80211MAC __________________
1501 -----------------___________________________------------------
1502 store the offset to the start of the ipv4 header in the sequence_number field
1503 or -1 if not found.
1504 */
1505
1506 #define WIFI_MIN_HDR_SIZ 24
1507
decode80211MAC(SFSample * sample)1508 static void decode80211MAC(SFSample *sample)
1509 {
1510 uint8_t *start = sample->s.header;
1511 uint8_t *end = start + sample->s.headerLen;
1512 uint8_t *ptr = start;
1513
1514 /* assume not found */
1515 sample->s.gotIPV4 = NO;
1516 sample->s.gotIPV6 = NO;
1517
1518 if(sample->s.headerLen < WIFI_MIN_HDR_SIZ) return; /* not enough for an 80211 MAC header */
1519
1520 uint32_t fc = (ptr[1] << 8) + ptr[0]; /* [b7..b0][b15..b8] */
1521 uint32_t protocolVersion = fc & 3;
1522 uint32_t control = (fc >> 2) & 3;
1523 uint32_t subType = (fc >> 4) & 15;
1524 uint32_t toDS = (fc >> 8) & 1;
1525 uint32_t fromDS = (fc >> 9) & 1;
1526 uint32_t moreFrag = (fc >> 10) & 1;
1527 uint32_t retry = (fc >> 11) & 1;
1528 uint32_t pwrMgt = (fc >> 12) & 1;
1529 uint32_t moreData = (fc >> 13) & 1;
1530 uint32_t encrypted = (fc >> 14) & 1;
1531 uint32_t order = fc >> 15;
1532
1533 ptr += 2;
1534
1535 uint32_t duration_id = (ptr[1] << 8) + ptr[0]; /* not in network byte order either? */
1536 ptr += 2;
1537
1538 switch(control) {
1539 case 0: /* mgmt */
1540 case 1: /* ctrl */
1541 case 3: /* rsvd */
1542 break;
1543
1544 case 2: /* data */
1545 {
1546
1547 uint8_t *macAddr1 = ptr;
1548 ptr += 6;
1549 uint8_t *macAddr2 = ptr;
1550 ptr += 6;
1551 uint8_t *macAddr3 = ptr;
1552 ptr += 6;
1553 uint32_t sequence = (ptr[0] << 8) + ptr[1];
1554 ptr += 2;
1555
1556 /* ToDS FromDS Addr1 Addr2 Addr3 Addr4
1557 0 0 DA SA BSSID N/A (ad-hoc)
1558 0 1 DA BSSID SA N/A
1559 1 0 BSSID SA DA N/A
1560 1 1 RA TA DA SA (wireless bridge) */
1561
1562 uint8_t *rxMAC = macAddr1;
1563 uint8_t *txMAC = macAddr2;
1564 uint8_t *srcMAC = NULL;
1565 uint8_t *dstMAC = NULL;
1566 SFStr buf;
1567
1568 if(toDS) {
1569 dstMAC = macAddr3;
1570 if(fromDS) {
1571 srcMAC = ptr; /* macAddr4. 1,1 => (wireless bridge) */
1572 ptr += 6;
1573 }
1574 else srcMAC = macAddr2; /* 1,0 */
1575 }
1576 else {
1577 dstMAC = macAddr1;
1578 if(fromDS) srcMAC = macAddr3; /* 0,1 */
1579 else srcMAC = macAddr2; /* 0,0 */
1580 }
1581
1582 if(srcMAC) {
1583 sf_logf(sample, "srcMAC", printMAC(srcMAC, &buf));
1584 memcpy(sample->s.eth_src, srcMAC, 6);
1585 }
1586 if(dstMAC) {
1587 sf_logf(sample, "dstMAC", printMAC(dstMAC, &buf));
1588 memcpy(sample->s.eth_dst, srcMAC, 6);
1589 }
1590 if(txMAC) sf_logf(sample, "txMAC", printMAC(txMAC, &buf));
1591 if(rxMAC) sf_logf(sample, "rxMAC", printMAC(rxMAC, &buf));
1592 }
1593 }
1594 }
1595
1596 /*_________________---------------------------__________________
1597 _________________ decodeIPLayer4 __________________
1598 -----------------___________________________------------------
1599 */
1600
decodeIPLayer4(SFSample * sample,uint8_t * ptr)1601 static void decodeIPLayer4(SFSample *sample, uint8_t *ptr) {
1602 uint8_t *end = sample->s.header + sample->s.headerLen;
1603 if(ptr > (end - 8)) {
1604 /* not enough header bytes left */
1605 return;
1606 }
1607 switch(sample->s.dcd_ipProtocol) {
1608 case 1: /* ICMP */
1609 {
1610 struct myicmphdr icmp;
1611 memcpy(&icmp, ptr, sizeof(icmp));
1612 sf_logf_U32(sample, "ICMPType", icmp.type);
1613 sf_logf_U32(sample, "ICMPCode", icmp.code);
1614 sample->s.dcd_sport = icmp.type;
1615 sample->s.dcd_dport = icmp.code;
1616 sample->s.offsetToPayload = ptr + sizeof(icmp) - sample->s.header;
1617 }
1618 break;
1619 case 6: /* TCP */
1620 {
1621 struct mytcphdr tcp;
1622 int headerBytes;
1623 memcpy(&tcp, ptr, sizeof(tcp));
1624 sample->s.dcd_sport = ntohs(tcp.th_sport);
1625 sample->s.dcd_dport = ntohs(tcp.th_dport);
1626 sample->s.dcd_tcpFlags = tcp.th_flags;
1627 sf_logf_U32(sample, "TCPSrcPort", sample->s.dcd_sport);
1628 sf_logf_U32(sample, "TCPDstPort", sample->s.dcd_dport);
1629 sf_logf_U32(sample, "TCPFlags", sample->s.dcd_tcpFlags);
1630 headerBytes = (tcp.th_off_and_unused >> 4) * 4;
1631 ptr += headerBytes;
1632 sample->s.offsetToPayload = ptr - sample->s.header;
1633 }
1634 break;
1635 case 17: /* UDP */
1636 {
1637 struct myudphdr udp;
1638 memcpy(&udp, ptr, sizeof(udp));
1639 sample->s.dcd_sport = ntohs(udp.uh_sport);
1640 sample->s.dcd_dport = ntohs(udp.uh_dport);
1641 sample->s.udp_pduLen = ntohs(udp.uh_ulen);
1642 sf_logf_U32(sample, "UDPSrcPort", sample->s.dcd_sport);
1643 sf_logf_U32(sample, "UDPDstPort", sample->s.dcd_dport);
1644 sf_logf_U32(sample, "UDPBytes", sample->s.udp_pduLen);
1645 sample->s.offsetToPayload = ptr + sizeof(udp) - sample->s.header;
1646 }
1647 break;
1648 default: /* some other protcol */
1649 sample->s.offsetToPayload = ptr - sample->s.header;
1650 break;
1651 }
1652 }
1653
1654 /*_________________---------------------------__________________
1655 _________________ decodeIPV4 __________________
1656 -----------------___________________________------------------
1657 */
1658
decodeIPV4(SFSample * sample)1659 static void decodeIPV4(SFSample *sample)
1660 {
1661 if(sample->s.gotIPV4) {
1662 SFStr buf;
1663 uint8_t *end = sample->s.header + sample->s.headerLen;
1664 uint8_t *start = sample->s.header + sample->s.offsetToIPV4;
1665 uint8_t *ptr = start;
1666 if((end - ptr) < sizeof(struct myiphdr)) return;
1667
1668 /* Create a local copy of the IP header (cannot overlay structure in case it is not quad-aligned...some
1669 platforms would core-dump if we tried that). It's OK coz this probably performs just as well anyway. */
1670 struct myiphdr ip;
1671 memcpy(&ip, ptr, sizeof(ip));
1672 /* Value copy all ip elements into sample */
1673 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V4;
1674 sample->s.ipsrc.address.ip_v4.addr = ip.saddr;
1675 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V4;
1676 sample->s.ipdst.address.ip_v4.addr = ip.daddr;
1677 sample->s.dcd_ipProtocol = ip.protocol;
1678 sample->s.dcd_ipTos = ip.tos;
1679 sample->s.dcd_ipTTL = ip.ttl;
1680 sf_logf_U32(sample, "ip.tot_len", ntohs(ip.tot_len));
1681 /* Log out the decoded IP fields */
1682 sf_logf(sample, "srcIP", printAddress(&sample->s.ipsrc, &buf));
1683 sf_logf(sample, "dstIP", printAddress(&sample->s.ipdst, &buf));
1684 sf_logf_U32(sample, "IPProtocol", sample->s.dcd_ipProtocol);
1685 sf_logf_U32(sample, "IPTOS", sample->s.dcd_ipTos);
1686 sf_logf_U32(sample, "IPTTL", sample->s.dcd_ipTTL);
1687 sf_logf_U32(sample, "IPID", ip.id);
1688 /* check for fragments */
1689 sample->s.ip_fragmentOffset = ntohs(ip.frag_off) & 0x1FFF;
1690 if(sample->s.ip_fragmentOffset > 0) {
1691 sf_logf_U32(sample, "IPFragmentOffset", sample->s.ip_fragmentOffset);
1692 }
1693 else {
1694 /* advance the pointer to the next protocol layer */
1695 /* ip headerLen is expressed as a number of quads */
1696 uint32_t headerBytes = (ip.version_and_headerLen & 0x0f) * 4;
1697 if((end - ptr) < headerBytes) return;
1698 ptr += headerBytes;
1699 decodeIPLayer4(sample, ptr);
1700 }
1701 }
1702 }
1703
1704 /*_________________---------------------------__________________
1705 _________________ decodeIPV6 __________________
1706 -----------------___________________________------------------
1707 */
1708
decodeIPV6(SFSample * sample)1709 static void decodeIPV6(SFSample *sample)
1710 {
1711 uint16_t payloadLen;
1712 uint32_t label;
1713 uint32_t nextHeader;
1714 uint32_t tos;
1715
1716 uint8_t *end = sample->s.header + sample->s.headerLen;
1717 uint8_t *start = sample->s.header + sample->s.offsetToIPV6;
1718 uint8_t *ptr = start;
1719 if((end - ptr) < sizeof(struct myip6hdr)) return;
1720
1721 if(sample->s.gotIPV6) {
1722
1723 /* check the version */
1724 {
1725 int ipVersion = (*ptr >> 4);
1726 if(ipVersion != 6) {
1727 sf_log(sample,"header decode error: unexpected IP version: %d\n", ipVersion);
1728 return;
1729 }
1730 }
1731
1732 /* get the tos (priority) */
1733 sample->s.dcd_ipTos = ((ptr[0] & 15) << 4) + (ptr[1] >> 4);
1734 ptr++;
1735 sf_logf_U32(sample, "IPTOS", sample->s.dcd_ipTos);
1736 /* 20-bit label */
1737 label = ((ptr[0] & 15) << 16) + (ptr[1] << 8) + ptr[2];
1738 ptr += 3;
1739 sf_logf_U32_formatted(sample, NULL, "IP6_label", "0x%1x", label);
1740 /* payload */
1741 payloadLen = (ptr[0] << 8) + ptr[1];
1742 ptr += 2;
1743 /* if payload is zero, that implies a jumbo payload */
1744 if(payloadLen == 0) sf_logf(sample, "IPV6_payloadLen", "<jumbo>");
1745 else sf_logf_U32(sample, "IPV6_payloadLen", payloadLen);
1746
1747 /* next header */
1748 nextHeader = *ptr++;
1749
1750 /* TTL */
1751 sample->s.dcd_ipTTL = *ptr++;
1752 sf_logf_U32(sample, "IPTTL", sample->s.dcd_ipTTL);
1753
1754 {/* src and dst address */
1755 SFStr buf;
1756 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V6;
1757 memcpy(&sample->s.ipsrc.address, ptr, 16);
1758 ptr +=16;
1759 sf_logf(sample, "srcIP6", printAddress(&sample->s.ipsrc, &buf));
1760 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V6;
1761 memcpy(&sample->s.ipdst.address, ptr, 16);
1762 ptr +=16;
1763 sf_logf(sample, "dstIP6", printAddress(&sample->s.ipdst, &buf));
1764 }
1765
1766 /* skip over some common header extensions...
1767 http://searchnetworking.techtarget.com/originalContent/0,289142,sid7_gci870277,00.html */
1768 while(nextHeader == 0 || /* hop */
1769 nextHeader == 43 || /* routing */
1770 nextHeader == 44 || /* fragment */
1771 /* nextHeader == 50 => encryption - don't bother coz we'll not be able to read any further */
1772 nextHeader == 51 || /* auth */
1773 nextHeader == 60) { /* destination options */
1774 uint32_t optionLen;
1775 sf_logf_U32(sample, "IP6HeaderExtension", nextHeader);
1776 nextHeader = ptr[0];
1777 optionLen = 8 * (ptr[1] + 1); /* second byte gives option len in 8-byte chunks, not counting first 8 */
1778 ptr += optionLen;
1779 if(ptr > end) return; /* ran off the end of the header */
1780 }
1781
1782 /* now that we have eliminated the extension headers, nextHeader should have what we want to
1783 remember as the ip protocol... */
1784 sample->s.dcd_ipProtocol = nextHeader;
1785 sf_logf_U32(sample, "IPProtocol", sample->s.dcd_ipProtocol);
1786 decodeIPLayer4(sample, ptr);
1787 }
1788 }
1789
1790 /*_________________---------------------------__________________
1791 _________________ readPcapHeader __________________
1792 -----------------___________________________------------------
1793 */
1794
1795 #define TCPDUMP_MAGIC 0xa1b2c3d4 /* from libpcap-0.5: savefile.c */
1796 #define DLT_EN10MB 1 /* from libpcap-0.5: net/bpf.h */
1797 #define PCAP_VERSION_MAJOR 2 /* from libpcap-0.5: pcap.h */
1798 #define PCAP_VERSION_MINOR 4 /* from libpcap-0.5: pcap.h */
1799
readPcapHeader()1800 static void readPcapHeader() {
1801 struct pcap_file_header hdr;
1802 if(fread(&hdr, sizeof(hdr), 1, sfConfig.readPcapFile) != 1) {
1803 fprintf(ERROUT, "unable to read pcap header from %s : %s\n", sfConfig.readPcapFileName, strerror(errno));
1804 exit(-30);
1805 }
1806 if(hdr.magic != TCPDUMP_MAGIC) {
1807 if(hdr.magic == MyByteSwap32(TCPDUMP_MAGIC)) {
1808 sfConfig.pcapSwap = YES;
1809 hdr.version_major = MyByteSwap16(hdr.version_major);
1810 hdr.version_minor = MyByteSwap16(hdr.version_minor);
1811 hdr.thiszone = MyByteSwap32(hdr.thiszone);
1812 hdr.sigfigs = MyByteSwap32(hdr.sigfigs);
1813 hdr.snaplen = MyByteSwap32(hdr.snaplen);
1814 hdr.linktype = MyByteSwap32(hdr.linktype);
1815 }
1816 else {
1817 fprintf(ERROUT, "%s not recognized as a tcpdump file\n(magic number = %08x instead of %08x)\n",
1818 sfConfig.readPcapFileName,
1819 hdr.magic,
1820 TCPDUMP_MAGIC);
1821 exit(-31);
1822 }
1823 }
1824 fprintf(ERROUT, "pcap version=%d.%d snaplen=%d linktype=%d \n",
1825 hdr.version_major,
1826 hdr.version_minor,
1827 hdr.snaplen,
1828 hdr.linktype);
1829 sfConfig.readPcapHdr = hdr;
1830 }
1831
1832 /*_________________---------------------------__________________
1833 _________________ writePcapHeader __________________
1834 -----------------___________________________------------------
1835 */
1836
1837 #define DLT_EN10MB 1 /* from libpcap-0.5: net/bpf.h */
1838 #define DLT_LINUX_SLL 113 /* Linux "cooked" encapsulation */
1839 #define PCAP_VERSION_MAJOR 2 /* from libpcap-0.5: pcap.h */
1840 #define PCAP_VERSION_MINOR 4 /* from libpcap-0.5: pcap.h */
1841
writePcapHeader()1842 static void writePcapHeader() {
1843 struct pcap_file_header hdr;
1844 memset(&hdr, 0, sizeof(hdr));
1845 hdr.magic = TCPDUMP_MAGIC;
1846 hdr.version_major = PCAP_VERSION_MAJOR;
1847 hdr.version_minor = PCAP_VERSION_MINOR;
1848 hdr.thiszone = 0;
1849 hdr.snaplen = SA_MAX_PCAP_PKT;
1850 hdr.sigfigs = 0;
1851 hdr.linktype = DLT_EN10MB;
1852 if (fwrite((char *)&hdr, sizeof(hdr), 1, stdout) != 1) {
1853 fprintf(ERROUT, "failed to write tcpdump header: %s\n", strerror(errno));
1854 exit(-1);
1855 }
1856 fflush(stdout);
1857 }
1858
1859 /*_________________---------------------------__________________
1860 _________________ writePcapPacket __________________
1861 -----------------___________________________------------------
1862 */
1863
writePcapPacket(SFSample * sample)1864 static void writePcapPacket(SFSample *sample) {
1865 char buf[SA_MAX_PCAP_PKT];
1866 int bytes = 0;
1867 struct pcap_pkthdr hdr;
1868 hdr.ts_sec = sample->pcapTimestamp ?: sample->readTimestamp;
1869 hdr.ts_usec = 0;
1870 hdr.len = sample->s.sampledPacketSize;
1871 hdr.caplen = sample->s.headerLen;
1872 if(sfConfig.removeContent && sample->s.offsetToPayload) {
1873 /* shorten the captured header to ensure no payload bytes are included */
1874 hdr.caplen = sample->s.offsetToPayload;
1875 }
1876
1877 /* prepare the whole thing in a buffer first, in case we are piping the output
1878 to another process and the reader expects it all to appear at once... */
1879 memcpy(buf, &hdr, sizeof(hdr));
1880 bytes = sizeof(hdr);
1881 memcpy(buf+bytes, sample->s.header, hdr.caplen);
1882 bytes += hdr.caplen;
1883
1884 if(fwrite(buf, bytes, 1, stdout) != 1) {
1885 fprintf(ERROUT, "writePcapPacket: packet write failed: %s\n", strerror(errno));
1886 exit(-3);
1887 }
1888 fflush(stdout);
1889 }
1890
1891 #ifdef SPOOFSOURCE
1892
1893 /*_________________---------------------------__________________
1894 _________________ in_checksum __________________
1895 -----------------___________________________------------------
1896 */
in_checksum(uint16_t * addr,int len)1897 static uint16_t in_checksum(uint16_t *addr, int len)
1898 {
1899 int nleft = len;
1900 uint16_t *w = addr;
1901 uint16_t answer;
1902 int sum = 0;
1903
1904 while (nleft > 1) {
1905 sum += *w++;
1906 nleft -= 2;
1907 }
1908
1909 if (nleft == 1) sum += *(uint8_t *)w;
1910
1911 sum = (sum >> 16) + (sum & 0xffff);
1912 sum += (sum >> 16);
1913 answer = ~sum;
1914 return (answer);
1915 }
1916
1917 /*_________________---------------------------__________________
1918 _________________ openNetFlowSocket_spoof __________________
1919 -----------------___________________________------------------
1920 */
1921
openNetFlowSocket_spoof()1922 static void openNetFlowSocket_spoof()
1923 {
1924 int on;
1925
1926 if((sfConfig.netFlowOutputSocket = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
1927 fprintf(ERROUT, "netflow output raw socket open failed\n");
1928 exit(-11);
1929 }
1930 on = 1;
1931 if(setsockopt(sfConfig.netFlowOutputSocket, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
1932 fprintf(ERROUT, "setsockopt( IP_HDRINCL ) failed\n");
1933 exit(-13);
1934 }
1935 on = 1;
1936 if(setsockopt(sfConfig.netFlowOutputSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) {
1937 fprintf(ERROUT, "setsockopt( SO_REUSEADDR ) failed\n");
1938 exit(-14);
1939 }
1940
1941 memset(&sfConfig.sendPkt, 0, sizeof(sfConfig.sendPkt));
1942 sfConfig.sendPkt.ip.version_and_headerLen = 0x45;
1943 sfConfig.sendPkt.ip.protocol = IPPROTO_UDP;
1944 sfConfig.sendPkt.ip.ttl = 64; /* IPDEFTTL */
1945 sfConfig.ipid = 12000; /* start counting from 12000 (just an arbitrary number) */
1946 /* sfConfig.ip->frag_off = htons(0x4000); */ /* don't fragment */
1947 /* can't set the source address yet, but the dest address is known */
1948 sfConfig.sendPkt.ip.daddr = sfConfig.netFlowOutputIP.address.ip_v4.addr;
1949 /* can't do the ip_len and checksum until we know the size of the packet */
1950 sfConfig.sendPkt.udp.uh_dport = htons(sfConfig.netFlowOutputPort);
1951 /* might as well set the source port to be the same */
1952 sfConfig.sendPkt.udp.uh_sport = htons(sfConfig.netFlowOutputPort);
1953 /* can't do the udp_len or udp_checksum until we know the size of the packet */
1954 }
1955
1956
1957
1958 /*_________________---------------------------__________________
1959 _________________ sendNetFlowDatagram_spoof __________________
1960 -----------------___________________________------------------
1961 */
1962
sendNetFlowDatagram_spoof(SFSample * sample,NFFlowPkt * pkt)1963 static void sendNetFlowDatagram_spoof(SFSample *sample, NFFlowPkt *pkt)
1964 {
1965 /* Grab the netflow version from packet */
1966 uint16_t version = ntohs(*((uint16_t *)pkt));
1967 uint16_t packetLen = 0;
1968
1969 /* Copy data into send packet */
1970 switch(version) {
1971 case 5:
1972 {
1973 packetLen = sizeof(NFFlowPkt5) + sizeof(struct myiphdr) + sizeof(struct myudphdr);
1974 memcpy(sfConfig.sendPkt.data, (char *)pkt, sizeof(NFFlowPkt5));
1975 }
1976 break;
1977 case 9:
1978 {
1979 packetLen = sizeof(NFFlowPkt9) + sizeof(struct myiphdr) + sizeof(struct myudphdr);
1980 memcpy(sfConfig.sendPkt.data, (char *)pkt, sizeof(NFFlowPkt9));
1981 }
1982 break;
1983 default:
1984 /* unsupported version */
1985 return;
1986 }
1987
1988 /* increment the ip-id */
1989 sfConfig.sendPkt.ip.id = htons(++sfConfig.ipid);
1990 /* set the length fields in the ip and udp headers */
1991 sfConfig.sendPkt.ip.tot_len = htons(packetLen);
1992 sfConfig.sendPkt.udp.uh_ulen = htons(packetLen - sizeof(struct myiphdr));
1993 /* set the source address to the source address of the input event */
1994 sfConfig.sendPkt.ip.saddr = sample->agent_addr.address.ip_v4.addr;
1995 /* IP header checksum */
1996 sfConfig.sendPkt.ip.check = in_checksum((uint16_t *)&sfConfig.sendPkt.ip, sizeof(struct myiphdr));
1997 if (sfConfig.sendPkt.ip.check == 0) sfConfig.sendPkt.ip.check = 0xffff;
1998 /* UDP Checksum
1999 copy out those parts of the IP header that are supposed to be in the UDP checksum,
2000 and blat them in front of the udp header (after saving what was there before).
2001 Then compute the udp checksum. Then patch the saved data back again. */
2002 {
2003 char *ptr;
2004 struct udpmagichdr {
2005 uint32_t src;
2006 uint32_t dst;
2007 uint8_t zero;
2008 uint8_t proto;
2009 uint16_t len;
2010 } h, saved;
2011
2012 h.src = sfConfig.sendPkt.ip.saddr;
2013 h.dst = sfConfig.sendPkt.ip.daddr;
2014 h.zero = 0;
2015 h.proto = IPPROTO_UDP;
2016 h.len = sfConfig.sendPkt.udp.uh_ulen;
2017 /* set the pointer to 12 bytes before the start of the udp header */
2018 ptr = (char *)&sfConfig.sendPkt.udp;
2019 ptr -= sizeof(struct udpmagichdr);
2020 /* save what's there */
2021 memcpy(&saved, ptr, sizeof(struct udpmagichdr));
2022 /* blat in the replacement bytes */
2023 memcpy(ptr, &h, sizeof(struct udpmagichdr));
2024 /* compute the checksum */
2025 sfConfig.sendPkt.udp.uh_sum = 0;
2026 sfConfig.sendPkt.udp.uh_sum = in_checksum((uint16_t *)ptr,
2027 ntohs(sfConfig.sendPkt.udp.uh_ulen) + sizeof(struct udpmagichdr));
2028 if (sfConfig.sendPkt.udp.uh_sum == 0) sfConfig.sendPkt.udp.uh_sum = 0xffff;
2029 /* copy the save bytes back again */
2030 memcpy(ptr, &saved, sizeof(struct udpmagichdr));
2031
2032 { /* now send the packet */
2033 int bytesSent;
2034 struct sockaddr dest;
2035 struct sockaddr_in *to = (struct sockaddr_in *)&dest;
2036 memset(&dest, 0, sizeof(dest));
2037 to->sin_family = AF_INET;
2038 to->sin_addr.s_addr = sfConfig.sendPkt.ip.daddr;
2039 if((bytesSent = sendto(sfConfig.netFlowOutputSocket,
2040 &sfConfig.sendPkt,
2041 packetLen,
2042 0,
2043 &dest,
2044 sizeof(dest))) != packetLen) {
2045 fprintf(ERROUT, "sendto returned %d (expected %d): %s\n", bytesSent, packetLen, strerror(errno));
2046 }
2047 }
2048 }
2049 }
2050
2051 #endif /* SPOOFSOURCE */
2052
2053 /*_________________---------------------------__________________
2054 _________________ openNetFlowSocket __________________
2055 -----------------___________________________------------------
2056 */
2057
openNetFlowSocket()2058 static void openNetFlowSocket()
2059 {
2060 int family = (sfConfig.netFlowOutputIP.type == SFLADDRESSTYPE_IP_V6) ? AF_INET6 : AF_INET;
2061
2062 #ifdef SPOOFSOURCE
2063 if(sfConfig.spoofSource) {
2064 if(family == AF_INET6) {
2065 fprintf(ERROUT, "IPv6 source spoofing not supported\n");
2066 sfConfig.spoofSource = NO;
2067 }
2068 else {
2069 openNetFlowSocket_spoof();
2070 return;
2071 }
2072 }
2073 #endif
2074
2075 /* set the port (we could have getaddrinfo() do this for us too) */
2076 if(family == AF_INET6)
2077 sfConfig.netFlowOutputSA.sa6.sin6_port = ntohs(sfConfig.netFlowOutputPort);
2078 else
2079 sfConfig.netFlowOutputSA.sa4.sin_port = ntohs(sfConfig.netFlowOutputPort);
2080
2081 /* open the socket */
2082 if((sfConfig.netFlowOutputSocket = socket(family, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
2083 fprintf(ERROUT, "netflow output socket open failed : %s\n", strerror(errno));
2084 exit(-4);
2085 }
2086
2087 /* connect to it so we can just use send() or write() to send on it */
2088 if(connect(sfConfig.netFlowOutputSocket,
2089 (struct sockaddr *)&sfConfig.netFlowOutputSA,
2090 family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)) != 0) {
2091 fprintf(ERROUT, "connect() to netflow output socket failed: %s\n",
2092 strerror(errno));
2093 exit(-5);
2094 }
2095 }
2096
2097 /*_________________---------------------------__________________
2098 _________________ sendNetFlowV5Datagram __________________
2099 -----------------___________________________------------------
2100 */
2101
2102 static int NFFlowSequenceNo = 0;
2103
sendNetFlowV5Datagram(SFSample * sample)2104 static void sendNetFlowV5Datagram(SFSample *sample)
2105 {
2106 NFFlowPkt5 pkt;
2107 uint32_t now = (uint32_t)time(NULL);
2108 uint32_t bytes;
2109 /* ignore fragments */
2110 if(sample->s.ip_fragmentOffset > 0) return;
2111 /* count the bytes from the start of IP header, with the exception that
2112 for udp packets we use the udp_pduLen. This is because the udp_pduLen
2113 can be up tp 65535 bytes, which causes fragmentation at the IP layer.
2114 Since the sampled fragments are discarded, we have to use this field
2115 to get the total bytes estimates right. */
2116 if(sample->s.udp_pduLen > 0) bytes = sample->s.udp_pduLen;
2117 else bytes = sample->s.sampledPacketSize - sample->s.stripped - sample->s.offsetToIPV4;
2118
2119 memset(&pkt, 0, sizeof(pkt));
2120 pkt.hdr.version = htons(5);
2121 pkt.hdr.count = htons(1);
2122 pkt.hdr.sysUpTime = htonl(now % (3600 * 24)) * 1000; /* pretend we started at midnight (milliseconds) */
2123 pkt.hdr.unixSeconds = htonl(now);
2124 pkt.hdr.unixNanoSeconds = 0; /* no need to be more accurate than 1 second */
2125 pkt.hdr.flowSequence = htonl(NFFlowSequenceNo++);
2126
2127 pkt.flow.srcIP = sample->s.ipsrc.address.ip_v4.addr;
2128 pkt.flow.dstIP = sample->s.ipdst.address.ip_v4.addr;
2129 pkt.flow.nextHop = sample->s.nextHop.address.ip_v4.addr;
2130 pkt.flow.if_in = htons((uint16_t)sample->s.inputPort);
2131 pkt.flow.if_out= htons((uint16_t)sample->s.outputPort);
2132
2133 if(!sfConfig.disableNetFlowScale) {
2134 pkt.flow.frames = htonl(sample->s.meanSkipCount);
2135 pkt.flow.bytes = htonl(sample->s.meanSkipCount * bytes);
2136 }
2137 else {
2138 /* set the sampling_interval header field too (used to be a 16-bit reserved field) */
2139 uint16_t samp_ival = (uint16_t)sample->s.meanSkipCount;
2140 pkt.hdr.sampling_interval = htons(samp_ival | 0x4000);
2141 pkt.flow.frames = htonl(1);
2142 pkt.flow.bytes = htonl(bytes);
2143 }
2144
2145 pkt.flow.firstTime = pkt.hdr.sysUpTime; /* set the start and end time to be now (in milliseconds since last boot) */
2146 pkt.flow.lastTime = pkt.hdr.sysUpTime;
2147 pkt.flow.srcPort = htons((uint16_t)sample->s.dcd_sport);
2148 pkt.flow.dstPort = htons((uint16_t)sample->s.dcd_dport);
2149 pkt.flow.tcpFlags = sample->s.dcd_tcpFlags;
2150 pkt.flow.ipProto = sample->s.dcd_ipProtocol;
2151 pkt.flow.ipTos = sample->s.dcd_ipTos;
2152
2153 if(sfConfig.netFlowPeerAS) {
2154 pkt.flow.srcAS = htons((uint16_t)sample->s.src_peer_as);
2155 pkt.flow.dstAS = htons((uint16_t)sample->s.dst_peer_as);
2156 }
2157 else {
2158 pkt.flow.srcAS = htons((uint16_t)sample->s.src_as);
2159 pkt.flow.dstAS = htons((uint16_t)sample->s.dst_as);
2160 }
2161
2162 pkt.flow.srcMask = (uint8_t)sample->s.srcMask;
2163 pkt.flow.dstMask = (uint8_t)sample->s.dstMask;
2164
2165 #ifdef SPOOFSOURCE
2166 if(sfConfig.spoofSource) {
2167 sendNetFlowDatagram_spoof(sample, (NFFlowPkt *)&pkt);
2168 return;
2169 }
2170 #endif /* SPOOFSOURCE */
2171
2172 /* send non-blocking */
2173 send(sfConfig.netFlowOutputSocket, (char *)&pkt, sizeof(pkt), 0);
2174
2175 }
2176
2177 /*_________________---------------------------__________________
2178 _________________ sendNetFlowV9Datagram __________________
2179 -----------------___________________________------------------
2180 */
2181
sendNetFlowV9Datagram(SFSample * sample)2182 static void sendNetFlowV9Datagram(SFSample *sample)
2183 {
2184 NFFlowPkt9 pkt;
2185
2186 uint32_t now = (uint32_t)time(NULL);
2187 uint32_t bytes;
2188 uint16_t i = 0;
2189 const size_t fieldCount = sizeof(pkt.tmpl.field) / sizeof(pkt.tmpl.field[0]);
2190 /* ignore fragments */
2191 if(sample->s.ip_fragmentOffset > 0) return;
2192 /* count the bytes from the start of IP header, with the exception that
2193 for udp packets we use the udp_pduLen. This is because the udp_pduLen
2194 can be up tp 65535 bytes, which causes fragmentation at the IP layer.
2195 Since the sampled fragments are discarded, we have to use this field
2196 to get the total bytes estimates right. */
2197 if(sample->s.udp_pduLen > 0) bytes = sample->s.udp_pduLen;
2198 else bytes = sample->s.sampledPacketSize - sample->s.stripped - sample->s.offsetToIPV4;
2199
2200 memset(&pkt, 0, sizeof(pkt));
2201
2202 /* Fill packet header */
2203 pkt.hdr.version = htons(9);
2204 pkt.hdr.count = htons(2); /* one template + one flow record */
2205 pkt.hdr.sysUpTime = htonl(now % (3600 * 24)) * 1000; /* pretend we started at midnight (milliseconds) */
2206 pkt.hdr.unixSeconds = htonl(now);
2207 pkt.hdr.flowSequence = htonl(NFFlowSequenceNo++);
2208
2209 /* Fill template flowset */
2210 pkt.tmpl.setId = 0;
2211 pkt.tmpl.length = htons(sizeof(pkt.tmpl));
2212 pkt.tmpl.templateId = htons(256);
2213 pkt.tmpl.fieldCount = htons(fieldCount);
2214 for(i=0; i<fieldCount; i++) {
2215 pkt.tmpl.field[i].id = htons(nfField9[i].id);
2216 pkt.tmpl.field[i].sz = htons(nfField9[i].sz);
2217 }
2218
2219 /* Fill data flowset */
2220 pkt.data.templateId = htons(256);
2221 pkt.data.length = htons(sizeof(pkt.data));
2222 pkt.data.flow.srcIP = sample->s.ipsrc.address.ip_v4.addr;
2223 pkt.data.flow.dstIP = sample->s.ipdst.address.ip_v4.addr;
2224 pkt.data.flow.nextHop = sample->s.nextHop.address.ip_v4.addr;
2225 /* We are no longer truncating these interface fields as with NetFlow v5 */
2226 pkt.data.flow.if_in = htonl(sample->s.inputPort);
2227 pkt.data.flow.if_out= htonl(sample->s.outputPort);
2228
2229 if(!sfConfig.disableNetFlowScale) {
2230 pkt.data.flow.packets = htonl(sample->s.meanSkipCount);
2231 pkt.data.flow.bytes = htonl(sample->s.meanSkipCount * bytes);
2232 }
2233 else {
2234 /* set the sampling_interval header field */
2235 pkt.data.flow.samplingInterval = htonl(sample->s.meanSkipCount);
2236 pkt.data.flow.packets = htonl(1);
2237 pkt.data.flow.bytes = htonl(bytes);
2238 }
2239
2240 /* set the start and end time to be now (in milliseconds since last boot) */
2241 pkt.data.flow.firstTime = pkt.hdr.sysUpTime;
2242 pkt.data.flow.lastTime = pkt.hdr.sysUpTime;
2243 pkt.data.flow.srcPort = htons((uint16_t)sample->s.dcd_sport);
2244 pkt.data.flow.dstPort = htons((uint16_t)sample->s.dcd_dport);
2245 pkt.data.flow.tcpFlags = sample->s.dcd_tcpFlags;
2246 pkt.data.flow.ipProto = sample->s.dcd_ipProtocol;
2247 pkt.data.flow.ipTos = sample->s.dcd_ipTos;
2248
2249 if(sfConfig.netFlowPeerAS) {
2250 pkt.data.flow.srcAS = htonl(sample->s.src_peer_as);
2251 pkt.data.flow.dstAS = htonl(sample->s.dst_peer_as);
2252 }
2253 else {
2254 pkt.data.flow.srcAS = htonl(sample->s.src_as);
2255 pkt.data.flow.dstAS = htonl(sample->s.dst_as);
2256 }
2257
2258 pkt.data.flow.srcMask = (uint8_t)sample->s.srcMask;
2259 pkt.data.flow.dstMask = (uint8_t)sample->s.dstMask;
2260
2261 #ifdef SPOOFSOURCE
2262 if(sfConfig.spoofSource) {
2263 sendNetFlowDatagram_spoof(sample, (NFFlowPkt *)&pkt);
2264 return;
2265 }
2266 #endif /* SPOOFSOURCE */
2267
2268 /* send non-blocking */
2269 send(sfConfig.netFlowOutputSocket, (char *)&pkt, sizeof(pkt), 0);
2270 }
2271
2272 /*_________________---------------------------__________________
2273 _________________ read data fns __________________
2274 -----------------___________________________------------------
2275 */
2276
getData32_nobswap(SFSample * sample)2277 static uint32_t getData32_nobswap(SFSample *sample) {
2278 uint32_t ans = *(sample->datap)++;
2279 /* make sure we didn't run off the end of the datagram. Thanks to
2280 Sven Eschenberg for spotting a bug/overrun-vulnerabilty that was here before. */
2281 if((uint8_t *)sample->datap > sample->endp) {
2282 SFABORT(sample, SF_ABORT_EOS);
2283 }
2284 return ans;
2285 }
2286
getData32(SFSample * sample)2287 static uint32_t getData32(SFSample *sample) {
2288 return ntohl(getData32_nobswap(sample));
2289 }
2290
getFloat(SFSample * sample)2291 static float getFloat(SFSample *sample) {
2292 float fl;
2293 uint32_t reg = getData32(sample);
2294 memcpy(&fl, ®, 4);
2295 return fl;
2296 }
2297
getData64(SFSample * sample)2298 static uint64_t getData64(SFSample *sample) {
2299 uint64_t tmpLo, tmpHi;
2300 tmpHi = getData32(sample);
2301 tmpLo = getData32(sample);
2302 return (tmpHi << 32) + tmpLo;
2303 }
2304
getDouble(SFSample * sample)2305 static double getDouble(SFSample *sample) {
2306 double dbl;
2307 uint64_t reg = getData64(sample);
2308 memcpy(&dbl, ®, 8);
2309 return dbl;
2310 }
2311
skipBytes(SFSample * sample,uint32_t skip)2312 static void skipBytes(SFSample *sample, uint32_t skip) {
2313 int quads = (skip + 3) / 4;
2314 sample->datap += quads;
2315 if(skip > sample->rawSampleLen || (uint8_t *)sample->datap > sample->endp) {
2316 SFABORT(sample, SF_ABORT_EOS);
2317 }
2318 }
2319
sf_log_next32(SFSample * sample,char * fieldName)2320 static uint32_t sf_log_next32(SFSample *sample, char *fieldName) {
2321 uint32_t val = getData32(sample);
2322 sf_logf_U32(sample, fieldName, val);
2323 return val;
2324 }
2325
sf_log_next64(SFSample * sample,char * fieldName)2326 static uint64_t sf_log_next64(SFSample *sample, char *fieldName) {
2327 uint64_t val64 = getData64(sample);
2328 sf_logf_U64(sample, fieldName, val64);
2329 return val64;
2330 }
2331
sf_log_percentage(SFSample * sample,char * fieldName)2332 void sf_log_percentage(SFSample *sample, char *fieldName)
2333 {
2334 char buf[32];
2335 uint32_t hundredths = getData32(sample);
2336 if(hundredths == (uint32_t)-1)
2337 sf_logf(sample, fieldName, "unknown");
2338 else {
2339 float percent = (float)hundredths / (float)100.0;
2340 sprintf(buf, "%.2f", percent);
2341 sf_logf(sample, fieldName, buf);
2342 }
2343 }
2344
sf_log_nextFloat(SFSample * sample,char * fieldName)2345 static float sf_log_nextFloat(SFSample *sample, char *fieldName) {
2346 char buf[32];
2347 float val = getFloat(sample);
2348 sprintf(buf, "%.3f", val);
2349 sf_logf(sample, fieldName, buf);
2350 return val;
2351 }
2352
sf_log_nextMAC(SFSample * sample,char * fieldName)2353 void sf_log_nextMAC(SFSample *sample, char *fieldName)
2354 {
2355 uint8_t *mac = (uint8_t *)sample->datap;
2356 skipBytes(sample, 6);
2357 SFStr macstr;
2358 SFStr_init(&macstr);
2359 SFStr_append_mac(&macstr, mac);
2360 sf_logf(sample, fieldName, SFStr_str(&macstr));
2361 }
2362
getString(SFSample * sample,char * buf,uint32_t bufLen)2363 static uint32_t getString(SFSample *sample, char *buf, uint32_t bufLen) {
2364 uint32_t len, read_len;
2365 len = getData32(sample);
2366 /* check the bytes are there first */
2367 uint32_t *dp = sample->datap;
2368 skipBytes(sample, len);
2369 /* truncate if too long */
2370 read_len = (len >= bufLen) ? (bufLen - 1) : len;
2371 memcpy(buf, dp, read_len);
2372 buf[read_len] = '\0'; /* null terminate */
2373 return len;
2374 }
2375
getAddress(SFSample * sample,SFLAddress * address)2376 static uint32_t getAddress(SFSample *sample, SFLAddress *address) {
2377 address->type = getData32(sample);
2378 switch(address->type) {
2379 case SFLADDRESSTYPE_IP_V4:
2380 address->address.ip_v4.addr = getData32_nobswap(sample);
2381 break;
2382 case SFLADDRESSTYPE_IP_V6:
2383 {
2384 /* make sure the data is there before we memcpy */
2385 uint32_t *dp = sample->datap;
2386 skipBytes(sample, 16);
2387 memcpy(&address->address.ip_v6.addr, dp, 16);
2388 }
2389 break;
2390 default:
2391 /* undefined address type - bail out */
2392 fprintf(ERROUT, "unknown address type = %d\n", address->type);
2393 SFABORT(sample, SF_ABORT_EOS);
2394 }
2395 return address->type;
2396 }
2397
skipTLVRecord(SFSample * sample,uint32_t tag,uint32_t len,char * description)2398 static void skipTLVRecord(SFSample *sample, uint32_t tag, uint32_t len, char *description) {
2399 SFStr buf;
2400 sf_log(sample,"skipping unknown %s: %s len=%d\n", description, printTag(tag, &buf), len);
2401 skipBytes(sample, len);
2402 }
2403
2404 /*_________________---------------------------__________________
2405 _________________ readExtendedSwitch __________________
2406 -----------------___________________________------------------
2407 */
2408
readExtendedSwitch(SFSample * sample)2409 static void readExtendedSwitch(SFSample *sample)
2410 {
2411 sf_logf(sample, "extendedType", "SWITCH");
2412 sample->s.in_vlan = getData32(sample);
2413 sample->s.in_priority = getData32(sample);
2414 sample->s.out_vlan = getData32(sample);
2415 sample->s.out_priority = getData32(sample);
2416
2417 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_SWITCH;
2418
2419 sf_logf_U32(sample, "in_vlan", sample->s.in_vlan);
2420 sf_logf_U32(sample, "in_priority", sample->s.in_priority);
2421 sf_logf_U32(sample, "out_vlan", sample->s.out_vlan);
2422 sf_logf_U32(sample, "out_priority", sample->s.out_priority);
2423 }
2424
2425 /*_________________---------------------------__________________
2426 _________________ readExtendedRouter __________________
2427 -----------------___________________________------------------
2428 */
2429
readExtendedRouter(SFSample * sample)2430 static void readExtendedRouter(SFSample *sample)
2431 {
2432 SFStr buf;
2433 sf_logf(sample, "extendedType", "ROUTER");
2434 getAddress(sample, &sample->s.nextHop);
2435 sample->s.srcMask = getData32(sample);
2436 sample->s.dstMask = getData32(sample);
2437
2438 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_ROUTER;
2439
2440 sf_logf(sample, "nextHop", printAddress(&sample->s.nextHop, &buf));
2441 sf_logf_U32(sample, "srcSubnetMask", sample->s.srcMask);
2442 sf_logf_U32(sample, "dstSubnetMask", sample->s.dstMask);
2443 }
2444
2445 /*_________________---------------------------__________________
2446 _________________ readExtendedGateway_v2 __________________
2447 -----------------___________________________------------------
2448 */
2449
readExtendedGateway_v2(SFSample * sample)2450 static void readExtendedGateway_v2(SFSample *sample)
2451 {
2452 sf_logf(sample, "extendedType", "GATEWAY");
2453
2454 sample->s.my_as = getData32(sample);
2455 sample->s.src_as = getData32(sample);
2456 sample->s.src_peer_as = getData32(sample);
2457
2458 /* clear dst_peer_as and dst_as to make sure we are not
2459 remembering values from a previous sample - (thanks Marc Lavine) */
2460 sample->s.dst_peer_as = 0;
2461 sample->s.dst_as = 0;
2462
2463 sample->s.dst_as_path_len = getData32(sample);
2464 /* just point at the dst_as_path array */
2465 if(sample->s.dst_as_path_len > 0) {
2466 sample->s.dst_as_path = sample->datap;
2467 /* and skip over it in the input */
2468 skipBytes(sample, sample->s.dst_as_path_len * 4);
2469 /* fill in the dst and dst_peer fields too */
2470 sample->s.dst_peer_as = ntohl(sample->s.dst_as_path[0]);
2471 sample->s.dst_as = ntohl(sample->s.dst_as_path[sample->s.dst_as_path_len - 1]);
2472 }
2473
2474 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY;
2475
2476 sf_logf_U32(sample, "my_as", sample->s.my_as);
2477 sf_logf_U32(sample, "src_as", sample->s.src_as);
2478 sf_logf_U32(sample, "src_peer_as", sample->s.src_peer_as);
2479 sf_logf_U32(sample, "dst_as", sample->s.dst_as);
2480 sf_logf_U32(sample, "dst_peer_as", sample->s.dst_peer_as);
2481 sf_logf_U32(sample, "dst_as_path_len", sample->s.dst_as_path_len);
2482 if(sample->s.dst_as_path_len > 0) {
2483 SFStr dst_as_path;
2484 SFStr_init(&dst_as_path);
2485 SFStr_append_array32(&dst_as_path, sample->s.dst_as_path, sample->s.dst_as_path_len, YES, '-');
2486 sf_logf(sample, "dst_as_path", SFStr_str(&dst_as_path));
2487 }
2488 }
2489
2490 /*_________________---------------------------__________________
2491 _________________ readExtendedGateway __________________
2492 -----------------___________________________------------------
2493 */
2494
readExtendedGateway(SFSample * sample)2495 static void readExtendedGateway(SFSample *sample)
2496 {
2497 uint32_t segments;
2498 uint32_t seg;
2499 SFStr buf;
2500
2501 sf_logf(sample, "extendedType", "GATEWAY");
2502
2503 if(sample->datagramVersion >= 5) {
2504 getAddress(sample, &sample->s.bgp_nextHop);
2505 sf_logf(sample, "bgp_nexthop", printAddress(&sample->s.bgp_nextHop, &buf));
2506 }
2507
2508 sample->s.my_as = getData32(sample);
2509 sample->s.src_as = getData32(sample);
2510 sample->s.src_peer_as = getData32(sample);
2511 sf_logf_U32(sample, "my_as", sample->s.my_as);
2512 sf_logf_U32(sample, "src_as", sample->s.src_as);
2513 sf_logf_U32(sample, "src_peer_as", sample->s.src_peer_as);
2514 segments = getData32(sample);
2515
2516 /* clear dst_peer_as and dst_as to make sure we are not
2517 remembering values from a previous sample - (thanks Marc Lavine) */
2518 sample->s.dst_peer_as = 0;
2519 sample->s.dst_as = 0;
2520
2521 if(segments > 0) {
2522 SFStr dst_as_path;
2523 SFStr_init(&dst_as_path);
2524 for(seg = 0; seg < segments; seg++) {
2525 uint32_t seg_type;
2526 uint32_t seg_len;
2527 uint32_t *seg_data;
2528 seg_type = getData32(sample);
2529 seg_len = getData32(sample);
2530 seg_data = sample->datap;
2531 skipBytes(sample, seg_len * 4);
2532 /* mark the first ASN as the dst_peer_as */
2533 if(seg == 0)
2534 sample->s.dst_peer_as = ntohl(seg_data[0]);
2535 /* make sure the AS sets are in parentheses */
2536 if(seg_type == SFLEXTENDED_AS_SET)
2537 SFStr_append(&dst_as_path, "(");
2538 SFStr_append_array32(&dst_as_path, seg_data, seg_len, YES, '-');
2539 if(seg_type == SFLEXTENDED_AS_SET)
2540 SFStr_append(&dst_as_path, ")");
2541 /* mark the last ASN as the dst_as */
2542 if(seg == (segments - 1))
2543 sample->s.dst_as = ntohl(seg_data[seg_len - 1]);
2544 }
2545 sf_logf(sample, "dst_as_path", SFStr_str(&dst_as_path));
2546 }
2547 sf_logf_U32(sample, "dst_as", sample->s.dst_as);
2548 sf_logf_U32(sample, "dst_peer_as", sample->s.dst_peer_as);
2549
2550 sample->s.communities_len = getData32(sample);
2551 /* just point at the communities array */
2552 if(sample->s.communities_len > 0) sample->s.communities = sample->datap;
2553 /* and skip over it in the input */
2554 skipBytes(sample, sample->s.communities_len * 4);
2555
2556 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_GATEWAY;
2557 if(sample->s.communities_len > 0) {
2558 SFStr communities;
2559 SFStr_init(&communities);
2560 SFStr_append_array32(&communities, sample->s.communities, sample->s.communities_len, YES, '-');
2561 sf_logf(sample, "BGP_communities", SFStr_str(&communities));
2562 }
2563
2564 sample->s.localpref = getData32(sample);
2565 sf_logf_U32(sample, "BGP_localpref", sample->s.localpref);
2566 }
2567
2568 /*_________________---------------------------__________________
2569 _________________ readExtendedUser __________________
2570 -----------------___________________________------------------
2571 */
2572
readExtendedUser(SFSample * sample)2573 static void readExtendedUser(SFSample *sample)
2574 {
2575 #define SA_MAX_EXTENDED_USER_LEN 200
2576 uint32_t src_user_charset;
2577 uint32_t src_user_len;
2578 char src_user[SA_MAX_EXTENDED_USER_LEN+1];
2579 uint32_t dst_user_charset;
2580 uint32_t dst_user_len;
2581 char dst_user[SA_MAX_EXTENDED_USER_LEN+1];
2582
2583 sf_logf(sample, "extendedType", "USER");
2584
2585 if(sample->datagramVersion >= 5) {
2586 src_user_charset = getData32(sample);
2587 sf_logf_U32(sample, "src_user_charset", src_user_charset);
2588 }
2589
2590 src_user_len = getString(sample, src_user, SA_MAX_EXTENDED_USER_LEN);
2591
2592 if(sample->datagramVersion >= 5) {
2593 dst_user_charset = getData32(sample);
2594 sf_logf_U32(sample, "dst_user_charset", dst_user_charset);
2595 }
2596
2597 dst_user_len = getString(sample, dst_user, SA_MAX_EXTENDED_USER_LEN);
2598
2599 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_USER;
2600
2601 sf_logf(sample, "src_user", src_user);
2602 sf_logf(sample, "dst_user", dst_user);
2603 }
2604
2605 /*_________________---------------------------__________________
2606 _________________ readExtendedUrl __________________
2607 -----------------___________________________------------------
2608 */
2609
readExtendedUrl(SFSample * sample)2610 static void readExtendedUrl(SFSample *sample)
2611 {
2612 #define SA_MAX_EXTENDED_URL_LEN 200
2613 #define SA_MAX_EXTENDED_HOST_LEN 200
2614 uint32_t url_direction;
2615 uint32_t url_len;
2616 char url[SA_MAX_EXTENDED_URL_LEN+1];
2617 uint32_t host_len;
2618 char host[SA_MAX_EXTENDED_HOST_LEN+1];
2619
2620 sf_logf(sample, "extendedType", "URL");
2621
2622 url_direction = getData32(sample);
2623 sf_logf_U32(sample, "url_direction", url_direction);
2624 url_len = getString(sample, url, SA_MAX_EXTENDED_URL_LEN);
2625 sf_logf(sample, "url", url);
2626 if(sample->datagramVersion >= 5) {
2627 host_len = getString(sample, host, SA_MAX_EXTENDED_HOST_LEN);
2628 sf_logf(sample, "host", host);
2629 }
2630 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_URL;
2631 }
2632
2633
2634 /*_________________---------------------------__________________
2635 _________________ mplsLabelStack __________________
2636 -----------------___________________________------------------
2637 */
2638
mplsLabelStack(SFSample * sample,char * fieldName)2639 static void mplsLabelStack(SFSample *sample, char *fieldName)
2640 {
2641 SFLLabelStack lstk;
2642 uint32_t lab;
2643 lstk.depth = getData32(sample);
2644 /* just point at the lablelstack array */
2645 if(lstk.depth > 0) lstk.stack = (uint32_t *)sample->datap;
2646 /* and skip over it in the input */
2647 skipBytes(sample, lstk.depth * 4);
2648
2649 if(lstk.depth > 0) {
2650 SFStr lsstr;
2651 SFStr_init(&lsstr);
2652 for(uint32_t j = 0; j < lstk.depth; j++) {
2653 if(j > 0)
2654 SFStr_append(&lsstr, "-");
2655 lab = ntohl(lstk.stack[j]);
2656 uint32_t parts[4];
2657 parts[0] = (lab >> 12); /* label */
2658 parts[1] = (lab >> 9) & 7; /* experimental */
2659 parts[2] = (lab >> 8) & 1; /* bottom of stack */
2660 parts[3] = (lab & 255); /* TTL */
2661 SFStr_append_array32(&lsstr, parts, 4, NO, '.');
2662 }
2663 sf_logf(sample, fieldName, SFStr_str(&lsstr));
2664 }
2665 }
2666
2667 /*_________________---------------------------__________________
2668 _________________ readExtendedMpls __________________
2669 -----------------___________________________------------------
2670 */
2671
readExtendedMpls(SFSample * sample)2672 static void readExtendedMpls(SFSample *sample)
2673 {
2674 SFStr buf;
2675 sf_logf(sample, "extendedType", "MPLS");
2676 getAddress(sample, &sample->s.mpls_nextHop);
2677 sf_logf(sample, "mpls_nexthop", printAddress(&sample->s.mpls_nextHop, &buf));
2678
2679 mplsLabelStack(sample, "mpls_input_stack");
2680 mplsLabelStack(sample, "mpls_output_stack");
2681
2682 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS;
2683 }
2684
2685 /*_________________---------------------------__________________
2686 _________________ readExtendedNat __________________
2687 -----------------___________________________------------------
2688 */
2689
readExtendedNat(SFSample * sample)2690 static void readExtendedNat(SFSample *sample)
2691 {
2692 SFStr buf;
2693 sf_logf(sample, "extendedType", "NAT");
2694 getAddress(sample, &sample->s.nat_src);
2695 sf_logf(sample, "nat_src", printAddress(&sample->s.nat_src, &buf));
2696 getAddress(sample, &sample->s.nat_dst);
2697 sf_logf(sample, "nat_dst", printAddress(&sample->s.nat_dst, &buf));
2698 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_NAT;
2699 }
2700
2701 /*_________________---------------------------__________________
2702 _________________ readExtendedNatPort __________________
2703 -----------------___________________________------------------
2704 */
2705
readExtendedNatPort(SFSample * sample)2706 static void readExtendedNatPort(SFSample *sample)
2707 {
2708 sf_logf(sample, "extendedType", "NAT PORT");
2709 sf_log_next32(sample, "nat_src_port");
2710 sf_log_next32(sample, "nat_dst_port");
2711 }
2712
2713
2714 /*_________________---------------------------__________________
2715 _________________ readExtendedMplsTunnel __________________
2716 -----------------___________________________------------------
2717 */
2718
readExtendedMplsTunnel(SFSample * sample)2719 static void readExtendedMplsTunnel(SFSample *sample)
2720 {
2721 #define SA_MAX_TUNNELNAME_LEN 100
2722 char tunnel_name[SA_MAX_TUNNELNAME_LEN+1];
2723 uint32_t tunnel_id, tunnel_cos;
2724
2725 if(getString(sample, tunnel_name, SA_MAX_TUNNELNAME_LEN) > 0)
2726 sf_logf(sample, "mpls_tunnel_lsp_name", tunnel_name);
2727 tunnel_id = getData32(sample);
2728 sf_logf_U32(sample, "mpls_tunnel_id", tunnel_id);
2729 tunnel_cos = getData32(sample);
2730 sf_logf_U32(sample, "mpls_tunnel_cos", tunnel_cos);
2731 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_TUNNEL;
2732 }
2733
2734 /*_________________---------------------------__________________
2735 _________________ readExtendedMplsVC __________________
2736 -----------------___________________________------------------
2737 */
2738
readExtendedMplsVC(SFSample * sample)2739 static void readExtendedMplsVC(SFSample *sample)
2740 {
2741 #define SA_MAX_VCNAME_LEN 100
2742 char vc_name[SA_MAX_VCNAME_LEN+1];
2743 uint32_t vll_vc_id, vc_cos;
2744 if(getString(sample, vc_name, SA_MAX_VCNAME_LEN) > 0)
2745 sf_logf(sample, "mpls_vc_name", vc_name);
2746 vll_vc_id = getData32(sample);
2747 sf_logf_U32(sample, "mpls_vll_vc_id", vll_vc_id);
2748 vc_cos = getData32(sample);
2749 sf_logf_U32(sample, "mpls_vc_cos", vc_cos);
2750 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_VC;
2751 }
2752
2753 /*_________________---------------------------__________________
2754 _________________ readExtendedMplsFTN __________________
2755 -----------------___________________________------------------
2756 */
2757
readExtendedMplsFTN(SFSample * sample)2758 static void readExtendedMplsFTN(SFSample *sample)
2759 {
2760 #define SA_MAX_FTN_LEN 100
2761 char ftn_descr[SA_MAX_FTN_LEN+1];
2762 uint32_t ftn_mask;
2763 if(getString(sample, ftn_descr, SA_MAX_FTN_LEN) > 0)
2764 sf_logf(sample, "mpls_ftn_descr", ftn_descr);
2765 ftn_mask = getData32(sample);
2766 sf_logf_U32(sample, "mpls_ftn_mask", ftn_mask);
2767 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_FTN;
2768 }
2769
2770 /*_________________---------------------------__________________
2771 _________________ readExtendedMplsLDP_FEC __________________
2772 -----------------___________________________------------------
2773 */
2774
readExtendedMplsLDP_FEC(SFSample * sample)2775 static void readExtendedMplsLDP_FEC(SFSample *sample)
2776 {
2777 uint32_t fec_addr_prefix_len = getData32(sample);
2778 sf_logf_U32(sample, "mpls_fec_addr_prefix_len", fec_addr_prefix_len);
2779 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_MPLS_LDP_FEC;
2780 }
2781
2782 /*_________________---------------------------__________________
2783 _________________ readExtendedVlanTunnel __________________
2784 -----------------___________________________------------------
2785 */
2786
readExtendedVlanTunnel(SFSample * sample)2787 static void readExtendedVlanTunnel(SFSample *sample)
2788 {
2789 uint32_t lab;
2790 SFLLabelStack lstk;
2791 lstk.depth = getData32(sample);
2792 /* just point at the lablelstack array */
2793 if(lstk.depth > 0) lstk.stack = (uint32_t *)sample->datap;
2794 /* and skip over it in the input */
2795 skipBytes(sample, lstk.depth * 4);
2796
2797 if(lstk.depth > 0) {
2798 SFStr vtstr;
2799 SFStr_init(&vtstr);
2800 uint32_t j = 0;
2801 for(; j < lstk.depth; j++) {
2802 if(j > 0)
2803 SFStr_append(&vtstr, "-");
2804 lab = ntohl(lstk.stack[j]);
2805 uint8_t TPI[2];
2806 uint32_t parts[3];
2807 TPI[0] = (lab >> 24);
2808 TPI[1] = (lab >> 16) & 255;
2809 parts[0] = (lab >> 13) & 7; /* priority */
2810 parts[1] = (lab >> 12) & 1; /* CFI */
2811 parts[2] = (lab & 4095); /* VLAN */
2812 SFStr_append_hex(&vtstr, TPI, 2, YES, NO, 0);
2813 SFStr_append_array32(&vtstr, parts, 3, NO, '.');
2814 }
2815 sf_logf(sample, "vlan_tunnel", SFStr_str(&vtstr));
2816 }
2817 sample->s.extended_data_tag |= SASAMPLE_EXTENDED_DATA_VLAN_TUNNEL;
2818 }
2819
2820 /*_________________---------------------------__________________
2821 _________________ readExtendedWifiPayload __________________
2822 -----------------___________________________------------------
2823 */
2824
readExtendedWifiPayload(SFSample * sample)2825 static void readExtendedWifiPayload(SFSample *sample)
2826 {
2827 sf_log_next32(sample, "cipher_suite");
2828 readFlowSample_header(sample);
2829 }
2830
2831 /*_________________---------------------------__________________
2832 _________________ readExtendedWifiRx __________________
2833 -----------------___________________________------------------
2834 */
2835
readExtendedWifiRx(SFSample * sample)2836 static void readExtendedWifiRx(SFSample *sample)
2837 {
2838 uint32_t i;
2839 uint8_t *bssid;
2840 SFStr buf;
2841 char ssid[SFL_MAX_SSID_LEN+1];
2842 if(getString(sample, ssid, SFL_MAX_SSID_LEN) > 0) {
2843 sf_logf(sample, "rx_SSID", ssid);
2844 }
2845
2846 bssid = (uint8_t *)sample->datap;
2847 skipBytes(sample, 6);
2848 sf_logf(sample, "rx_BSSID", printMAC(bssid, &buf));
2849 sf_log_next32(sample, "rx_version");
2850 sf_log_next32(sample, "rx_channel");
2851 sf_log_next64(sample, "rx_speed");
2852 sf_log_next32(sample, "rx_rsni");
2853 sf_log_next32(sample, "rx_rcpi");
2854 sf_log_next32(sample, "rx_packet_uS");
2855 }
2856
2857 /*_________________---------------------------__________________
2858 _________________ readExtendedWifiTx __________________
2859 -----------------___________________________------------------
2860 */
2861
readExtendedWifiTx(SFSample * sample)2862 static void readExtendedWifiTx(SFSample *sample)
2863 {
2864 uint32_t i;
2865 uint8_t *bssid;
2866 SFStr buf;
2867 char ssid[SFL_MAX_SSID_LEN+1];
2868 if(getString(sample, ssid, SFL_MAX_SSID_LEN) > 0) {
2869 sf_logf(sample, "tx_SSID", ssid);
2870 }
2871
2872 bssid = (uint8_t *)sample->datap;
2873 skipBytes(sample, 6);
2874 sf_logf(sample, "tx_BSSID", printMAC(bssid, &buf));
2875 sf_log_next32(sample, "tx_version");
2876 sf_log_next32(sample, "tx_transmissions");
2877 sf_log_next32(sample, "tx_packet_uS");
2878 sf_log_next32(sample, "tx_retrans_uS");
2879 sf_log_next32(sample, "tx_channel");
2880 sf_log_next64(sample, "tx_speed");
2881 sf_log_next32(sample, "tx_power_mW");
2882 }
2883
2884 /*_________________---------------------------__________________
2885 _________________ readExtendedAggregation __________________
2886 -----------------___________________________------------------
2887 */
2888
2889 #if 0 /* commenting this out until its caller is uncommented too */
2890 static void readExtendedAggregation(SFSample *sample)
2891 {
2892 uint32_t i, num_pdus = getData32(sample);
2893 sf_logf_U32(sample, "aggregation_num_pdus", num_pdus);
2894 for(i = 0; i < num_pdus; i++) {
2895 sf_logf_U32(sample, "aggregation_pdu", i);
2896 readFlowSample(sample, NO); /* not sure if this the right one here */
2897 }
2898 }
2899 #endif
2900
2901 /*_________________---------------------------__________________
2902 _________________ readFlowSample_header __________________
2903 -----------------___________________________------------------
2904 */
2905
readFlowSample_header(SFSample * sample)2906 static void readFlowSample_header(SFSample *sample)
2907 {
2908 SFStr scratch;
2909 sf_logf(sample, "flowSampleType", "HEADER");
2910 sample->s.headerProtocol = getData32(sample);
2911 sf_logf_U32(sample, "headerProtocol", sample->s.headerProtocol);
2912 sample->s.sampledPacketSize = getData32(sample);
2913 sf_logf_U32(sample, "sampledPacketSize", sample->s.sampledPacketSize);
2914 if(sample->datagramVersion > 4) {
2915 /* stripped count introduced in sFlow version 5 */
2916 sample->s.stripped = getData32(sample);
2917 sf_logf_U32(sample, "strippedBytes", sample->s.stripped);
2918 }
2919 sample->s.headerLen = getData32(sample);
2920 sf_logf_U32(sample, "headerLen", sample->s.headerLen);
2921
2922 sample->s.header = (uint8_t *)sample->datap; /* just point at the header */
2923 skipBytes(sample, sample->s.headerLen);
2924 SFStr_init(&scratch);
2925 SFStr_append_hex(&scratch, sample->s.header, sample->s.headerLen, NO, YES, '-');
2926 sf_logf(sample, "headerBytes", SFStr_str(&scratch));
2927
2928 switch(sample->s.headerProtocol) {
2929 /* the header protocol tells us where to jump into the decode */
2930 case SFLHEADER_ETHERNET_ISO8023:
2931 decodeLinkLayer(sample);
2932 break;
2933 case SFLHEADER_IPv4:
2934 sample->s.gotIPV4 = YES;
2935 sample->s.offsetToIPV4 = 0;
2936 break;
2937 case SFLHEADER_IPv6:
2938 sample->s.gotIPV6 = YES;
2939 sample->s.offsetToIPV6 = 0;
2940 break;
2941 case SFLHEADER_IEEE80211MAC:
2942 decode80211MAC(sample);
2943 break;
2944 case SFLHEADER_ISO88024_TOKENBUS:
2945 case SFLHEADER_ISO88025_TOKENRING:
2946 case SFLHEADER_FDDI:
2947 case SFLHEADER_FRAME_RELAY:
2948 case SFLHEADER_X25:
2949 case SFLHEADER_PPP:
2950 case SFLHEADER_SMDS:
2951 case SFLHEADER_AAL5:
2952 case SFLHEADER_AAL5_IP:
2953 case SFLHEADER_MPLS:
2954 case SFLHEADER_POS:
2955 case SFLHEADER_IEEE80211_AMPDU:
2956 case SFLHEADER_IEEE80211_AMSDU_SUBFRAME:
2957 sf_log(sample,"NO_DECODE headerProtocol=%d\n", sample->s.headerProtocol);
2958 break;
2959 default:
2960 fprintf(ERROUT, "undefined headerProtocol = %d\n", sample->s.headerProtocol);
2961 exit(-12);
2962 }
2963
2964 if(sample->s.gotIPV4) {
2965 /* report the size of the original IPPdu (including the IP header) */
2966 sf_logf_U32_formatted(sample, NULL, "IPSize", "%d", sample->s.sampledPacketSize - sample->s.stripped - sample->s.offsetToIPV4);
2967 decodeIPV4(sample);
2968 }
2969 else if(sample->s.gotIPV6) {
2970 /* report the size of the original IPPdu (including the IP header) */
2971 sf_logf_U32_formatted(sample, NULL, "IPSize", "%d", sample->s.sampledPacketSize - sample->s.stripped - sample->s.offsetToIPV6);
2972 decodeIPV6(sample);
2973 }
2974
2975 }
2976
2977 /*_________________---------------------------__________________
2978 _________________ readFlowSample_ethernet __________________
2979 -----------------___________________________------------------
2980 */
2981
readFlowSample_ethernet(SFSample * sample,char * prefix)2982 static void readFlowSample_ethernet(SFSample *sample, char *prefix)
2983 {
2984 SFStr buf;
2985 SFStr_init(&buf);
2986 SFStr_append(&buf, prefix);
2987 SFStr_append(&buf, "ETHERNET");
2988 sf_logf(sample, "flowSampleType", SFStr_str(&buf));
2989 sample->s.eth_len = getData32(sample);
2990 memcpy(sample->s.eth_src, sample->datap, 6);
2991 skipBytes(sample, 6);
2992 memcpy(sample->s.eth_dst, sample->datap, 6);
2993 skipBytes(sample, 6);
2994 sample->s.eth_type = getData32(sample);
2995 sf_logf_pushPrefix(sample, prefix);
2996 sf_logf_U32(sample, "ethernet_type", sample->s.eth_type);
2997 sf_logf_U32(sample, "ethernet_len", sample->s.eth_len);
2998 sf_logf(sample, "ethernet_src", printMAC(sample->s.eth_src, &buf));
2999 sf_logf(sample, "ethernet_dst", printMAC(sample->s.eth_dst, &buf));
3000 sf_logf_popPrefix(sample);
3001 }
3002
3003
3004 /*_________________---------------------------__________________
3005 _________________ readFlowSample_IPv4 __________________
3006 -----------------___________________________------------------
3007 */
3008
readFlowSample_IPv4(SFSample * sample,char * prefix)3009 static void readFlowSample_IPv4(SFSample *sample, char *prefix)
3010 {
3011 SFStr buf;
3012 SFStr_init(&buf);
3013 SFStr_append(&buf, prefix);
3014 SFStr_append(&buf, "IPV4");
3015 sf_logf(sample, "flowSampleType", SFStr_str(&buf));
3016 sample->s.headerLen = sizeof(SFLSampled_ipv4);
3017 sample->s.header = (uint8_t *)sample->datap; /* just point at the header */
3018 skipBytes(sample, sample->s.headerLen);
3019 sf_logf_pushPrefix(sample, prefix);
3020 {
3021 SFStr buf;
3022 SFLSampled_ipv4 nfKey;
3023 memcpy(&nfKey, sample->s.header, sizeof(nfKey));
3024 sample->s.sampledPacketSize = ntohl(nfKey.length);
3025 sf_logf_U32(sample, "sampledPacketSize", sample->s.sampledPacketSize);
3026 sf_logf_U32(sample, "IPSize", sample->s.sampledPacketSize);
3027 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V4;
3028 sample->s.ipsrc.address.ip_v4 = nfKey.src_ip;
3029 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V4;
3030 sample->s.ipdst.address.ip_v4 = nfKey.dst_ip;
3031 sample->s.dcd_ipProtocol = ntohl(nfKey.protocol);
3032 sample->s.dcd_ipTos = ntohl(nfKey.tos);
3033 sf_logf(sample, "srcIP", printAddress(&sample->s.ipsrc, &buf));
3034 sf_logf(sample, "dstIP", printAddress(&sample->s.ipdst, &buf));
3035 sf_logf_U32(sample, "IPProtocol", sample->s.dcd_ipProtocol);
3036 sf_logf_U32(sample, "IPTOS", sample->s.dcd_ipTos);
3037 sample->s.dcd_sport = ntohl(nfKey.src_port);
3038 sample->s.dcd_dport = ntohl(nfKey.dst_port);
3039 switch(sample->s.dcd_ipProtocol) {
3040 case 1: /* ICMP */
3041 sf_logf_U32(sample, "ICMPType", sample->s.dcd_dport);
3042 /* not sure about the dest port being icmp type
3043 - might be that src port is icmp type and dest
3044 port is icmp code. Still, have seen some
3045 implementations where src port is 0 and dst
3046 port is the type, so it may be safer to
3047 assume that the destination port has the type */
3048 break;
3049 case 6: /* TCP */
3050 sf_logf_U32(sample, "TCPSrcPort", sample->s.dcd_sport);
3051 sf_logf_U32(sample, "TCPDstPort", sample->s.dcd_dport);
3052 sample->s.dcd_tcpFlags = ntohl(nfKey.tcp_flags);
3053 sf_logf_U32(sample, "TCPFlags", sample->s.dcd_tcpFlags);
3054 break;
3055 case 17: /* UDP */
3056 sf_logf_U32(sample, "UDPSrcPort", sample->s.dcd_sport);
3057 sf_logf_U32(sample, "UDPDstPort", sample->s.dcd_dport);
3058 break;
3059 default: /* some other protcol */
3060 break;
3061 }
3062 }
3063 sf_logf_popPrefix(sample);
3064 }
3065
3066 /*_________________---------------------------__________________
3067 _________________ readFlowSample_IPv6 __________________
3068 -----------------___________________________------------------
3069 */
3070
readFlowSample_IPv6(SFSample * sample,char * prefix)3071 static void readFlowSample_IPv6(SFSample *sample, char *prefix)
3072 {
3073 SFStr buf;
3074 SFStr_init(&buf);
3075 SFStr_append(&buf, prefix);
3076 SFStr_append(&buf, "IPV6");
3077 sf_logf(sample, "flowSampleType", SFStr_str(&buf));
3078 sample->s.header = (uint8_t *)sample->datap; /* just point at the header */
3079 sample->s.headerLen = sizeof(SFLSampled_ipv6);
3080 skipBytes(sample, sample->s.headerLen);
3081 sf_logf_pushPrefix(sample, prefix);
3082 {
3083 SFStr buf;
3084 SFLSampled_ipv6 nfKey6;
3085 memcpy(&nfKey6, sample->s.header, sizeof(nfKey6));
3086 sample->s.sampledPacketSize = ntohl(nfKey6.length);
3087 sf_logf_U32(sample, "sampledPacketSize", sample->s.sampledPacketSize);
3088 sf_logf_U32(sample, "IPSize", sample->s.sampledPacketSize);
3089 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V6;
3090 memcpy(&sample->s.ipsrc.address.ip_v6, &nfKey6.src_ip, 16);
3091 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V6;
3092 memcpy(&sample->s.ipdst.address.ip_v6, &nfKey6.dst_ip, 16);
3093 sample->s.dcd_ipProtocol = ntohl(nfKey6.protocol);
3094 sf_logf(sample, "srcIP6", printAddress(&sample->s.ipsrc, &buf));
3095 sf_logf(sample, "dstIP6", printAddress(&sample->s.ipdst, &buf));
3096 sf_logf_U32(sample, "IPProtocol", sample->s.dcd_ipProtocol);
3097 sf_logf_U32(sample, "priority", ntohl(nfKey6.priority));
3098 sample->s.dcd_sport = ntohl(nfKey6.src_port);
3099 sample->s.dcd_dport = ntohl(nfKey6.dst_port);
3100 switch(sample->s.dcd_ipProtocol) {
3101 case 1: /* ICMP */
3102 sf_logf_U32(sample, "ICMPType", sample->s.dcd_dport);
3103 /* not sure about the dest port being icmp type
3104 - might be that src port is icmp type and dest
3105 port is icmp code. Still, have seen some
3106 implementations where src port is 0 and dst
3107 port is the type, so it may be safer to
3108 assume that the destination port has the type */
3109 break;
3110 case 6: /* TCP */
3111 sf_logf_U32(sample, "TCPSrcPort", sample->s.dcd_sport);
3112 sf_logf_U32(sample, "TCPDstPort", sample->s.dcd_dport);
3113 sample->s.dcd_tcpFlags = ntohl(nfKey6.tcp_flags);
3114 sf_logf_U32(sample, "TCPFlags", sample->s.dcd_tcpFlags);
3115 break;
3116 case 17: /* UDP */
3117 sf_logf_U32(sample, "UDPSrcPort", sample->s.dcd_sport);
3118 sf_logf_U32(sample, "UDPDstPort", sample->s.dcd_dport);
3119 break;
3120 default: /* some other protcol */
3121 break;
3122 }
3123 }
3124 sf_logf_popPrefix(sample);
3125 }
3126
3127 /*_________________----------------------------__________________
3128 _________________ readFlowSample_memcache __________________
3129 -----------------____________________________------------------
3130 */
3131
readFlowSample_memcache(SFSample * sample)3132 static void readFlowSample_memcache(SFSample *sample)
3133 {
3134 char key[SFL_MAX_MEMCACHE_KEY+1];
3135 #define ENC_KEY_BYTES (SFL_MAX_MEMCACHE_KEY * 3) + 1
3136 char enc_key[ENC_KEY_BYTES];
3137 sf_logf(sample, "flowSampleType", "memcache");
3138 sf_log_next32(sample, "memcache_op_protocol");
3139 sf_log_next32(sample, "memcache_op_cmd");
3140 if(getString(sample, key, SFL_MAX_MEMCACHE_KEY) > 0) {
3141 sf_logf(sample, "memcache_op_key", URLEncode(key, enc_key, ENC_KEY_BYTES));
3142 }
3143 sf_log_next32(sample, "memcache_op_nkeys");
3144 sf_log_next32(sample, "memcache_op_value_bytes");
3145 sf_log_next32(sample, "memcache_op_duration_uS");
3146 sf_log_next32(sample, "memcache_op_status");
3147 }
3148
3149 /*_________________----------------------------__________________
3150 _________________ readFlowSample_http __________________
3151 -----------------____________________________------------------
3152 */
3153
3154 /* absorb compiler warning about strftime printing */
3155 #pragma GCC diagnostic push
3156 #pragma GCC diagnostic ignored "-Wformat"
3157
readFlowSample_http(SFSample * sample,uint32_t tag)3158 static void readFlowSample_http(SFSample *sample, uint32_t tag)
3159 {
3160 char uri[SFL_MAX_HTTP_URI+1];
3161 char host[SFL_MAX_HTTP_HOST+1];
3162 char referrer[SFL_MAX_HTTP_REFERRER+1];
3163 char useragent[SFL_MAX_HTTP_USERAGENT+1];
3164 char xff[SFL_MAX_HTTP_XFF+1];
3165 char authuser[SFL_MAX_HTTP_AUTHUSER+1];
3166 char mimetype[SFL_MAX_HTTP_MIMETYPE+1];
3167 uint32_t method;
3168 uint32_t protocol;
3169 uint32_t status;
3170 uint64_t req_bytes;
3171 uint64_t resp_bytes;
3172
3173 sf_logf(sample, "flowSampleType", "http");
3174 method = sf_log_next32(sample, "http_method");
3175 protocol = sf_log_next32(sample, "http_protocol");
3176 if(getString(sample, uri, SFL_MAX_HTTP_URI) > 0) {
3177 sf_logf(sample, "http_uri", uri);
3178 }
3179 if(getString(sample, host, SFL_MAX_HTTP_HOST) > 0) {
3180 sf_logf(sample, "http_host", host);
3181 }
3182 if(getString(sample, referrer, SFL_MAX_HTTP_REFERRER) > 0) {
3183 sf_logf(sample, "http_referrer", referrer);
3184 }
3185 if(getString(sample, useragent, SFL_MAX_HTTP_USERAGENT) > 0) {
3186 sf_logf(sample, "http_useragent", useragent);
3187 }
3188 if(tag == SFLFLOW_HTTP2) {
3189 if(getString(sample, xff, SFL_MAX_HTTP_XFF) > 0) {
3190 sf_logf(sample, "http_xff", xff);
3191 }
3192 }
3193 if(getString(sample, authuser, SFL_MAX_HTTP_AUTHUSER) > 0) {
3194 sf_logf(sample, "http_authuser", authuser);
3195 }
3196 if(getString(sample, mimetype, SFL_MAX_HTTP_MIMETYPE) > 0) {
3197 sf_logf(sample, "http_mimetype", mimetype);
3198 }
3199 if(tag == SFLFLOW_HTTP2) {
3200 req_bytes = sf_log_next64(sample, "http_request_bytes");
3201 }
3202 resp_bytes = sf_log_next64(sample, "http_bytes");
3203 sf_log_next32(sample, "http_duration_uS");
3204 status = sf_log_next32(sample, "http_status");
3205
3206 if(sfConfig.outputFormat == SFLFMT_CLF) {
3207 time_t now = time(NULL);
3208 char nowstr[200];
3209 strftime(nowstr, 200, "%d/%b/%Y:%H:%M:%S %z", localtime(&now)); /* there seems to be no simple portable equivalent to %z */
3210 /* should really be: snprintf(sfCLF.http_log, SFLFMT_CLF_MAX_LINE,...) but snprintf() is not always available */
3211 sprintf(sfCLF.http_log, "- %s [%s] \"%s %s HTTP/%u.%u\" %u %"PRIu64" \"%s\" \"%s\"",
3212 authuser[0] ? authuser : "-",
3213 nowstr,
3214 SFHTTP_method_names[method],
3215 uri[0] ? uri : "-",
3216 protocol / 1000,
3217 protocol % 1000,
3218 status,
3219 resp_bytes,
3220 referrer[0] ? referrer : "-",
3221 useragent[0] ? useragent : "-");
3222 sfCLF.valid = YES;
3223 }
3224 }
3225
3226 #pragma GCC diagnostic pop
3227
3228 /*_________________----------------------------__________________
3229 _________________ readFlowSample_APP __________________
3230 -----------------____________________________------------------
3231 */
3232
readFlowSample_APP(SFSample * sample)3233 static void readFlowSample_APP(SFSample *sample)
3234 {
3235 char application[SFLAPP_MAX_APPLICATION_LEN];
3236 char operation[SFLAPP_MAX_OPERATION_LEN];
3237 char attributes[SFLAPP_MAX_ATTRIBUTES_LEN];
3238 char status[SFLAPP_MAX_STATUS_LEN];
3239 uint32_t status32;
3240
3241 sf_logf(sample, "flowSampleType", "applicationOperation");
3242
3243 if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) {
3244 sf_logf(sample, "application", application);
3245 }
3246 if(getString(sample, operation, SFLAPP_MAX_OPERATION_LEN) > 0) {
3247 sf_logf(sample, "operation", operation);
3248 }
3249 if(getString(sample, attributes, SFLAPP_MAX_ATTRIBUTES_LEN) > 0) {
3250 sf_logf(sample, "attributes", attributes);
3251 }
3252 if(getString(sample, status, SFLAPP_MAX_STATUS_LEN) > 0) {
3253 sf_logf(sample, "status_descr", status);
3254 }
3255 sf_log_next64(sample, "request_bytes");
3256 sf_log_next64(sample, "response_bytes");
3257 sf_log_next32(sample, "duration_uS");
3258 status32 = getData32(sample);
3259 if(status32 >= SFLAPP_NUM_STATUS_CODES) {
3260 char buf[64];
3261 sprintf(buf, "<out-of-range=%u>", status32);
3262 sf_logf(sample, "status", buf);
3263 }
3264 else {
3265 sf_logf(sample, "status", (char *)SFL_APP_STATUS_names[status32]);
3266 }
3267 }
3268
3269
3270 /*_________________----------------------------__________________
3271 _________________ readFlowSample_APP_CTXT __________________
3272 -----------------____________________________------------------
3273 */
3274
readFlowSample_APP_CTXT(SFSample * sample)3275 static void readFlowSample_APP_CTXT(SFSample *sample)
3276 {
3277 char application[SFLAPP_MAX_APPLICATION_LEN];
3278 char operation[SFLAPP_MAX_OPERATION_LEN];
3279 char attributes[SFLAPP_MAX_ATTRIBUTES_LEN];
3280 if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) {
3281 sf_logf(sample, "server_context_application", application);
3282 }
3283 if(getString(sample, operation, SFLAPP_MAX_OPERATION_LEN) > 0) {
3284 sf_logf(sample, "server_context_operation", operation);
3285 }
3286 if(getString(sample, attributes, SFLAPP_MAX_ATTRIBUTES_LEN) > 0) {
3287 sf_logf(sample, "server_context_attributes", attributes);
3288 }
3289 }
3290
3291 /*_________________---------------------------------__________________
3292 _________________ readFlowSample_APP_ACTOR_INIT __________________
3293 -----------------_________________________________------------------
3294 */
3295
readFlowSample_APP_ACTOR_INIT(SFSample * sample)3296 static void readFlowSample_APP_ACTOR_INIT(SFSample *sample)
3297 {
3298 char actor[SFLAPP_MAX_ACTOR_LEN];
3299 if(getString(sample, actor, SFLAPP_MAX_ACTOR_LEN) > 0) {
3300 sf_logf(sample, "actor_initiator", actor);
3301 }
3302 }
3303
3304 /*_________________---------------------------------__________________
3305 _________________ readFlowSample_APP_ACTOR_TGT __________________
3306 -----------------_________________________________------------------
3307 */
3308
readFlowSample_APP_ACTOR_TGT(SFSample * sample)3309 static void readFlowSample_APP_ACTOR_TGT(SFSample *sample)
3310 {
3311 char actor[SFLAPP_MAX_ACTOR_LEN];
3312 if(getString(sample, actor, SFLAPP_MAX_ACTOR_LEN) > 0) {
3313 sf_logf(sample, "actor_target", actor);
3314 }
3315 }
3316
3317 /*_________________----------------------------__________________
3318 _________________ readExtendedSocket4 __________________
3319 -----------------____________________________------------------
3320 */
3321
readExtendedSocket4(SFSample * sample)3322 static void readExtendedSocket4(SFSample *sample)
3323 {
3324 SFStr buf;
3325 sf_logf(sample, "extendedType", "socket4");
3326 sf_log_next32(sample, "socket4_ip_protocol");
3327 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V4;
3328 sample->s.ipsrc.address.ip_v4.addr = getData32_nobswap(sample);
3329 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V4;
3330 sample->s.ipdst.address.ip_v4.addr = getData32_nobswap(sample);
3331 sf_logf(sample, "socket4_local_ip", printAddress(&sample->s.ipsrc, &buf));
3332 sf_logf(sample, "socket4_remote_ip", printAddress(&sample->s.ipdst, &buf));
3333 sf_log_next32(sample, "socket4_local_port");
3334 sf_log_next32(sample, "socket4_remote_port");
3335
3336 if(sfConfig.outputFormat == SFLFMT_CLF)
3337 SFStr_copy(&buf, sfCLF.client, SFLFMT_CLF_MAX_CLIENT_LEN);
3338 }
3339
3340 /*_________________----------------------------__________________
3341 _________________ readExtendedProxySocket4 __________________
3342 -----------------____________________________------------------
3343 */
3344
readExtendedProxySocket4(SFSample * sample)3345 static void readExtendedProxySocket4(SFSample *sample)
3346 {
3347 SFStr buf;
3348 SFLAddress ipsrc,ipdst;
3349 sf_logf(sample, "extendedType", "proxy_socket4");
3350 sf_log_next32(sample, "proxy_socket4_ip_protocol");
3351 ipsrc.type = SFLADDRESSTYPE_IP_V4;
3352 ipsrc.address.ip_v4.addr = getData32_nobswap(sample);
3353 ipdst.type = SFLADDRESSTYPE_IP_V4;
3354 ipdst.address.ip_v4.addr = getData32_nobswap(sample);
3355 sf_logf(sample, "proxy_socket4_local_ip", printAddress(&ipsrc, &buf));
3356 sf_logf(sample, "proxy_socket4_remote_ip", printAddress(&ipdst, &buf));
3357 sf_log_next32(sample, "proxy_socket4_local_port");
3358 sf_log_next32(sample, "proxy_socket4_remote_port");
3359 }
3360
3361 /*_________________----------------------------__________________
3362 _________________ readExtendedSocket6 __________________
3363 -----------------____________________________------------------
3364 */
3365
readExtendedSocket6(SFSample * sample)3366 static void readExtendedSocket6(SFSample *sample)
3367 {
3368 SFStr buf;
3369 sf_logf(sample, "extendedType", "socket6");
3370 sf_log_next32(sample, "socket6_ip_protocol");
3371 sample->s.ipsrc.type = SFLADDRESSTYPE_IP_V6;
3372 memcpy(&sample->s.ipsrc.address.ip_v6, sample->datap, 16);
3373 skipBytes(sample, 16);
3374 sample->s.ipdst.type = SFLADDRESSTYPE_IP_V6;
3375 memcpy(&sample->s.ipdst.address.ip_v6, sample->datap, 16);
3376 skipBytes(sample, 16);
3377 sf_logf(sample, "socket6_local_ip", printAddress(&sample->s.ipsrc, &buf));
3378 sf_logf(sample, "socket6_remote_ip", printAddress(&sample->s.ipdst, &buf));
3379 sf_log_next32(sample, "socket6_local_port");
3380 sf_log_next32(sample, "socket6_remote_port");
3381
3382 if(sfConfig.outputFormat == SFLFMT_CLF)
3383 SFStr_copy(&buf, sfCLF.client, SFLFMT_CLF_MAX_CLIENT_LEN);
3384 }
3385
3386 /*_________________----------------------------__________________
3387 _________________ readExtendedProxySocket6 __________________
3388 -----------------____________________________------------------
3389 */
3390
readExtendedProxySocket6(SFSample * sample)3391 static void readExtendedProxySocket6(SFSample *sample)
3392 {
3393 SFStr buf;
3394 SFLAddress ipsrc, ipdst;
3395 sf_logf(sample, "extendedType", "proxy_socket6");
3396 sf_log_next32(sample, "proxy_socket6_ip_protocol");
3397 ipsrc.type = SFLADDRESSTYPE_IP_V6;
3398 memcpy(&ipsrc.address.ip_v6, sample->datap, 16);
3399 skipBytes(sample, 16);
3400 ipdst.type = SFLADDRESSTYPE_IP_V6;
3401 memcpy(&ipdst.address.ip_v6, sample->datap, 16);
3402 skipBytes(sample, 16);
3403 sf_logf(sample, "proxy_socket6_local_ip", printAddress(&ipsrc, &buf));
3404 sf_logf(sample, "proxy_socket6_remote_ip", printAddress(&ipdst, &buf));
3405 sf_log_next32(sample, "proxy_socket6_local_port");
3406 sf_log_next32(sample, "proxy_socket6_remote_port");
3407 }
3408
3409 /*_________________----------------------------__________________
3410 _________________ readExtendedDecap __________________
3411 -----------------____________________________------------------
3412 */
3413
readExtendedDecap(SFSample * sample,char * prefix)3414 static void readExtendedDecap(SFSample *sample, char *prefix)
3415 {
3416 SFStr buf;
3417 SFStr_init(&buf);
3418 SFStr_append(&buf, prefix);
3419 SFStr_append(&buf, "decap");
3420 sf_logf(sample, "extendedType", SFStr_str(&buf));
3421 uint32_t offset = getData32(sample);
3422 sf_logf_U32_formatted(sample, prefix, "decap_inner_header_offset", "%u", offset);
3423 }
3424
3425 /*_________________----------------------------__________________
3426 _________________ readExtendedVNI __________________
3427 -----------------____________________________------------------
3428 */
3429
readExtendedVNI(SFSample * sample,char * prefix)3430 static void readExtendedVNI(SFSample *sample, char *prefix)
3431 {
3432 SFStr buf;
3433 SFStr_init(&buf);
3434 SFStr_append(&buf, prefix);
3435 SFStr_append(&buf, "VNI");
3436 sf_logf(sample, "extendedType", SFStr_str(&buf));
3437 uint32_t vni = getData32(sample);
3438 sf_logf_U32_formatted(sample, prefix, "VNI", "%u", vni);
3439 }
3440
3441 /*_________________----------------------------__________________
3442 _________________ readExtendedTCPInfo __________________
3443 -----------------____________________________------------------
3444 */
3445
readExtendedTCPInfo(SFSample * sample)3446 static void readExtendedTCPInfo(SFSample *sample)
3447 {
3448 char *direction;
3449 EnumPktDirection dirn = getData32(sample);
3450 switch(dirn) {
3451 case PKTDIR_unknown: direction = "unknown"; break;
3452 case PKTDIR_received: direction = "received"; break;
3453 case PKTDIR_sent: direction = "sent"; break;
3454 default: direction = "<bad value>"; break;
3455 }
3456 sf_logf(sample, "tcpinfo_direction", direction);
3457 sf_log_next32(sample, "tcpinfo_send_mss");
3458 sf_log_next32(sample, "tcpinfo_receive_mss");
3459 sf_log_next32(sample, "tcpinfo_unacked_pkts");
3460 sf_log_next32(sample, "tcpinfo_lost_pkts");
3461 sf_log_next32(sample, "tcpinfo_retrans_pkts");
3462 sf_log_next32(sample, "tcpinfo_path_mtu");
3463 sf_log_next32(sample, "tcpinfo_rtt_uS");
3464 sf_log_next32(sample, "tcpinfo_rtt_uS_var");
3465 sf_log_next32(sample, "tcpinfo_send_congestion_win");
3466 sf_log_next32(sample, "tcpinfo_reordering");
3467 sf_log_next32(sample, "tcpinfo_rtt_uS_min");
3468 }
3469
3470 /*_________________----------------------------__________________
3471 _________________ readExtendedEntities __________________
3472 -----------------____________________________------------------
3473 */
3474
readExtendedEntities(SFSample * sample)3475 static void readExtendedEntities(SFSample *sample)
3476 {
3477 sf_logf(sample, "extendedType", "entities");
3478 sf_log_next32(sample, "entities_src_class");
3479 sf_log_next32(sample, "entities_src_index");
3480 sf_log_next32(sample, "entities_dst_class");
3481 sf_log_next32(sample, "entities_dst_index");
3482 }
3483
3484 /*_________________----------------------------__________________
3485 _________________ readExtendedFunction __________________
3486 -----------------____________________________------------------
3487 */
3488
readExtendedFunction(SFSample * sample)3489 static void readExtendedFunction(SFSample *sample)
3490 {
3491 sf_logf(sample, "extendedType", "function");
3492 char fnSymbol[SFL_MAX_FUNCTION_SYMBOL_LEN+1];
3493 if(getString(sample, fnSymbol, SFL_MAX_FUNCTION_SYMBOL_LEN) > 0) {
3494 sf_logf(sample, "symbol", fnSymbol);
3495 }
3496 }
3497
3498 /*_________________---------------------------__________________
3499 _________________ readFlowSample_v2v4 __________________
3500 -----------------___________________________------------------
3501 */
3502
readFlowSample_v2v4(SFSample * sample)3503 static void readFlowSample_v2v4(SFSample *sample)
3504 {
3505 SFStr buf;
3506 sf_logf(sample, "sampleType", "FLOWSAMPLE");
3507
3508 sample->s.samplesGenerated = getData32(sample);
3509 sf_logf_U32(sample, "sampleSequenceNo", sample->s.samplesGenerated);
3510 {
3511 uint32_t samplerId = getData32(sample);
3512 sample->s.ds_class = samplerId >> 24;
3513 sample->s.ds_index = samplerId & 0x00ffffff;
3514 sf_logf(sample, "sourceId", printDataSource(sample->s.ds_class, sample->s.ds_index, &buf));
3515 }
3516
3517 sample->s.meanSkipCount = getData32(sample);
3518 sample->s.samplePool = getData32(sample);
3519 sample->s.dropEvents = getData32(sample);
3520 sample->s.inputPort = getData32(sample);
3521 sample->s.outputPort = getData32(sample);
3522 sf_logf_U32(sample, "meanSkipCount", sample->s.meanSkipCount);
3523 sf_logf_U32(sample, "samplePool", sample->s.samplePool);
3524 sf_logf_U32(sample, "dropEvents", sample->s.dropEvents);
3525 sf_logf_U32(sample, "inputPort", sample->s.inputPort);
3526 sf_logf(sample, "outputPort", printOutputPort_v2v4(sample->s.outputPort, &buf));
3527
3528 sample->s.packet_data_tag = getData32(sample);
3529
3530 if(sfConfig.outputFormat == SFLFMT_JSON) {
3531 json_start_ar("elements");
3532 json_start_ob(NULL);
3533 }
3534
3535 switch(sample->s.packet_data_tag) {
3536
3537 case INMPACKETTYPE_HEADER: readFlowSample_header(sample); break;
3538 case INMPACKETTYPE_IPV4:
3539 sample->s.gotIPV4Struct = YES;
3540 readFlowSample_IPv4(sample, "");
3541 break;
3542 case INMPACKETTYPE_IPV6:
3543 sample->s.gotIPV6Struct = YES;
3544 readFlowSample_IPv6(sample, "");
3545 break;
3546 default: receiveError(sample, "unexpected packet_data_tag", YES); break;
3547 }
3548
3549 if(sfConfig.outputFormat == SFLFMT_JSON)
3550 json_end_ob();
3551
3552 sample->s.extended_data_tag = 0;
3553 {
3554 uint32_t x;
3555 sample->s.num_extended = getData32(sample);
3556 for(x = 0; x < sample->s.num_extended; x++) {
3557 uint32_t extended_tag;
3558 if(sfConfig.outputFormat == SFLFMT_JSON) {
3559 json_start_ob(NULL);
3560 }
3561 extended_tag = getData32(sample);
3562 switch(extended_tag) {
3563 case INMEXTENDED_SWITCH: readExtendedSwitch(sample); break;
3564 case INMEXTENDED_ROUTER: readExtendedRouter(sample); break;
3565 case INMEXTENDED_GATEWAY:
3566 if(sample->datagramVersion == 2) readExtendedGateway_v2(sample);
3567 else readExtendedGateway(sample);
3568 break;
3569 case INMEXTENDED_USER: readExtendedUser(sample); break;
3570 case INMEXTENDED_URL: readExtendedUrl(sample); break;
3571 default: receiveError(sample, "unrecognized extended data tag", YES); break;
3572 }
3573 if(sfConfig.outputFormat == SFLFMT_JSON)
3574 json_end_ob();
3575 }
3576 }
3577 if(sfConfig.outputFormat == SFLFMT_JSON)
3578 json_end_ar();
3579
3580 if(sampleFilterOK(sample)) {
3581 switch(sfConfig.outputFormat) {
3582 case SFLFMT_NETFLOW:
3583 /* if we are exporting netflow and we have an IPv4 layer, compose the datagram now */
3584 if(sfConfig.netFlowOutputSocket && (sample->s.gotIPV4 || sample->s.gotIPV4Struct)) sendNetFlowDatagram(sample);
3585 break;
3586 case SFLFMT_PCAP:
3587 /* if we are writing tcpdump format, write the next packet record now */
3588 writePcapPacket(sample);
3589 break;
3590 case SFLFMT_PCAP_DISCARD:
3591 break;
3592 case SFLFMT_LINE:
3593 /* or line-by-line output... */
3594 writeFlowLine(sample);
3595 break;
3596 case SFLFMT_LINE_CUSTOM:
3597 /* or custom line-by-line output... */
3598 writeLineCustom(sample);
3599 break;
3600 case SFLFMT_CLF:
3601 case SFLFMT_FULL:
3602 case SFLFMT_SCRIPT:
3603 case SFLFMT_JSON:
3604 default:
3605 /* if it was full-detail output then it was done as we went along */
3606 break;
3607 }
3608 }
3609 if(sfConfig.outputFormat == SFLFMT_LINE_CUSTOM) {
3610 /* do this here in case sampleFilter rejected sample above */
3611 clearLineCustom(sample, SFSCOPE_SAMPLE);
3612 }
3613 }
3614
3615 /*_________________---------------------------__________________
3616 _________________ readFlowSample __________________
3617 -----------------___________________________------------------
3618 */
3619
readFlowSample(SFSample * sample,int expanded)3620 static void readFlowSample(SFSample *sample, int expanded)
3621 {
3622 SFStr buf;
3623 uint32_t num_elements, sampleLength;
3624 uint8_t *sampleStart;
3625
3626 sf_logf(sample, "sampleType", "FLOWSAMPLE");
3627 sampleLength = getData32(sample);
3628 sampleStart = (uint8_t *)sample->datap;
3629 sample->s.samplesGenerated = getData32(sample);
3630 if(expanded) {
3631 sample->s.ds_class = getData32(sample);
3632 sample->s.ds_index = getData32(sample);
3633 }
3634 else {
3635 uint32_t samplerId = getData32(sample);
3636 sample->s.ds_class = samplerId >> 24;
3637 sample->s.ds_index = samplerId & 0x00ffffff;
3638 }
3639 sf_logf_U32(sample, "sampleSequenceNo", sample->s.samplesGenerated);
3640 sf_logf(sample, "sourceId", printDataSource(sample->s.ds_class, sample->s.ds_index, &buf));
3641
3642 sample->s.meanSkipCount = getData32(sample);
3643 sample->s.samplePool = getData32(sample);
3644 sample->s.dropEvents = getData32(sample);
3645 sf_logf_U32(sample, "meanSkipCount", sample->s.meanSkipCount);
3646 sf_logf_U32(sample, "samplePool", sample->s.samplePool);
3647 sf_logf_U32(sample, "dropEvents", sample->s.dropEvents);
3648 if(expanded) {
3649 sample->s.inputPortFormat = getData32(sample);
3650 sample->s.inputPort = getData32(sample);
3651 sample->s.outputPortFormat = getData32(sample);
3652 sample->s.outputPort = getData32(sample);
3653 }
3654 else {
3655 uint32_t inp, outp;
3656 inp = getData32(sample);
3657 outp = getData32(sample);
3658 sample->s.inputPortFormat = inp >> 30;
3659 sample->s.outputPortFormat = outp >> 30;
3660 sample->s.inputPort = inp & 0x3fffffff;
3661 sample->s.outputPort = outp & 0x3fffffff;
3662 }
3663
3664 sf_logf(sample, "inputPort", printInOutPort(sample->s.inputPort, sample->s.inputPortFormat, &buf));
3665 sf_logf(sample, "outputPort", printInOutPort(sample->s.outputPort, sample->s.outputPortFormat, &buf));
3666
3667 /* clear the CLF record */
3668 sfCLF.valid = NO;
3669 sfCLF.client[0] = '\0';
3670
3671 if(sfConfig.outputFormat == SFLFMT_JSON)
3672 json_start_ar("elements");
3673
3674 num_elements = getData32(sample);
3675 {
3676 uint32_t el;
3677 for(el = 0; el < num_elements; el++) {
3678 uint32_t tag, length;
3679 uint8_t *start;
3680 SFStr buf;
3681 if(sfConfig.outputFormat == SFLFMT_JSON) {
3682 json_start_ob(NULL);
3683 }
3684 tag = sample->s.elementType = getData32(sample);
3685 sf_logf(sample, "flowBlock_tag", printTag(tag, &buf));
3686 length = getData32(sample);
3687 start = (uint8_t *)sample->datap;
3688
3689 switch(tag) {
3690 case SFLFLOW_HEADER: readFlowSample_header(sample); break;
3691 case SFLFLOW_ETHERNET: readFlowSample_ethernet(sample, ""); break;
3692 case SFLFLOW_IPV4: readFlowSample_IPv4(sample, ""); break;
3693 case SFLFLOW_IPV6: readFlowSample_IPv6(sample, ""); break;
3694 case SFLFLOW_MEMCACHE: readFlowSample_memcache(sample); break;
3695 case SFLFLOW_HTTP: readFlowSample_http(sample, tag); break;
3696 case SFLFLOW_HTTP2: readFlowSample_http(sample, tag); break;
3697 case SFLFLOW_APP: readFlowSample_APP(sample); break;
3698 case SFLFLOW_APP_CTXT: readFlowSample_APP_CTXT(sample); break;
3699 case SFLFLOW_APP_ACTOR_INIT: readFlowSample_APP_ACTOR_INIT(sample); break;
3700 case SFLFLOW_APP_ACTOR_TGT: readFlowSample_APP_ACTOR_TGT(sample); break;
3701 case SFLFLOW_EX_SWITCH: readExtendedSwitch(sample); break;
3702 case SFLFLOW_EX_ROUTER: readExtendedRouter(sample); break;
3703 case SFLFLOW_EX_GATEWAY: readExtendedGateway(sample); break;
3704 case SFLFLOW_EX_USER: readExtendedUser(sample); break;
3705 case SFLFLOW_EX_URL: readExtendedUrl(sample); break;
3706 case SFLFLOW_EX_MPLS: readExtendedMpls(sample); break;
3707 case SFLFLOW_EX_NAT: readExtendedNat(sample); break;
3708 case SFLFLOW_EX_NAT_PORT: readExtendedNatPort(sample); break;
3709 case SFLFLOW_EX_MPLS_TUNNEL: readExtendedMplsTunnel(sample); break;
3710 case SFLFLOW_EX_MPLS_VC: readExtendedMplsVC(sample); break;
3711 case SFLFLOW_EX_MPLS_FTN: readExtendedMplsFTN(sample); break;
3712 case SFLFLOW_EX_MPLS_LDP_FEC: readExtendedMplsLDP_FEC(sample); break;
3713 case SFLFLOW_EX_VLAN_TUNNEL: readExtendedVlanTunnel(sample); break;
3714 case SFLFLOW_EX_80211_PAYLOAD: readExtendedWifiPayload(sample); break;
3715 case SFLFLOW_EX_80211_RX: readExtendedWifiRx(sample); break;
3716 case SFLFLOW_EX_80211_TX: readExtendedWifiTx(sample); break;
3717 /* case SFLFLOW_EX_AGGREGATION: readExtendedAggregation(sample); break; */
3718 case SFLFLOW_EX_SOCKET4: readExtendedSocket4(sample); break;
3719 case SFLFLOW_EX_SOCKET6: readExtendedSocket6(sample); break;
3720 case SFLFLOW_EX_PROXYSOCKET4: readExtendedProxySocket4(sample); break;
3721 case SFLFLOW_EX_PROXYSOCKET6: readExtendedProxySocket6(sample); break;
3722 case SFLFLOW_EX_L2_TUNNEL_OUT: readFlowSample_ethernet(sample, "tunnel_l2_out_"); break;
3723 case SFLFLOW_EX_L2_TUNNEL_IN: readFlowSample_ethernet(sample, "tunnel_l2_in_"); break;
3724 case SFLFLOW_EX_IPV4_TUNNEL_OUT: readFlowSample_IPv4(sample, "tunnel_ipv4_out_"); break;
3725 case SFLFLOW_EX_IPV4_TUNNEL_IN: readFlowSample_IPv4(sample, "tunnel_ipv4_in_"); break;
3726 case SFLFLOW_EX_IPV6_TUNNEL_OUT: readFlowSample_IPv6(sample, "tunnel_ipv6_out_"); break;
3727 case SFLFLOW_EX_IPV6_TUNNEL_IN: readFlowSample_IPv6(sample, "tunnel_ipv6_in_"); break;
3728 case SFLFLOW_EX_DECAP_OUT: readExtendedDecap(sample, "out_"); break;
3729 case SFLFLOW_EX_DECAP_IN: readExtendedDecap(sample, "in_"); break;
3730 case SFLFLOW_EX_VNI_OUT: readExtendedVNI(sample, "out_"); break;
3731 case SFLFLOW_EX_VNI_IN: readExtendedVNI(sample, "in_"); break;
3732 case SFLFLOW_EX_TCP_INFO: readExtendedTCPInfo(sample); break;
3733 case SFLFLOW_EX_ENTITIES: readExtendedEntities(sample); break;
3734 default: skipTLVRecord(sample, tag, length, "flow_sample_element"); break;
3735 }
3736 lengthCheck(sample, "flow_sample_element", start, length);
3737 if(sfConfig.outputFormat == SFLFMT_JSON)
3738 json_end_ob();
3739 }
3740 }
3741 lengthCheck(sample, "flow_sample", sampleStart, sampleLength);
3742 if(sfConfig.outputFormat == SFLFMT_JSON)
3743 json_end_ar();
3744
3745 if(sampleFilterOK(sample)) {
3746 switch(sfConfig.outputFormat) {
3747 case SFLFMT_NETFLOW:
3748 /* if we are exporting netflow and we have an IPv4 layer, compose the datagram now */
3749 if(sfConfig.netFlowOutputSocket && sample->s.gotIPV4) sendNetFlowDatagram(sample);
3750 break;
3751 case SFLFMT_PCAP:
3752 /* if we are writing tcpdump format, write the next packet record now */
3753 writePcapPacket(sample);
3754 break;
3755 case SFLFMT_PCAP_DISCARD:
3756 break;
3757 case SFLFMT_LINE:
3758 /* or line-by-line output... */
3759 writeFlowLine(sample);
3760 break;
3761 case SFLFMT_LINE_CUSTOM:
3762 /* or custom line-by-line output... */
3763 writeLineCustom(sample);
3764 break;
3765 case SFLFMT_CLF:
3766 if(sfCLF.valid) {
3767 if(printf("%s %s\n", sfCLF.client, sfCLF.http_log) < 0) {
3768 exit(-48);
3769 }
3770 }
3771 break;
3772 case SFLFMT_FULL:
3773 case SFLFMT_SCRIPT:
3774 case SFLFMT_JSON:
3775 default:
3776 /* if it was full-detail output then it was done as we went along */
3777 break;
3778 }
3779 }
3780 if(sfConfig.outputFormat == SFLFMT_LINE_CUSTOM) {
3781 /* do this here in case sampleFilter rejected sample above */
3782 clearLineCustom(sample, SFSCOPE_SAMPLE);
3783 }
3784 }
3785
3786 /*_________________---------------------------__________________
3787 _________________ discard reason codes __________________
3788 -----------------___________________________------------------
3789 */
3790
3791 #define SFL_DROP(nm,cd) { .name=#nm, .code=cd },
3792 static struct { char *name; int code; } sflow_codes[] = {
3793 #include "sflow_drop.h"
3794 };
3795 #undef SFL_DROP
3796
getReasonCodeName(int reasonCode)3797 static char *getReasonCodeName(int reasonCode) {
3798 int entries = sizeof(sflow_codes) / sizeof(sflow_codes[0]);
3799 for(int ii = 0; ii < entries; ii++) {
3800 if((reasonCode == sflow_codes[ii].code))
3801 return sflow_codes[ii].name;
3802 }
3803 return NULL;
3804 }
3805
3806 /*_________________---------------------------__________________
3807 _________________ readDiscardSample __________________
3808 -----------------___________________________------------------
3809 */
3810
readDiscardSample(SFSample * sample)3811 static void readDiscardSample(SFSample *sample)
3812 {
3813 SFStr buf;
3814 uint32_t num_elements, sampleLength, discardCode;
3815 uint8_t *sampleStart;
3816 char *discardReason;
3817
3818 sf_logf(sample, "sampleType", "DISCARD");
3819 sampleLength = getData32(sample);
3820 sampleStart = (uint8_t *)sample->datap;
3821 sample->s.samplesGenerated = getData32(sample);
3822 sample->s.ds_class = getData32(sample);
3823 sample->s.ds_index = getData32(sample);
3824 sf_logf_U32(sample, "sampleSequenceNo", sample->s.samplesGenerated);
3825 sf_logf(sample, "sourceId", printDataSource(sample->s.ds_class, sample->s.ds_index, &buf));
3826 sample->s.dropEvents = getData32(sample);
3827 sf_logf_U32(sample, "dropEvents", sample->s.dropEvents);
3828 sample->s.inputPort = getData32(sample);
3829 sample->s.outputPort = getData32(sample);
3830 sf_logf(sample, "inputPort", printInOutPort(sample->s.inputPort, sample->s.inputPortFormat, &buf));
3831 sf_logf(sample, "outputPort", printInOutPort(sample->s.outputPort, sample->s.outputPortFormat, &buf));
3832 discardCode = getData32(sample);
3833 sf_logf_U32(sample, "discardCode", discardCode);
3834 discardReason = getReasonCodeName(discardCode);
3835 sf_logf(sample, "discardReason", discardReason ?: "NotFound");
3836
3837 if(sfConfig.outputFormat == SFLFMT_JSON)
3838 json_start_ar("elements");
3839
3840 sf_logf_pushPrefix(sample, "discarded_");
3841
3842 num_elements = getData32(sample);
3843 {
3844 uint32_t el;
3845 for(el = 0; el < num_elements; el++) {
3846 uint32_t tag, length;
3847 uint8_t *start;
3848 SFStr buf;
3849 if(sfConfig.outputFormat == SFLFMT_JSON) {
3850 json_start_ob(NULL);
3851 }
3852 tag = sample->s.elementType = getData32(sample);
3853 sf_logf(sample, "flowBlock_tag", printTag(tag, &buf));
3854 length = getData32(sample);
3855 start = (uint8_t *)sample->datap;
3856
3857 // TODO: separate fn for flow-sample elements?
3858 switch(tag) {
3859 case SFLFLOW_HEADER: readFlowSample_header(sample); break;
3860 case SFLFLOW_EX_FUNCTION: readExtendedFunction(sample); break;
3861 default: skipTLVRecord(sample, tag, length, "discard_sample_element"); break;
3862 }
3863 lengthCheck(sample, "discard_sample_element", start, length);
3864 if(sfConfig.outputFormat == SFLFMT_JSON)
3865 json_end_ob();
3866 }
3867 }
3868
3869 sf_logf_popPrefix(sample);
3870
3871 lengthCheck(sample, "discard_sample", sampleStart, sampleLength);
3872 if(sfConfig.outputFormat == SFLFMT_JSON)
3873 json_end_ar();
3874
3875 if(sampleFilterOK(sample)) {
3876 switch(sfConfig.outputFormat) {
3877 case SFLFMT_NETFLOW:
3878 break;
3879 case SFLFMT_PCAP:
3880 break;
3881 case SFLFMT_PCAP_DISCARD:
3882 /* if we are writing tcpdump format, write the next packet record now */
3883 writePcapPacket(sample);
3884 break;
3885 case SFLFMT_LINE:
3886 /* or line-by-line output... */
3887 /* TODO: writeDiscardLine(sample)? */
3888 break;
3889 case SFLFMT_LINE_CUSTOM:
3890 /* or custom line-by-line output... */
3891 writeLineCustom(sample);
3892 break;
3893 case SFLFMT_CLF:
3894 case SFLFMT_FULL:
3895 case SFLFMT_SCRIPT:
3896 case SFLFMT_JSON:
3897 default:
3898 /* if it was full-detail output then it was done as we went along */
3899 break;
3900 }
3901 }
3902 if(sfConfig.outputFormat == SFLFMT_LINE_CUSTOM) {
3903 /* do this here in case sampleFilter rejected sample above */
3904 clearLineCustom(sample, SFSCOPE_SAMPLE);
3905 }
3906 }
3907
3908 /*_________________---------------------------__________________
3909 _________________ readCounters_generic __________________
3910 -----------------___________________________------------------
3911 */
3912
readCounters_generic(SFSample * sample)3913 static void readCounters_generic(SFSample *sample)
3914 {
3915 /* the first part of the generic counters block is really just more info about the interface. */
3916 sample->s.ifCounters.ifIndex = sf_log_next32(sample, "ifIndex");
3917 sample->s.ifCounters.ifType = sf_log_next32(sample, "networkType");
3918 sample->s.ifCounters.ifSpeed = sf_log_next64(sample, "ifSpeed");
3919 sample->s.ifCounters.ifDirection = sf_log_next32(sample, "ifDirection");
3920 sample->s.ifCounters.ifStatus = sf_log_next32(sample, "ifStatus");
3921 /* the generic counters always come first */
3922 sample->s.ifCounters.ifInOctets = sf_log_next64(sample, "ifInOctets");
3923 sample->s.ifCounters.ifInUcastPkts = sf_log_next32(sample, "ifInUcastPkts");
3924 sample->s.ifCounters.ifInMulticastPkts = sf_log_next32(sample, "ifInMulticastPkts");
3925 sample->s.ifCounters.ifInBroadcastPkts = sf_log_next32(sample, "ifInBroadcastPkts");
3926 sample->s.ifCounters.ifInDiscards = sf_log_next32(sample, "ifInDiscards");
3927 sample->s.ifCounters.ifInErrors = sf_log_next32(sample, "ifInErrors");
3928 sample->s.ifCounters.ifInUnknownProtos = sf_log_next32(sample, "ifInUnknownProtos");
3929 sample->s.ifCounters.ifOutOctets = sf_log_next64(sample, "ifOutOctets");
3930 sample->s.ifCounters.ifOutUcastPkts = sf_log_next32(sample, "ifOutUcastPkts");
3931 sample->s.ifCounters.ifOutMulticastPkts = sf_log_next32(sample, "ifOutMulticastPkts");
3932 sample->s.ifCounters.ifOutBroadcastPkts = sf_log_next32(sample, "ifOutBroadcastPkts");
3933 sample->s.ifCounters.ifOutDiscards = sf_log_next32(sample, "ifOutDiscards");
3934 sample->s.ifCounters.ifOutErrors = sf_log_next32(sample, "ifOutErrors");
3935 sample->s.ifCounters.ifPromiscuousMode = sf_log_next32(sample, "ifPromiscuousMode");
3936 }
3937
3938 /*_________________---------------------------__________________
3939 _________________ readCounters_ethernet __________________
3940 -----------------___________________________------------------
3941 */
3942
readCounters_ethernet(SFSample * sample)3943 static void readCounters_ethernet(SFSample *sample)
3944 {
3945 sf_log_next32(sample, "dot3StatsAlignmentErrors");
3946 sf_log_next32(sample, "dot3StatsFCSErrors");
3947 sf_log_next32(sample, "dot3StatsSingleCollisionFrames");
3948 sf_log_next32(sample, "dot3StatsMultipleCollisionFrames");
3949 sf_log_next32(sample, "dot3StatsSQETestErrors");
3950 sf_log_next32(sample, "dot3StatsDeferredTransmissions");
3951 sf_log_next32(sample, "dot3StatsLateCollisions");
3952 sf_log_next32(sample, "dot3StatsExcessiveCollisions");
3953 sf_log_next32(sample, "dot3StatsInternalMacTransmitErrors");
3954 sf_log_next32(sample, "dot3StatsCarrierSenseErrors");
3955 sf_log_next32(sample, "dot3StatsFrameTooLongs");
3956 sf_log_next32(sample, "dot3StatsInternalMacReceiveErrors");
3957 sf_log_next32(sample, "dot3StatsSymbolErrors");
3958 }
3959
3960
3961 /*_________________---------------------------__________________
3962 _________________ readCounters_tokenring __________________
3963 -----------------___________________________------------------
3964 */
3965
readCounters_tokenring(SFSample * sample)3966 static void readCounters_tokenring(SFSample *sample)
3967 {
3968 sf_log_next32(sample, "dot5StatsLineErrors");
3969 sf_log_next32(sample, "dot5StatsBurstErrors");
3970 sf_log_next32(sample, "dot5StatsACErrors");
3971 sf_log_next32(sample, "dot5StatsAbortTransErrors");
3972 sf_log_next32(sample, "dot5StatsInternalErrors");
3973 sf_log_next32(sample, "dot5StatsLostFrameErrors");
3974 sf_log_next32(sample, "dot5StatsReceiveCongestions");
3975 sf_log_next32(sample, "dot5StatsFrameCopiedErrors");
3976 sf_log_next32(sample, "dot5StatsTokenErrors");
3977 sf_log_next32(sample, "dot5StatsSoftErrors");
3978 sf_log_next32(sample, "dot5StatsHardErrors");
3979 sf_log_next32(sample, "dot5StatsSignalLoss");
3980 sf_log_next32(sample, "dot5StatsTransmitBeacons");
3981 sf_log_next32(sample, "dot5StatsRecoverys");
3982 sf_log_next32(sample, "dot5StatsLobeWires");
3983 sf_log_next32(sample, "dot5StatsRemoves");
3984 sf_log_next32(sample, "dot5StatsSingles");
3985 sf_log_next32(sample, "dot5StatsFreqErrors");
3986 }
3987
3988
3989 /*_________________---------------------------__________________
3990 _________________ readCounters_vg __________________
3991 -----------------___________________________------------------
3992 */
3993
readCounters_vg(SFSample * sample)3994 static void readCounters_vg(SFSample *sample)
3995 {
3996 sf_log_next32(sample, "dot12InHighPriorityFrames");
3997 sf_log_next64(sample, "dot12InHighPriorityOctets");
3998 sf_log_next32(sample, "dot12InNormPriorityFrames");
3999 sf_log_next64(sample, "dot12InNormPriorityOctets");
4000 sf_log_next32(sample, "dot12InIPMErrors");
4001 sf_log_next32(sample, "dot12InOversizeFrameErrors");
4002 sf_log_next32(sample, "dot12InDataErrors");
4003 sf_log_next32(sample, "dot12InNullAddressedFrames");
4004 sf_log_next32(sample, "dot12OutHighPriorityFrames");
4005 sf_log_next64(sample, "dot12OutHighPriorityOctets");
4006 sf_log_next32(sample, "dot12TransitionIntoTrainings");
4007 sf_log_next64(sample, "dot12HCInHighPriorityOctets");
4008 sf_log_next64(sample, "dot12HCInNormPriorityOctets");
4009 sf_log_next64(sample, "dot12HCOutHighPriorityOctets");
4010 }
4011
4012
4013
4014 /*_________________---------------------------__________________
4015 _________________ readCounters_vlan __________________
4016 -----------------___________________________------------------
4017 */
4018
readCounters_vlan(SFSample * sample)4019 static void readCounters_vlan(SFSample *sample)
4020 {
4021 sample->s.in_vlan = getData32(sample);
4022 sf_logf_U32(sample, "in_vlan", sample->s.in_vlan);
4023 sf_log_next64(sample, "octets");
4024 sf_log_next32(sample, "ucastPkts");
4025 sf_log_next32(sample, "multicastPkts");
4026 sf_log_next32(sample, "broadcastPkts");
4027 sf_log_next32(sample, "discards");
4028 }
4029
4030 /*_________________---------------------------__________________
4031 _________________ readCounters_80211 __________________
4032 -----------------___________________________------------------
4033 */
4034
readCounters_80211(SFSample * sample)4035 static void readCounters_80211(SFSample *sample)
4036 {
4037 sf_log_next32(sample, "dot11TransmittedFragmentCount");
4038 sf_log_next32(sample, "dot11MulticastTransmittedFrameCount");
4039 sf_log_next32(sample, "dot11FailedCount");
4040 sf_log_next32(sample, "dot11RetryCount");
4041 sf_log_next32(sample, "dot11MultipleRetryCount");
4042 sf_log_next32(sample, "dot11FrameDuplicateCount");
4043 sf_log_next32(sample, "dot11RTSSuccessCount");
4044 sf_log_next32(sample, "dot11RTSFailureCount");
4045 sf_log_next32(sample, "dot11ACKFailureCount");
4046 sf_log_next32(sample, "dot11ReceivedFragmentCount");
4047 sf_log_next32(sample, "dot11MulticastReceivedFrameCount");
4048 sf_log_next32(sample, "dot11FCSErrorCount");
4049 sf_log_next32(sample, "dot11TransmittedFrameCount");
4050 sf_log_next32(sample, "dot11WEPUndecryptableCount");
4051 sf_log_next32(sample, "dot11QoSDiscardedFragmentCount");
4052 sf_log_next32(sample, "dot11AssociatedStationCount");
4053 sf_log_next32(sample, "dot11QoSCFPollsReceivedCount");
4054 sf_log_next32(sample, "dot11QoSCFPollsUnusedCount");
4055 sf_log_next32(sample, "dot11QoSCFPollsUnusableCount");
4056 sf_log_next32(sample, "dot11QoSCFPollsLostCount");
4057 }
4058
4059 /*_________________---------------------------__________________
4060 _________________ readCounters_processor __________________
4061 -----------------___________________________------------------
4062 */
4063
readCounters_processor(SFSample * sample)4064 static void readCounters_processor(SFSample *sample)
4065 {
4066 sf_log_percentage(sample, "5s_cpu");
4067 sf_log_percentage(sample, "1m_cpu");
4068 sf_log_percentage(sample, "5m_cpu");
4069 sf_log_next64(sample, "total_memory_bytes");
4070 sf_log_next64(sample, "free_memory_bytes");
4071 }
4072
4073 /*_________________---------------------------__________________
4074 _________________ readCounters_radio __________________
4075 -----------------___________________________------------------
4076 */
4077
readCounters_radio(SFSample * sample)4078 static void readCounters_radio(SFSample *sample)
4079 {
4080 sf_log_next32(sample, "radio_elapsed_time");
4081 sf_log_next32(sample, "radio_on_channel_time");
4082 sf_log_next32(sample, "radio_on_channel_busy_time");
4083 }
4084
4085 /*_________________---------------------------__________________
4086 _________________ readCounters_OFPort __________________
4087 -----------------___________________________------------------
4088 */
4089
readCounters_OFPort(SFSample * sample)4090 static void readCounters_OFPort(SFSample *sample)
4091 {
4092 uint64_t dpid = getData64(sample);
4093 char buf[64];
4094 sprintf(buf, "%016"PRIx64"", dpid);
4095 sf_logf(sample, "openflow_datapath_id", buf);
4096 sf_log_next32(sample, "openflow_port");
4097 }
4098
4099 /*_________________---------------------------__________________
4100 _________________ readCounters_portName __________________
4101 -----------------___________________________------------------
4102 */
4103
readCounters_portName(SFSample * sample)4104 static void readCounters_portName(SFSample *sample)
4105 {
4106 char ifname[SFL_MAX_PORTNAME_LEN+1];
4107 if(getString(sample, ifname, SFL_MAX_PORTNAME_LEN) > 0) {
4108 sf_logf(sample, "ifName", ifname);
4109 }
4110 }
4111
4112 /*_________________---------------------------__________________
4113 _________________ readCounters_OVSDP __________________
4114 -----------------___________________________------------------
4115 */
4116
readCounters_OVSDP(SFSample * sample)4117 static void readCounters_OVSDP(SFSample *sample)
4118 {
4119 sf_log_next32(sample, "OVS_dp_hits");
4120 sf_log_next32(sample, "OVS_dp_misses");
4121 sf_log_next32(sample, "OVS_dp_lost");
4122 sf_log_next32(sample, "OVS_dp_mask_hits");
4123 sf_log_next32(sample, "OVS_dp_flows");
4124 sf_log_next32(sample, "OVS_dp_masks");
4125 }
4126
4127 /*_________________---------------------------__________________
4128 _________________ readCounters_host_hid __________________
4129 -----------------___________________________------------------
4130 */
4131
readCounters_host_hid(SFSample * sample)4132 static void readCounters_host_hid(SFSample *sample)
4133 {
4134 uint32_t i;
4135 uint8_t *uuid;
4136 char hostname[SFL_MAX_HOSTNAME_LEN+1];
4137 char os_release[SFL_MAX_OSRELEASE_LEN+1];
4138 if(getString(sample, hostname, SFL_MAX_HOSTNAME_LEN) > 0) {
4139 sf_logf(sample, "hostname", hostname);
4140 }
4141 SFStr uuidstr;
4142 SFStr_init(&uuidstr);
4143 uuid = (uint8_t *)sample->datap;
4144 SFStr_append_UUID(&uuidstr, uuid);
4145 sf_logf(sample, "UUID", SFStr_str(&uuidstr));
4146 skipBytes(sample, 16);
4147 sf_log_next32(sample, "machine_type");
4148 sf_log_next32(sample, "os_name");
4149 if(getString(sample, os_release, SFL_MAX_OSRELEASE_LEN) > 0) {
4150 sf_logf(sample, "os_release", os_release);
4151 }
4152 }
4153
4154 /*_________________---------------------------__________________
4155 _________________ readCounters_adaptors __________________
4156 -----------------___________________________------------------
4157 */
4158
readCounters_adaptors(SFSample * sample)4159 static void readCounters_adaptors(SFSample *sample)
4160 {
4161 uint8_t *mac;
4162 uint32_t i, j, ifindex, num_macs, num_adaptors = getData32(sample);
4163 if(sfConfig.outputFormat == SFLFMT_JSON) {
4164 /* JSON - print as array of adaptors with nested arrays of MACs */
4165 json_start_ar("adaptor_list");
4166 for(i = 0; i < num_adaptors; i++) {
4167 ifindex = getData32(sample);
4168 json_start_ob(NULL);
4169 sf_logf_U32(sample, "ifIndex", ifindex);
4170 num_macs = getData32(sample);
4171 sf_logf_U32(sample, "MACs", num_macs);
4172 json_start_ar("mac_list");
4173 for(j = 0; j < num_macs; j++) {
4174 if(j > 0)
4175 printf(",");
4176 mac = (uint8_t *)sample->datap;
4177 skipBytes(sample, 8);
4178 SFStr macstr;
4179 SFStr_init(&macstr);
4180 SFStr_append_mac(&macstr, mac);
4181 json_indent();
4182 printf("\"%s\" ", SFStr_str(&macstr));
4183 }
4184 json_end_ar(); /* end mac_list */
4185 json_end_ob(); /* end adaptor */
4186 }
4187 json_end_ar(); /* end adaptor_list */
4188 }
4189 else {
4190 /* print as flat list of fields, with adaptor and mac index numbers */
4191 for(i = 0; i < num_adaptors; i++) {
4192 ifindex = getData32(sample);
4193 char prefix[32];
4194 sprintf(prefix, "adaptor_%u_", i);
4195 sf_logf_U32_formatted(sample, prefix, "ifIndex", "%u", ifindex);
4196 num_macs = getData32(sample);
4197 sf_logf_U32_formatted(sample, prefix, "MACs", "%u", num_macs);
4198 for(j = 0; j < num_macs; j++) {
4199 mac = (uint8_t *)sample->datap;
4200 skipBytes(sample, 8);
4201 SFStr macstr;
4202 SFStr_init(&macstr);
4203 SFStr_append_mac(&macstr, mac);
4204 char fieldName[32];
4205 sprintf(fieldName, "MAC_%u", j);
4206 sf_logf_pushPrefix(sample, prefix);
4207 sf_logf(sample, fieldName, SFStr_str(&macstr));
4208 sf_logf_popPrefix(sample);
4209 }
4210 }
4211 }
4212 }
4213
4214 /*_________________----------------------------__________________
4215 _________________ readCounters_host_parent __________________
4216 -----------------____________________________------------------
4217 */
4218
readCounters_host_parent(SFSample * sample)4219 static void readCounters_host_parent(SFSample *sample)
4220 {
4221 sf_log_next32(sample, "parent_dsClass");
4222 sf_log_next32(sample, "parent_dsIndex");
4223 }
4224
4225 /*_________________---------------------------__________________
4226 _________________ readCounters_host_cpu __________________
4227 -----------------___________________________------------------
4228 */
4229
readCounters_host_cpu(SFSample * sample,uint32_t length)4230 static void readCounters_host_cpu(SFSample *sample, uint32_t length)
4231 {
4232 sf_log_nextFloat(sample, "cpu_load_one");
4233 sf_log_nextFloat(sample, "cpu_load_five");
4234 sf_log_nextFloat(sample, "cpu_load_fifteen");
4235 sf_log_next32(sample, "cpu_proc_run");
4236 sf_log_next32(sample, "cpu_proc_total");
4237 sf_log_next32(sample, "cpu_num");
4238 sf_log_next32(sample, "cpu_speed");
4239 sf_log_next32(sample, "cpu_uptime");
4240 sf_log_next32(sample, "cpu_user");
4241 sf_log_next32(sample, "cpu_nice");
4242 sf_log_next32(sample, "cpu_system");
4243 sf_log_next32(sample, "cpu_idle");
4244 sf_log_next32(sample, "cpu_wio");
4245 sf_log_next32(sample, "cpuintr");
4246 sf_log_next32(sample, "cpu_sintr");
4247 sf_log_next32(sample, "cpuinterrupts");
4248 sf_log_next32(sample, "cpu_contexts");
4249 if(length > 68) {
4250 /* these three fields were added in December 2014 */
4251 sf_log_next32(sample, "cpu_steal");
4252 sf_log_next32(sample, "cpu_guest");
4253 sf_log_next32(sample, "cpu_guest_nice");
4254 }
4255 }
4256
4257 /*_________________---------------------------__________________
4258 _________________ readCounters_host_mem __________________
4259 -----------------___________________________------------------
4260 */
4261
readCounters_host_mem(SFSample * sample)4262 static void readCounters_host_mem(SFSample *sample)
4263 {
4264 sf_log_next64(sample, "mem_total");
4265 sf_log_next64(sample, "mem_free");
4266 sf_log_next64(sample, "mem_shared");
4267 sf_log_next64(sample, "mem_buffers");
4268 sf_log_next64(sample, "mem_cached");
4269 sf_log_next64(sample, "swap_total");
4270 sf_log_next64(sample, "swap_free");
4271 sf_log_next32(sample, "page_in");
4272 sf_log_next32(sample, "page_out");
4273 sf_log_next32(sample, "swap_in");
4274 sf_log_next32(sample, "swap_out");
4275 }
4276
4277 /*_________________---------------------------__________________
4278 _________________ readCounters_host_dsk __________________
4279 -----------------___________________________------------------
4280 */
4281
readCounters_host_dsk(SFSample * sample)4282 static void readCounters_host_dsk(SFSample *sample)
4283 {
4284 sf_log_next64(sample, "disk_total");
4285 sf_log_next64(sample, "disk_free");
4286 sf_log_percentage(sample, "disk_partition_max_used");
4287 sf_log_next32(sample, "disk_reads");
4288 sf_log_next64(sample, "disk_bytes_read");
4289 sf_log_next32(sample, "disk_read_time");
4290 sf_log_next32(sample, "disk_writes");
4291 sf_log_next64(sample, "disk_bytes_written");
4292 sf_log_next32(sample, "disk_write_time");
4293 }
4294
4295 /*_________________---------------------------__________________
4296 _________________ readCounters_host_nio __________________
4297 -----------------___________________________------------------
4298 */
4299
readCounters_host_nio(SFSample * sample)4300 static void readCounters_host_nio(SFSample *sample)
4301 {
4302 sf_log_next64(sample, "nio_bytes_in");
4303 sf_log_next32(sample, "nio_pkts_in");
4304 sf_log_next32(sample, "nio_errs_in");
4305 sf_log_next32(sample, "nio_drops_in");
4306 sf_log_next64(sample, "nio_bytes_out");
4307 sf_log_next32(sample, "nio_pkts_out");
4308 sf_log_next32(sample, "nio_errs_out");
4309 sf_log_next32(sample, "nio_drops_out");
4310 }
4311
4312 /*_________________---------------------------__________________
4313 _________________ readCounters_host_ip __________________
4314 -----------------___________________________------------------
4315 */
4316
readCounters_host_ip(SFSample * sample)4317 static void readCounters_host_ip(SFSample *sample)
4318 {
4319 sf_log_next32(sample, "ipForwarding");
4320 sf_log_next32(sample, "ipDefaultTTL");
4321 sf_log_next32(sample, "ipInReceives");
4322 sf_log_next32(sample, "ipInHdrErrors");
4323 sf_log_next32(sample, "ipInAddrErrors");
4324 sf_log_next32(sample, "ipForwDatagrams");
4325 sf_log_next32(sample, "ipInUnknownProtos");
4326 sf_log_next32(sample, "ipInDiscards");
4327 sf_log_next32(sample, "ipInDelivers");
4328 sf_log_next32(sample, "ipOutRequests");
4329 sf_log_next32(sample, "ipOutDiscards");
4330 sf_log_next32(sample, "ipOutNoRoutes");
4331 sf_log_next32(sample, "ipReasmTimeout");
4332 sf_log_next32(sample, "ipReasmReqds");
4333 sf_log_next32(sample, "ipReasmOKs");
4334 sf_log_next32(sample, "ipReasmFails");
4335 sf_log_next32(sample, "ipFragOKs");
4336 sf_log_next32(sample, "ipFragFails");
4337 sf_log_next32(sample, "ipFragCreates");
4338 }
4339
4340 /*_________________---------------------------__________________
4341 _________________ readCounters_host_icmp __________________
4342 -----------------___________________________------------------
4343 */
4344
readCounters_host_icmp(SFSample * sample)4345 static void readCounters_host_icmp(SFSample *sample)
4346 {
4347 sf_log_next32(sample, "icmpInMsgs");
4348 sf_log_next32(sample, "icmpInErrors");
4349 sf_log_next32(sample, "icmpInDestUnreachs");
4350 sf_log_next32(sample, "icmpInTimeExcds");
4351 sf_log_next32(sample, "icmpInParamProbs");
4352 sf_log_next32(sample, "icmpInSrcQuenchs");
4353 sf_log_next32(sample, "icmpInRedirects");
4354 sf_log_next32(sample, "icmpInEchos");
4355 sf_log_next32(sample, "icmpInEchoReps");
4356 sf_log_next32(sample, "icmpInTimestamps");
4357 sf_log_next32(sample, "icmpInAddrMasks");
4358 sf_log_next32(sample, "icmpInAddrMaskReps");
4359 sf_log_next32(sample, "icmpOutMsgs");
4360 sf_log_next32(sample, "icmpOutErrors");
4361 sf_log_next32(sample, "icmpOutDestUnreachs");
4362 sf_log_next32(sample, "icmpOutTimeExcds");
4363 sf_log_next32(sample, "icmpOutParamProbs");
4364 sf_log_next32(sample, "icmpOutSrcQuenchs");
4365 sf_log_next32(sample, "icmpOutRedirects");
4366 sf_log_next32(sample, "icmpOutEchos");
4367 sf_log_next32(sample, "icmpOutEchoReps");
4368 sf_log_next32(sample, "icmpOutTimestamps");
4369 sf_log_next32(sample, "icmpOutTimestampReps");
4370 sf_log_next32(sample, "icmpOutAddrMasks");
4371 sf_log_next32(sample, "icmpOutAddrMaskReps");
4372 }
4373
4374 /*_________________---------------------------__________________
4375 _________________ readCounters_host_tcp __________________
4376 -----------------___________________________------------------
4377 */
4378
readCounters_host_tcp(SFSample * sample)4379 static void readCounters_host_tcp(SFSample *sample)
4380 {
4381 sf_log_next32(sample, "tcpRtoAlgorithm");
4382 sf_log_next32(sample, "tcpRtoMin");
4383 sf_log_next32(sample, "tcpRtoMax");
4384 sf_log_next32(sample, "tcpMaxConn");
4385 sf_log_next32(sample, "tcpActiveOpens");
4386 sf_log_next32(sample, "tcpPassiveOpens");
4387 sf_log_next32(sample, "tcpAttemptFails");
4388 sf_log_next32(sample, "tcpEstabResets");
4389 sf_log_next32(sample, "tcpCurrEstab");
4390 sf_log_next32(sample, "tcpInSegs");
4391 sf_log_next32(sample, "tcpOutSegs");
4392 sf_log_next32(sample, "tcpRetransSegs");
4393 sf_log_next32(sample, "tcpInErrs");
4394 sf_log_next32(sample, "tcpOutRsts");
4395 sf_log_next32(sample, "tcpInCsumErrors");
4396 }
4397
4398 /*_________________---------------------------__________________
4399 _________________ readCounters_host_udp __________________
4400 -----------------___________________________------------------
4401 */
4402
readCounters_host_udp(SFSample * sample)4403 static void readCounters_host_udp(SFSample *sample)
4404 {
4405 sf_log_next32(sample, "udpInDatagrams");
4406 sf_log_next32(sample, "udpNoPorts");
4407 sf_log_next32(sample, "udpInErrors");
4408 sf_log_next32(sample, "udpOutDatagrams");
4409 sf_log_next32(sample, "udpRcvbufErrors");
4410 sf_log_next32(sample, "udpSndbufErrors");
4411 sf_log_next32(sample, "udpInCsumErrors");
4412 }
4413
4414 /*_________________-----------------------------__________________
4415 _________________ readCounters_host_vnode __________________
4416 -----------------_____________________________------------------
4417 */
4418
readCounters_host_vnode(SFSample * sample)4419 static void readCounters_host_vnode(SFSample *sample)
4420 {
4421 sf_log_next32(sample, "vnode_mhz");
4422 sf_log_next32(sample, "vnode_cpus");
4423 sf_log_next64(sample, "vnode_memory");
4424 sf_log_next64(sample, "vnode_memory_free");
4425 sf_log_next32(sample, "vnode_num_domains");
4426 }
4427
4428 /*_________________----------------------------__________________
4429 _________________ readCounters_host_vcpu __________________
4430 -----------------____________________________------------------
4431 */
4432
readCounters_host_vcpu(SFSample * sample)4433 static void readCounters_host_vcpu(SFSample *sample)
4434 {
4435 sf_log_next32(sample, "vcpu_state");
4436 sf_log_next32(sample, "vcpu_cpu_mS");
4437 sf_log_next32(sample, "vcpu_cpuCount");
4438 }
4439
4440 /*_________________----------------------------__________________
4441 _________________ readCounters_host_vmem __________________
4442 -----------------____________________________------------------
4443 */
4444
readCounters_host_vmem(SFSample * sample)4445 static void readCounters_host_vmem(SFSample *sample)
4446 {
4447 sf_log_next64(sample, "vmem_memory");
4448 sf_log_next64(sample, "vmem_maxMemory");
4449 }
4450
4451 /*_________________----------------------------__________________
4452 _________________ readCounters_host_vdsk __________________
4453 -----------------____________________________------------------
4454 */
4455
readCounters_host_vdsk(SFSample * sample)4456 static void readCounters_host_vdsk(SFSample *sample)
4457 {
4458 sf_log_next64(sample, "vdsk_capacity");
4459 sf_log_next64(sample, "vdsk_allocation");
4460 sf_log_next64(sample, "vdsk_available");
4461 sf_log_next32(sample, "vdsk_rd_req");
4462 sf_log_next64(sample, "vdsk_rd_bytes");
4463 sf_log_next32(sample, "vdsk_wr_req");
4464 sf_log_next64(sample, "vdsk_wr_bytes");
4465 sf_log_next32(sample, "vdsk_errs");
4466 }
4467
4468 /*_________________----------------------------__________________
4469 _________________ readCounters_host_vnio __________________
4470 -----------------____________________________------------------
4471 */
4472
readCounters_host_vnio(SFSample * sample)4473 static void readCounters_host_vnio(SFSample *sample)
4474 {
4475 sf_log_next64(sample, "vnio_bytes_in");
4476 sf_log_next32(sample, "vnio_pkts_in");
4477 sf_log_next32(sample, "vnio_errs_in");
4478 sf_log_next32(sample, "vnio_drops_in");
4479 sf_log_next64(sample, "vnio_bytes_out");
4480 sf_log_next32(sample, "vnio_pkts_out");
4481 sf_log_next32(sample, "vnio_errs_out");
4482 sf_log_next32(sample, "vnio_drops_out");
4483 }
4484
4485 /*_________________------------------------------__________________
4486 _________________ readCounters_host_gpu_nvml __________________
4487 -----------------______________________________------------------
4488 */
4489
readCounters_host_gpu_nvml(SFSample * sample)4490 static void readCounters_host_gpu_nvml(SFSample *sample)
4491 {
4492 sf_log_next32(sample, "nvml_device_count");
4493 sf_log_next32(sample, "nvml_processes");
4494 sf_log_next32(sample, "nvml_gpu_mS");
4495 sf_log_next32(sample, "nvml_mem_mS");
4496 sf_log_next64(sample, "nvml_mem_bytes_total");
4497 sf_log_next64(sample, "nvml_mem_bytes_free");
4498 sf_log_next32(sample, "nvml_ecc_errors");
4499 sf_log_next32(sample, "nvml_energy_mJ");
4500 sf_log_next32(sample, "nvml_temperature_C");
4501 sf_log_next32(sample, "nvml_fan_speed_pc");
4502 }
4503
4504 /*_________________------------------------------__________________
4505 _________________ readCounters_bcm_tables __________________
4506 -----------------______________________________------------------
4507 */
4508
readCounters_bcm_tables(SFSample * sample)4509 static void readCounters_bcm_tables(SFSample *sample)
4510 {
4511 sf_log_next32(sample, "bcm_asic_host_entries");
4512 sf_log_next32(sample, "bcm_host_entries_max");
4513 sf_log_next32(sample, "bcm_ipv4_entries");
4514 sf_log_next32(sample, "bcm_ipv4_entries_max");
4515 sf_log_next32(sample, "bcm_ipv6_entries");
4516 sf_log_next32(sample, "bcm_ipv6_entries_max");
4517 sf_log_next32(sample, "bcm_ipv4_ipv6_entries");
4518 sf_log_next32(sample, "bcm_ipv4_ipv6_entries_max");
4519 sf_log_next32(sample, "bcm_long_ipv6_entries");
4520 sf_log_next32(sample, "bcm_long_ipv6_entries_max");
4521 sf_log_next32(sample, "bcm_total_routes");
4522 sf_log_next32(sample, "bcm_total_routes_max");
4523 sf_log_next32(sample, "bcm_ecmp_nexthops");
4524 sf_log_next32(sample, "bcm_ecmp_nexthops_max");
4525 sf_log_next32(sample, "bcm_mac_entries");
4526 sf_log_next32(sample, "bcm_mac_entries_max");
4527 sf_log_next32(sample, "bcm_ipv4_neighbors");
4528 sf_log_next32(sample, "bcm_ipv6_neighbors");
4529 sf_log_next32(sample, "bcm_ipv4_routes");
4530 sf_log_next32(sample, "bcm_ipv6_routes");
4531 sf_log_next32(sample, "bcm_acl_ingress_entries");
4532 sf_log_next32(sample, "bcm_acl_ingress_entries_max");
4533 sf_log_next32(sample, "bcm_acl_ingress_counters");
4534 sf_log_next32(sample, "bcm_acl_ingress_counters_max");
4535 sf_log_next32(sample, "bcm_acl_ingress_meters");
4536 sf_log_next32(sample, "bcm_acl_ingress_meters_max");
4537 sf_log_next32(sample, "bcm_acl_ingress_slices");
4538 sf_log_next32(sample, "bcm_acl_ingress_slices_max");
4539 sf_log_next32(sample, "bcm_acl_egress_entries");
4540 sf_log_next32(sample, "bcm_acl_egress_entries_max");
4541 sf_log_next32(sample, "bcm_acl_egress_counters");
4542 sf_log_next32(sample, "bcm_acl_egress_counters_max");
4543 sf_log_next32(sample, "bcm_acl_egress_meters");
4544 sf_log_next32(sample, "bcm_acl_egress_meters_max");
4545 sf_log_next32(sample, "bcm_acl_egress_slices");
4546 sf_log_next32(sample, "bcm_acl_egress_slices_max");
4547 }
4548
4549 /*_________________----------------------------__________________
4550 _________________ readCounters_memcache __________________
4551 -----------------____________________________------------------
4552 for structure 2200 (deprecated)
4553 */
4554
readCounters_memcache(SFSample * sample)4555 static void readCounters_memcache(SFSample *sample)
4556 {
4557 sf_log_next32(sample, "memcache_uptime");
4558 sf_log_next32(sample, "memcache_rusage_user");
4559 sf_log_next32(sample, "memcache_rusage_system");
4560 sf_log_next32(sample, "memcache_curr_connections");
4561 sf_log_next32(sample, "memcache_total_connections");
4562 sf_log_next32(sample, "memcache_connection_structures");
4563 sf_log_next32(sample, "memcache_cmd_get");
4564 sf_log_next32(sample, "memcache_cmd_set");
4565 sf_log_next32(sample, "memcache_cmd_flush");
4566 sf_log_next32(sample, "memcache_get_hits");
4567 sf_log_next32(sample, "memcache_get_misses");
4568 sf_log_next32(sample, "memcache_delete_misses");
4569 sf_log_next32(sample, "memcache_delete_hits");
4570 sf_log_next32(sample, "memcache_incr_misses");
4571 sf_log_next32(sample, "memcache_incr_hits");
4572 sf_log_next32(sample, "memcache_decr_misses");
4573 sf_log_next32(sample, "memcache_decr_hits");
4574 sf_log_next32(sample, "memcache_cas_misses");
4575 sf_log_next32(sample, "memcache_cas_hits");
4576 sf_log_next32(sample, "memcache_cas_badval");
4577 sf_log_next32(sample, "memcache_auth_cmds");
4578 sf_log_next32(sample, "memcache_auth_errors");
4579 sf_log_next64(sample, "memcache_bytes_read");
4580 sf_log_next64(sample, "memcache_bytes_written");
4581 sf_log_next32(sample, "memcache_limit_maxbytes");
4582 sf_log_next32(sample, "memcache_accepting_conns");
4583 sf_log_next32(sample, "memcache_listen_disabled_num");
4584 sf_log_next32(sample, "memcache_threads");
4585 sf_log_next32(sample, "memcache_conn_yields");
4586 sf_log_next64(sample, "memcache_bytes");
4587 sf_log_next32(sample, "memcache_curr_items");
4588 sf_log_next32(sample, "memcache_total_items");
4589 sf_log_next32(sample, "memcache_evictions");
4590 }
4591
4592 /*_________________----------------------------__________________
4593 _________________ readCounters_memcache2 __________________
4594 -----------------____________________________------------------
4595 for structure 2204
4596 */
4597
readCounters_memcache2(SFSample * sample)4598 static void readCounters_memcache2(SFSample *sample)
4599 {
4600 sf_log_next32(sample, "memcache_cmd_set");
4601 sf_log_next32(sample, "memcache_cmd_touch");
4602 sf_log_next32(sample, "memcache_cmd_flush");
4603 sf_log_next32(sample, "memcache_get_hits");
4604 sf_log_next32(sample, "memcache_get_misses");
4605 sf_log_next32(sample, "memcache_delete_hits");
4606 sf_log_next32(sample, "memcache_delete_misses");
4607 sf_log_next32(sample, "memcache_incr_hits");
4608 sf_log_next32(sample, "memcache_incr_misses");
4609 sf_log_next32(sample, "memcache_decr_hits");
4610 sf_log_next32(sample, "memcache_decr_misses");
4611 sf_log_next32(sample, "memcache_cas_hits");
4612 sf_log_next32(sample, "memcache_cas_misses");
4613 sf_log_next32(sample, "memcache_cas_badval");
4614 sf_log_next32(sample, "memcache_auth_cmds");
4615 sf_log_next32(sample, "memcache_auth_errors");
4616 sf_log_next32(sample, "memcache_threads");
4617 sf_log_next32(sample, "memcache_conn_yields");
4618 sf_log_next32(sample, "memcache_listen_disabled_num");
4619 sf_log_next32(sample, "memcache_curr_connections");
4620 sf_log_next32(sample, "memcache_rejected_connections");
4621 sf_log_next32(sample, "memcache_total_connections");
4622 sf_log_next32(sample, "memcache_connection_structures");
4623 sf_log_next32(sample, "memcache_evictions");
4624 sf_log_next32(sample, "memcache_reclaimed");
4625 sf_log_next32(sample, "memcache_curr_items");
4626 sf_log_next32(sample, "memcache_total_items");
4627 sf_log_next64(sample, "memcache_bytes_read");
4628 sf_log_next64(sample, "memcache_bytes_written");
4629 sf_log_next64(sample, "memcache_bytes");
4630 sf_log_next64(sample, "memcache_limit_maxbytes");
4631 }
4632
4633 /*_________________----------------------------__________________
4634 _________________ readCounters_http __________________
4635 -----------------____________________________------------------
4636 */
4637
readCounters_http(SFSample * sample)4638 static void readCounters_http(SFSample *sample)
4639 {
4640 sf_log_next32(sample, "http_method_option_count");
4641 sf_log_next32(sample, "http_method_get_count");
4642 sf_log_next32(sample, "http_method_head_count");
4643 sf_log_next32(sample, "http_method_post_count");
4644 sf_log_next32(sample, "http_method_put_count");
4645 sf_log_next32(sample, "http_method_delete_count");
4646 sf_log_next32(sample, "http_method_trace_count");
4647 sf_log_next32(sample, "http_methd_connect_count");
4648 sf_log_next32(sample, "http_method_other_count");
4649 sf_log_next32(sample, "http_status_1XX_count");
4650 sf_log_next32(sample, "http_status_2XX_count");
4651 sf_log_next32(sample, "http_status_3XX_count");
4652 sf_log_next32(sample, "http_status_4XX_count");
4653 sf_log_next32(sample, "http_status_5XX_count");
4654 sf_log_next32(sample, "http_status_other_count");
4655 }
4656
4657 /*_________________----------------------------__________________
4658 _________________ readCounters_JVM __________________
4659 -----------------____________________________------------------
4660 */
4661
readCounters_JVM(SFSample * sample)4662 static void readCounters_JVM(SFSample *sample)
4663 {
4664 char vm_name[SFLJVM_MAX_VMNAME_LEN];
4665 char vendor[SFLJVM_MAX_VENDOR_LEN];
4666 char version[SFLJVM_MAX_VERSION_LEN];
4667 if(getString(sample, vm_name, SFLJVM_MAX_VMNAME_LEN) > 0) {
4668 sf_logf(sample, "jvm_name", vm_name);
4669 }
4670 if(getString(sample, vendor, SFLJVM_MAX_VENDOR_LEN) > 0) {
4671 sf_logf(sample, "jvm_vendor", vendor);
4672 }
4673 if(getString(sample, version, SFLJVM_MAX_VERSION_LEN) > 0) {
4674 sf_logf(sample, "jvm_version", version);
4675 }
4676 }
4677
4678 /*_________________----------------------------__________________
4679 _________________ readCounters_JMX __________________
4680 -----------------____________________________------------------
4681 */
4682
readCounters_JMX(SFSample * sample,uint32_t length)4683 static void readCounters_JMX(SFSample *sample, uint32_t length)
4684 {
4685 sf_log_next64(sample, "heap_mem_initial");
4686 sf_log_next64(sample, "heap_mem_used");
4687 sf_log_next64(sample, "heap_mem_committed");
4688 sf_log_next64(sample, "heap_mem_max");
4689 sf_log_next64(sample, "non_heap_mem_initial");
4690 sf_log_next64(sample, "non_heap_mem_used");
4691 sf_log_next64(sample, "non_heap_mem_committed");
4692 sf_log_next64(sample, "non_heap_mem_max");
4693 sf_log_next32(sample, "gc_count");
4694 sf_log_next32(sample, "gc_mS");
4695 sf_log_next32(sample, "classes_loaded");
4696 sf_log_next32(sample, "classes_total");
4697 sf_log_next32(sample, "classes_unloaded");
4698 sf_log_next32(sample, "compilation_mS");
4699 sf_log_next32(sample, "threads_live");
4700 sf_log_next32(sample, "threads_daemon");
4701 sf_log_next32(sample, "threads_started");
4702 if(length > 100) {
4703 sf_log_next32(sample, "fds_open");
4704 sf_log_next32(sample, "fds_max");
4705 }
4706 }
4707
4708 /*_________________----------------------------__________________
4709 _________________ readCounters_APP __________________
4710 -----------------____________________________------------------
4711 */
4712
readCounters_APP(SFSample * sample)4713 static void readCounters_APP(SFSample *sample)
4714 {
4715 char application[SFLAPP_MAX_APPLICATION_LEN];
4716 if(getString(sample, application, SFLAPP_MAX_APPLICATION_LEN) > 0) {
4717 sf_logf(sample, "application", application);
4718 }
4719 sf_log_next32(sample, "status_OK");
4720 sf_log_next32(sample, "errors_OTHER");
4721 sf_log_next32(sample, "errors_TIMEOUT");
4722 sf_log_next32(sample, "errors_INTERNAL_ERROR");
4723 sf_log_next32(sample, "errors_BAD_REQUEST");
4724 sf_log_next32(sample, "errors_FORBIDDEN");
4725 sf_log_next32(sample, "errors_TOO_LARGE");
4726 sf_log_next32(sample, "errors_NOT_IMPLEMENTED");
4727 sf_log_next32(sample, "errors_NOT_FOUND");
4728 sf_log_next32(sample, "errors_UNAVAILABLE");
4729 sf_log_next32(sample, "errors_UNAUTHORIZED");
4730 }
4731
4732 /*_________________----------------------------__________________
4733 _________________ readCounters_APP_RESOURCE __________________
4734 -----------------____________________________------------------
4735 */
4736
readCounters_APP_RESOURCE(SFSample * sample)4737 static void readCounters_APP_RESOURCE(SFSample *sample)
4738 {
4739 sf_log_next32(sample, "user_time");
4740 sf_log_next32(sample, "system_time");
4741 sf_log_next64(sample, "memory_used");
4742 sf_log_next64(sample, "memory_max");
4743 sf_log_next32(sample, "files_open");
4744 sf_log_next32(sample, "files_max");
4745 sf_log_next32(sample, "connections_open");
4746 sf_log_next32(sample, "connections_max");
4747 }
4748
4749 /*_________________----------------------------__________________
4750 _________________ readCounters_APP_WORKERS __________________
4751 -----------------____________________________------------------
4752 */
4753
readCounters_APP_WORKERS(SFSample * sample)4754 static void readCounters_APP_WORKERS(SFSample *sample)
4755 {
4756 sf_log_next32(sample, "workers_active");
4757 sf_log_next32(sample, "workers_idle");
4758 sf_log_next32(sample, "workers_max");
4759 sf_log_next32(sample, "requests_delayed");
4760 sf_log_next32(sample, "requests_dropped");
4761 }
4762
4763 /*_________________----------------------------__________________
4764 _________________ readCounters_VDI __________________
4765 -----------------____________________________------------------
4766 */
4767
readCounters_VDI(SFSample * sample)4768 static void readCounters_VDI(SFSample *sample)
4769 {
4770 sf_log_next32(sample, "vdi_sessions_current");
4771 sf_log_next32(sample, "vdi_sessions_total");
4772 sf_log_next32(sample, "vdi_sessions_duration");
4773 sf_log_next32(sample, "vdi_rx_bytes");
4774 sf_log_next32(sample, "vdi_tx_bytes");
4775 sf_log_next32(sample, "vdi_rx_packets");
4776 sf_log_next32(sample, "vdi_tx_packets");
4777 sf_log_next32(sample, "vdi_rx_packets_lost");
4778 sf_log_next32(sample, "vdi_tx_packets_lost");
4779 sf_log_next32(sample, "vdi_rtt_min_ms");
4780 sf_log_next32(sample, "vdi_rtt_max_ms");
4781 sf_log_next32(sample, "vdi_rtt_avg_ms");
4782 sf_log_next32(sample, "vdi_audio_rx_bytes");
4783 sf_log_next32(sample, "vdi_audio_tx_bytes");
4784 sf_log_next32(sample, "vdi_audio_tx_limit");
4785 sf_log_next32(sample, "vdi_img_rx_bytes");
4786 sf_log_next32(sample, "vdi_img_tx_bytes");
4787 sf_log_next32(sample, "vdi_img_frames");
4788 sf_log_next32(sample, "vdi_img_qual_min");
4789 sf_log_next32(sample, "vdi_img_qual_max");
4790 sf_log_next32(sample, "vdi_img_qual_avg");
4791 sf_log_next32(sample, "vdi_usb_rx_bytes");
4792 sf_log_next32(sample, "vdi_usb_tx_bytes");
4793 }
4794
4795 /*_________________------------------------------__________________
4796 _________________ readCounters_LACP __________________
4797 -----------------______________________________------------------
4798 */
4799
readCounters_LACP(SFSample * sample)4800 static void readCounters_LACP(SFSample *sample)
4801 {
4802 SFLLACP_portState portState;
4803 sf_log_nextMAC(sample, "actorSystemID");
4804 sf_log_nextMAC(sample, "partnerSystemID");
4805 sf_log_next32(sample, "attachedAggID");
4806 portState.all = getData32_nobswap(sample);
4807 sf_logf_U32(sample, "actorAdminPortState", portState.v.actorAdmin);
4808 sf_logf_U32(sample, "actorOperPortState", portState.v.actorOper);
4809 sf_logf_U32(sample, "partnerAdminPortState", portState.v.partnerAdmin);
4810 sf_logf_U32(sample, "partnerOperPortState", portState.v.partnerOper);
4811 sf_log_next32(sample, "LACPDUsRx");
4812 sf_log_next32(sample, "markerPDUsRx");
4813 sf_log_next32(sample, "markerResponsePDUsRx");
4814 sf_log_next32(sample, "unknownRx");
4815 sf_log_next32(sample, "illegalRx");
4816 sf_log_next32(sample, "LACPDUsTx");
4817 sf_log_next32(sample, "markerPDUsTx");
4818 sf_log_next32(sample, "markerResponsePDUsTx");
4819 }
4820
4821 /*_________________----------------------------__________________
4822 _________________ readCounters_SFP __________________
4823 -----------------____________________________------------------
4824 */
4825
sf_logf_SFP(SFSample * sample,char * field,uint32_t lane,uint32_t val32)4826 static void sf_logf_SFP(SFSample *sample, char *field, uint32_t lane, uint32_t val32)
4827 {
4828 if(sfConfig.outputFormat == SFLFMT_JSON) {
4829 sf_logf_U32(sample, field, val32);
4830 }
4831 char fieldName[64];
4832 sprintf(fieldName, "%s.%u", field, lane);
4833 sf_logf_U32_formatted(sample, "sfp_lane_", fieldName, "%u", val32);
4834 }
4835
readCounters_SFP(SFSample * sample)4836 static void readCounters_SFP(SFSample *sample)
4837 {
4838 uint32_t num_lanes,ll;
4839 sf_log_next32(sample, "sfp_module_id");
4840 sf_log_next32(sample, "sfp_module_total_lanes");
4841 sf_log_next32(sample, "sfp_module_supply_voltage");
4842 sf_log_next32(sample, "sfp_module_temperature");
4843 num_lanes = getData32(sample);
4844 sf_logf_U32(sample, "sfp_module_active_lanes", num_lanes);
4845
4846 if(sfConfig.outputFormat == SFLFMT_JSON)
4847 json_start_ar("sfp_lanes");
4848
4849 for(ll=0; ll < num_lanes; ll++) {
4850
4851 if(sfConfig.outputFormat == SFLFMT_JSON) {
4852 json_start_ob(NULL);
4853 }
4854 sf_logf_SFP(sample, "index", ll, getData32(sample));
4855 sf_logf_SFP(sample, "tx_bias_current_uA", ll, getData32(sample));
4856 sf_logf_SFP(sample, "tx_power_uW.%u", ll, getData32(sample));
4857 sf_logf_SFP(sample, "tx_power_min_uW.%u", ll, getData32(sample));
4858 sf_logf_SFP(sample, "tx_power_max_uW.%u", ll, getData32(sample));
4859 sf_logf_SFP(sample, "tx_wavelength_nM.%u", ll, getData32(sample));
4860 sf_logf_SFP(sample, "rx_power_uW.%u", ll, getData32(sample));
4861 sf_logf_SFP(sample, "rx_power_min_uW.%u", ll, getData32(sample));
4862 sf_logf_SFP(sample, "rx_power_max_uW.%u", ll, getData32(sample));
4863 sf_logf_SFP(sample, "rx_wavelength_nM.%u", ll, getData32(sample));
4864 if(sfConfig.outputFormat == SFLFMT_JSON)
4865 json_end_ob();
4866 }
4867
4868 if(ll > 0 && sfConfig.outputFormat == SFLFMT_JSON)
4869 json_end_ar();
4870 }
4871
4872 /*_________________---------------------------__________________
4873 _________________ readCountersSample_v2v4 __________________
4874 -----------------___________________________------------------
4875 */
4876
readCountersSample_v2v4(SFSample * sample)4877 static void readCountersSample_v2v4(SFSample *sample)
4878 {
4879 SFStr buf;
4880 sf_logf(sample, "sampleType", "COUNTERSSAMPLE");
4881 sample->s.samplesGenerated = getData32(sample);
4882 sf_logf_U32(sample, "sampleSequenceNo", sample->s.samplesGenerated);
4883 {
4884 uint32_t samplerId = getData32(sample);
4885 sample->s.ds_class = samplerId >> 24;
4886 sample->s.ds_index = samplerId & 0x00ffffff;
4887 }
4888 sf_logf(sample, "sourceId", printDataSource(sample->s.ds_class, sample->s.ds_index, &buf));
4889
4890 sample->s.statsSamplingInterval = getData32(sample);
4891 sf_logf_U32(sample, "statsSamplingInterval", sample->s.statsSamplingInterval);
4892 /* now find out what sort of counter blocks we have here... */
4893 sample->s.counterBlockVersion = getData32(sample);
4894 sf_logf_U32(sample, "counterBlockVersion", sample->s.counterBlockVersion);
4895
4896 if(sfConfig.outputFormat == SFLFMT_JSON) {
4897 json_start_ar("elements");
4898 json_start_ob(NULL);
4899 }
4900
4901 /* first see if we should read the generic stats */
4902 switch(sample->s.counterBlockVersion) {
4903 case INMCOUNTERSVERSION_GENERIC:
4904 case INMCOUNTERSVERSION_ETHERNET:
4905 case INMCOUNTERSVERSION_TOKENRING:
4906 case INMCOUNTERSVERSION_FDDI:
4907 case INMCOUNTERSVERSION_VG:
4908 case INMCOUNTERSVERSION_WAN: readCounters_generic(sample); break;
4909 case INMCOUNTERSVERSION_VLAN: break;
4910 default: receiveError(sample, "unknown stats version", YES); break;
4911 }
4912
4913 if(sfConfig.outputFormat == SFLFMT_JSON) {
4914 json_end_ob();
4915 json_start_ob(NULL);
4916 }
4917
4918 /* now see if there are any specific counter blocks to add */
4919 switch(sample->s.counterBlockVersion) {
4920 case INMCOUNTERSVERSION_GENERIC: /* nothing more */ break;
4921 case INMCOUNTERSVERSION_ETHERNET: readCounters_ethernet(sample); break;
4922 case INMCOUNTERSVERSION_TOKENRING: readCounters_tokenring(sample); break;
4923 case INMCOUNTERSVERSION_FDDI: break;
4924 case INMCOUNTERSVERSION_VG: readCounters_vg(sample); break;
4925 case INMCOUNTERSVERSION_WAN: break;
4926 case INMCOUNTERSVERSION_VLAN: readCounters_vlan(sample); break;
4927 default: receiveError(sample, "unknown INMCOUNTERSVERSION", YES); break;
4928 }
4929
4930 switch(sfConfig.outputFormat) {
4931 case SFLFMT_JSON:
4932 json_end_ob();
4933 json_end_ar();
4934 break;
4935 case SFLFMT_LINE:
4936 writeCountersLine(sample);
4937 break;
4938 case SFLFMT_LINE_CUSTOM:
4939 writeLineCustom(sample);
4940 clearLineCustom(sample, SFSCOPE_SAMPLE);
4941 break;
4942 default:
4943 break;
4944 }
4945 }
4946
4947 /*_________________---------------------------__________________
4948 _________________ readCountersSample __________________
4949 -----------------___________________________------------------
4950 */
4951
readCountersSample(SFSample * sample,int expanded)4952 static void readCountersSample(SFSample *sample, int expanded)
4953 {
4954 SFStr buf;
4955 uint32_t sampleLength;
4956 uint32_t num_elements;
4957 uint8_t *sampleStart;
4958 sf_logf(sample, "sampleType", "COUNTERSSAMPLE");
4959 sampleLength = getData32(sample);
4960 sampleStart = (uint8_t *)sample->datap;
4961 sample->s.samplesGenerated = getData32(sample);
4962
4963 sf_logf_U32(sample, "sampleSequenceNo", sample->s.samplesGenerated);
4964 if(expanded) {
4965 sample->s.ds_class = getData32(sample);
4966 sample->s.ds_index = getData32(sample);
4967 }
4968 else {
4969 uint32_t samplerId = getData32(sample);
4970 sample->s.ds_class = samplerId >> 24;
4971 sample->s.ds_index = samplerId & 0x00ffffff;
4972 }
4973 sf_logf(sample, "sourceId", printDataSource(sample->s.ds_class, sample->s.ds_index, &buf));
4974
4975 num_elements = getData32(sample);
4976
4977 if(sfConfig.outputFormat == SFLFMT_JSON)
4978 json_start_ar("elements");
4979
4980 for(uint32_t el = 0; el < num_elements; el++) {
4981 uint32_t tag, length;
4982 uint8_t *start;
4983 SFStr buf;
4984 if(sfConfig.outputFormat == SFLFMT_JSON) {
4985 json_start_ob(NULL);
4986 }
4987 tag = sample->s.elementType = getData32(sample);
4988 sf_logf(sample, "counterBlock_tag", printTag(tag, &buf));
4989 length = getData32(sample);
4990 start = (uint8_t *)sample->datap;
4991
4992 switch(tag) {
4993 case SFLCOUNTERS_GENERIC: readCounters_generic(sample); break;
4994 case SFLCOUNTERS_ETHERNET: readCounters_ethernet(sample); break;
4995 case SFLCOUNTERS_TOKENRING:readCounters_tokenring(sample); break;
4996 case SFLCOUNTERS_VG: readCounters_vg(sample); break;
4997 case SFLCOUNTERS_VLAN: readCounters_vlan(sample); break;
4998 case SFLCOUNTERS_80211: readCounters_80211(sample); break;
4999 case SFLCOUNTERS_LACP: readCounters_LACP(sample); break;
5000 case SFLCOUNTERS_SFP: readCounters_SFP(sample); break;
5001 case SFLCOUNTERS_PROCESSOR: readCounters_processor(sample); break;
5002 case SFLCOUNTERS_RADIO: readCounters_radio(sample); break;
5003 case SFLCOUNTERS_OFPORT: readCounters_OFPort(sample); break;
5004 case SFLCOUNTERS_PORTNAME: readCounters_portName(sample); break;
5005 case SFLCOUNTERS_HOST_HID: readCounters_host_hid(sample); break;
5006 case SFLCOUNTERS_ADAPTORS: readCounters_adaptors(sample); break;
5007 case SFLCOUNTERS_HOST_PAR: readCounters_host_parent(sample); break;
5008 case SFLCOUNTERS_HOST_CPU: readCounters_host_cpu(sample, length); break;
5009 case SFLCOUNTERS_HOST_MEM: readCounters_host_mem(sample); break;
5010 case SFLCOUNTERS_HOST_DSK: readCounters_host_dsk(sample); break;
5011 case SFLCOUNTERS_HOST_NIO: readCounters_host_nio(sample); break;
5012 case SFLCOUNTERS_HOST_IP: readCounters_host_ip(sample); break;
5013 case SFLCOUNTERS_HOST_ICMP: readCounters_host_icmp(sample); break;
5014 case SFLCOUNTERS_HOST_TCP: readCounters_host_tcp(sample); break;
5015 case SFLCOUNTERS_HOST_UDP: readCounters_host_udp(sample); break;
5016 case SFLCOUNTERS_HOST_VRT_NODE: readCounters_host_vnode(sample); break;
5017 case SFLCOUNTERS_HOST_VRT_CPU: readCounters_host_vcpu(sample); break;
5018 case SFLCOUNTERS_HOST_VRT_MEM: readCounters_host_vmem(sample); break;
5019 case SFLCOUNTERS_HOST_VRT_DSK: readCounters_host_vdsk(sample); break;
5020 case SFLCOUNTERS_HOST_VRT_NIO: readCounters_host_vnio(sample); break;
5021 case SFLCOUNTERS_HOST_GPU_NVML: readCounters_host_gpu_nvml(sample); break;
5022 case SFLCOUNTERS_BCM_TABLES: readCounters_bcm_tables(sample); break;
5023 case SFLCOUNTERS_MEMCACHE: readCounters_memcache(sample); break;
5024 case SFLCOUNTERS_MEMCACHE2: readCounters_memcache2(sample); break;
5025 case SFLCOUNTERS_HTTP: readCounters_http(sample); break;
5026 case SFLCOUNTERS_JVM: readCounters_JVM(sample); break;
5027 case SFLCOUNTERS_JMX: readCounters_JMX(sample, length); break;
5028 case SFLCOUNTERS_APP: readCounters_APP(sample); break;
5029 case SFLCOUNTERS_APP_RESOURCE: readCounters_APP_RESOURCE(sample); break;
5030 case SFLCOUNTERS_APP_WORKERS: readCounters_APP_WORKERS(sample); break;
5031 case SFLCOUNTERS_VDI: readCounters_VDI(sample); break;
5032 case SFLCOUNTERS_OVSDP: readCounters_OVSDP(sample); break;
5033 default: skipTLVRecord(sample, tag, length, "counters_sample_element"); break;
5034 }
5035 lengthCheck(sample, "counters_sample_element", start, length);
5036 if(sfConfig.outputFormat == SFLFMT_JSON)
5037 json_end_ob();
5038 }
5039 lengthCheck(sample, "counters_sample", sampleStart, sampleLength);
5040 if(sfConfig.outputFormat == SFLFMT_JSON)
5041 json_end_ar();
5042
5043 switch(sfConfig.outputFormat) {
5044 case SFLFMT_LINE:
5045 writeCountersLine(sample);
5046 break;
5047 case SFLFMT_LINE_CUSTOM:
5048 writeLineCustom(sample);
5049 clearLineCustom(sample, SFSCOPE_SAMPLE);
5050 break;
5051 default:
5052 break;
5053 }
5054 }
5055
5056 /*_________________---------------------------__________________
5057 _________________ readRTMetric __________________
5058 -----------------___________________________------------------
5059 */
5060
readRTMetric(SFSample * sample)5061 static void readRTMetric(SFSample *sample)
5062 {
5063 #define SFL_MAX_RTMETRIC_KEY_LEN 64
5064 #define SFL_MAX_RTMETRIC_VAL_LEN 255
5065 char dsName[SFL_MAX_RTMETRIC_KEY_LEN];
5066 uint32_t sampleLength;
5067 uint32_t num_elements;
5068 uint8_t *sampleStart;
5069 sf_logf(sample, "sampleType", "RTMETRIC");
5070 sampleLength = getData32(sample);
5071 sampleStart = (uint8_t *)sample->datap;
5072 if(getString(sample, dsName, SFL_MAX_RTMETRIC_KEY_LEN) > 0) {
5073 sf_logf(sample, "rtmetric_datasource_name", dsName);
5074 }
5075 num_elements = getData32(sample);
5076 {
5077 uint32_t el;
5078 for(el = 0; el < num_elements; el++) {
5079 char mname[SFL_MAX_RTMETRIC_KEY_LEN];
5080 uint32_t mtype;
5081 char mvalstr[SFL_MAX_RTMETRIC_VAL_LEN];
5082 uint32_t mvali32;
5083 uint64_t mvali64;
5084 float mvalfloat;
5085 double mvaldouble;
5086 getString(sample, mname, SFL_MAX_RTMETRIC_KEY_LEN);
5087 mtype = getData32(sample);
5088 switch(mtype) {
5089 case 0:
5090 getString(sample, mvalstr, SFL_MAX_RTMETRIC_VAL_LEN);
5091 sf_logf_pushPrefix(sample, "rtmetric_string_");
5092 sf_logf(sample, mname, mvalstr);
5093 sf_logf_popPrefix(sample);
5094 break;
5095 case 1:
5096 mvali32 = getData32(sample);
5097 sf_logf_U32_formatted(sample, "rtmetric_counter32_", mname, "%u", mvali32);
5098 break;
5099 case 2:
5100 mvali64 = getData64(sample);
5101 sf_logf_U64_formatted(sample, "rtmetric_counter64_", mname, "%"PRIu64, mvali64);
5102 break;
5103 case 3:
5104 mvali32 = getData32(sample);
5105 sf_logf_U32_formatted(sample, "rtmetric_gauge32_", mname, "%u", mvali32);
5106 break;
5107 case 4:
5108 mvali64 = getData64(sample);
5109 sf_logf_U64_formatted(sample, "rtmetric_gauge64_", mname, "%"PRIu64, mvali64);
5110 break;
5111 case 5:
5112 mvalfloat = getFloat(sample);
5113 sf_logf_double_formatted(sample, "rtmetric_gaugeFloat_", mname, "%.3f", (double)mvalfloat);
5114 break;
5115 case 6:
5116 mvaldouble = getDouble(sample);
5117 sf_logf_double_formatted(sample, "rtmetric_gaugeDouble_", mname, "%.3f", mvaldouble);
5118 break;
5119 default:
5120 sf_log(sample, "rtmetric unknown_type %u\n", mtype);
5121 SFABORT(sample, SF_ABORT_DECODE_ERROR);
5122 break;
5123 }
5124 }
5125 }
5126 lengthCheck(sample, "rtmetric_sample", sampleStart, sampleLength);
5127 }
5128
5129 /*_________________---------------------------__________________
5130 _________________ readRTFlow __________________
5131 -----------------___________________________------------------
5132 */
5133
readRTFlow(SFSample * sample)5134 static void readRTFlow(SFSample *sample)
5135 {
5136 char dsName[SFL_MAX_RTMETRIC_KEY_LEN];
5137 uint32_t sampleLength;
5138 uint32_t num_elements;
5139 uint8_t *sampleStart;
5140 sf_logf(sample, "sampleType", "RTFLOW");
5141 sampleLength = getData32(sample);
5142 sampleStart = (uint8_t *)sample->datap;
5143 if(getString(sample, dsName, SFL_MAX_RTMETRIC_KEY_LEN) > 0) {
5144 sf_logf(sample, "rtflow_datasource_name", dsName);
5145 }
5146 sf_log_next32(sample, "rtflow_sampling_rate");
5147 sf_log_next32(sample, "rtflow_sample_pool");
5148 num_elements = getData32(sample);
5149 {
5150 uint32_t el;
5151 for(el = 0; el < num_elements; el++) {
5152 char fname[SFL_MAX_RTMETRIC_KEY_LEN];
5153 uint32_t ftype;
5154 char fvalstr[SFL_MAX_RTMETRIC_VAL_LEN];
5155 uint32_t fvali32;
5156 uint64_t fvali64;
5157 float fvalfloat;
5158 double fvaldouble;
5159 SFLAddress fvaladdr;
5160 SFStr addrstr;
5161 u_char fvalmac[6];
5162 char fvalmacstr[32];
5163 getString(sample, fname, SFL_MAX_RTMETRIC_KEY_LEN);
5164 ftype = getData32(sample);
5165 switch(ftype) {
5166 case 0:
5167 getString(sample, fvalstr, SFL_MAX_RTMETRIC_VAL_LEN);
5168 sf_logf_pushPrefix(sample, "rtflow_string_");
5169 sf_logf(sample, fname, fvalstr);
5170 sf_logf_popPrefix(sample);
5171 break;
5172 case 1:
5173 memcpy(fvalmac, sample->datap, 6);
5174 skipBytes(sample, 6);
5175 sf_logf_pushPrefix(sample, "rtflow_mac_");
5176 sf_logf(sample, fname, printMAC(fvalmac, &addrstr));
5177 sf_logf_popPrefix(sample);
5178 break;
5179 case 2:
5180 fvaladdr.type = SFLADDRESSTYPE_IP_V4;
5181 fvaladdr.address.ip_v4.addr = getData32_nobswap(sample);
5182 sf_logf_pushPrefix(sample, "rtflow_ip_");
5183 sf_logf(sample, fname, printAddress(&fvaladdr, &addrstr));
5184 sf_logf_popPrefix(sample);
5185 break;
5186 case 3:
5187 fvaladdr.type = SFLADDRESSTYPE_IP_V6;
5188 memcpy(fvaladdr.address.ip_v6.addr, sample->datap, 16);
5189 skipBytes(sample, 16);
5190 sf_logf_pushPrefix(sample, "rtflow_ip6_");
5191 sf_logf(sample, fname, printAddress(&fvaladdr, &addrstr));
5192 sf_logf_popPrefix(sample);
5193 break;
5194 case 4:
5195 fvali32 = getData32(sample);
5196 sf_logf_U32_formatted(sample, "rtflow_int32_", fname, "%u", fvali32);
5197 break;
5198 case 5:
5199 fvali64 = getData64(sample);
5200 sf_logf_U64_formatted(sample, "rtflow_int64_", fname, "%"PRIu64, fvali64);
5201 break;
5202 case 6:
5203 fvalfloat = getFloat(sample);
5204 sf_logf_double_formatted(sample, "rtflow_float_", fname, "%.3f", (double)fvalfloat);
5205 break;
5206 case 7:
5207 fvaldouble = getDouble(sample);
5208 sf_logf_double_formatted(sample, "rtflow_double_", fname, "%.3f", fvaldouble);
5209 break;
5210 default:
5211 sf_log(sample, "rtflow unknown_type %u\n", ftype);
5212 SFABORT(sample, SF_ABORT_DECODE_ERROR);
5213 break;
5214 }
5215 }
5216 }
5217 lengthCheck(sample, "rtflow_sample", sampleStart, sampleLength);
5218 }
5219
5220 /*_________________---------------------------__________________
5221 _________________ readSFlowDatagram __________________
5222 -----------------___________________________------------------
5223 */
5224
readSFlowDatagram(SFSample * sample)5225 static void readSFlowDatagram(SFSample *sample)
5226 {
5227 uint32_t samplesInPacket;
5228 SFStr buf;
5229
5230 /* log some datagram info */
5231 sfConfig.currentFieldScope = SFSCOPE_DATAGRAM;
5232 sf_logf(sample, "datagramSourceIP", printAddress(&sample->sourceIP, &buf));
5233 sf_logf_U32(sample, "datagramSize", sample->rawSampleLen);
5234 sf_logf_U32(sample, "unixSecondsUTC", sample->readTimestamp);
5235 sf_logf(sample, "localtime", printTimestamp(sample->readTimestamp, &buf));
5236 if(sample->pcapTimestamp) {
5237 /* thanks to Richard Clayton for this bugfix */
5238 sf_logf(sample, "pcapTimestamp", printTimestamp(sample->pcapTimestamp, &buf));
5239 }
5240
5241 /* check the version */
5242 sample->datagramVersion = getData32(sample);
5243 sf_logf_U32(sample, "datagramVersion", sample->datagramVersion);
5244 if(sample->datagramVersion != 2 &&
5245 sample->datagramVersion != 4 &&
5246 sample->datagramVersion != 5) {
5247 receiveError(sample, "unexpected datagram version number\n", YES);
5248 }
5249
5250 /* get the agent address */
5251 getAddress(sample, &sample->agent_addr);
5252
5253 /* version 5 has an agent sub-id as well */
5254 if(sample->datagramVersion >= 5) {
5255 sample->agentSubId = getData32(sample);
5256 sf_logf_U32(sample, "agentSubId", sample->agentSubId);
5257 }
5258
5259 sample->sequenceNo = getData32(sample); /* this is the packet sequence number */
5260 sample->sysUpTime = getData32(sample);
5261 samplesInPacket = getData32(sample);
5262 sf_logf(sample, "agent", printAddress(&sample->agent_addr, &buf));
5263 sf_logf_U32(sample, "packetSequenceNo", sample->sequenceNo);
5264 sf_logf_U32(sample, "sysUpTime", sample->sysUpTime);
5265 sf_logf_U32(sample, "samplesInPacket", samplesInPacket);
5266
5267 /* now iterate and pull out the flows and counters samples */
5268 sfConfig.currentFieldScope = SFSCOPE_SAMPLE;
5269 {
5270 uint32_t samp = 0;
5271 if(sfConfig.outputFormat == SFLFMT_JSON)
5272 json_start_ar("samples");
5273
5274 for(; samp < samplesInPacket; samp++) {
5275 if((uint8_t *)sample->datap >= sample->endp) {
5276 fprintf(ERROUT, "unexpected end of datagram after sample %d of %d\n", samp, samplesInPacket);
5277 SFABORT(sample, SF_ABORT_EOS);
5278 }
5279 // clear all per-sample fields
5280 memset(&sample->s, 0, sizeof(sample->s));
5281 /* just read the tag, then call the approriate decode fn */
5282 sample->s.elementType = 0;
5283 sample->s.sampleType = getData32(sample);
5284
5285 if(sfConfig.outputFormat == SFLFMT_JSON) {
5286 json_start_ob(NULL);
5287 }
5288 else
5289 sf_log(sample,"startSample ----------------------\n");
5290
5291 sf_logf(sample, "sampleType_tag", printTag(sample->s.sampleType, &buf));
5292 if(sample->datagramVersion >= 5) {
5293 switch(sample->s.sampleType) {
5294 case SFLFLOW_SAMPLE: readFlowSample(sample, NO); break;
5295 case SFLCOUNTERS_SAMPLE: readCountersSample(sample, NO); break;
5296 case SFLFLOW_SAMPLE_EXPANDED: readFlowSample(sample, YES); break;
5297 case SFLCOUNTERS_SAMPLE_EXPANDED: readCountersSample(sample, YES); break;
5298 case SFLEVENT_DISCARDED_PACKET: readDiscardSample(sample); break;
5299 case SFLRTMETRIC: readRTMetric(sample); break;
5300 case SFLRTFLOW: readRTFlow(sample); break;
5301 default: skipTLVRecord(sample, sample->s.sampleType, getData32(sample), "sample"); break;
5302 }
5303 }
5304 else {
5305 switch(sample->s.sampleType) {
5306 case FLOWSAMPLE: readFlowSample_v2v4(sample); break;
5307 case COUNTERSSAMPLE: readCountersSample_v2v4(sample); break;
5308 default: receiveError(sample, "unexpected sample type", YES); break;
5309 }
5310 }
5311 if(sfConfig.outputFormat == SFLFMT_JSON)
5312 json_end_ob();
5313 else
5314 sf_log(sample,"endSample ----------------------\n");
5315 }
5316 if(sfConfig.outputFormat == SFLFMT_JSON)
5317 json_end_ar();
5318 }
5319 }
5320
5321 /*_________________---------------------------__________________
5322 _________________ receiveSFlowDatagram __________________
5323 -----------------___________________________------------------
5324 */
5325
receiveSFlowDatagram(SFSample * sample)5326 static void receiveSFlowDatagram(SFSample *sample)
5327 {
5328 if(sfConfig.forwardingTargets || sfConfig.forwardingTargets6) {
5329 /* if we are forwarding, then do nothing else (it might
5330 be important from a performance point of view). */
5331 SFForwardingTarget *tgt = sfConfig.forwardingTargets;
5332 for( ; tgt != NULL; tgt = tgt->nxt) {
5333 int bytesSent;
5334 if((bytesSent = sendto(tgt->sock,
5335 (const char *)sample->rawSample,
5336 sample->rawSampleLen,
5337 0,
5338 (struct sockaddr *)(&tgt->addr),
5339 sizeof(tgt->addr))) != sample->rawSampleLen) {
5340 fprintf(ERROUT, "sendto returned %d (expected %d): %s\n",
5341 bytesSent,
5342 sample->rawSampleLen,
5343 strerror(errno));
5344 }
5345 }
5346 SFForwardingTarget6 *tgt6 = sfConfig.forwardingTargets6;
5347 for( ; tgt6 != NULL; tgt6 = tgt6->nxt) {
5348 int bytesSent;
5349 if((bytesSent = sendto(tgt6->sock,
5350 (const char *)sample->rawSample,
5351 sample->rawSampleLen,
5352 0,
5353 (struct sockaddr *)(&tgt6->addr),
5354 sizeof(tgt6->addr))) != sample->rawSampleLen) {
5355 fprintf(ERROUT, "sendto returned %d (expected %d): %s\n",
5356 bytesSent,
5357 sample->rawSampleLen,
5358 strerror(errno));
5359 }
5360 }
5361 }
5362 else {
5363 int exceptionVal;
5364 sample->readTimestamp = (long)time(NULL);
5365 if(sfConfig.outputFormat == SFLFMT_JSON) {
5366 sfConfig.jsonStart = YES;
5367 json_start_ob(NULL);
5368 }
5369 else {
5370 sf_log(sample,"startDatagram =================================\n");
5371 }
5372
5373 if((exceptionVal = setjmp(sample->env)) == 0) {
5374 /* TRY */
5375 sample->datap = (uint32_t *)sample->rawSample;
5376 sample->endp = (uint8_t *)sample->rawSample + sample->rawSampleLen;
5377 readSFlowDatagram(sample);
5378 }
5379 else {
5380 /* CATCH */
5381 fprintf(ERROUT, "caught exception: %d\n", exceptionVal);
5382 }
5383 if(sfConfig.outputFormat == SFLFMT_JSON) {
5384 json_end_ob();
5385 printf("\n");
5386 }
5387 else {
5388 sf_log(sample, "endDatagram =================================\n");
5389 }
5390 fflush(stdout);
5391
5392 if(sfConfig.outputFormat == SFLFMT_JSON) {
5393 /* reset depth in case an exception left it hanging */
5394 sfConfig.outputDepth = 0;
5395 /* add blank line if pretty-printing */
5396 if(sfConfig.jsonIndent)
5397 putchar('\n');
5398
5399 }
5400 else if(sfConfig.outputFormat == SFLFMT_LINE_CUSTOM) {
5401 /* clear datagram-scoped field values */
5402 clearLineCustom(sample, SFSCOPE_DATAGRAM);
5403 }
5404 }
5405 }
5406
5407 /*__________________-----------------------------__________________
5408 _________________ openInputUDPSocket __________________
5409 -----------------_____________________________------------------
5410 */
5411
openInputUDPSocket(uint16_t port)5412 static int openInputUDPSocket(uint16_t port)
5413 {
5414 int soc;
5415 struct sockaddr_in myaddr_in;
5416
5417 /* Create socket */
5418 memset((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));
5419 myaddr_in.sin_family = AF_INET;
5420 /* myaddr_in6.sin6_addr.s_addr = INADDR_ANY; */
5421 myaddr_in.sin_port = htons(port);
5422
5423 if ((soc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
5424 fprintf(ERROUT, "v4 socket() creation failed, %s\n", strerror(errno));
5425 return -1;
5426 }
5427
5428 #ifndef _WIN32
5429 /* make socket non-blocking */
5430 int save_fd = fcntl(soc, F_GETFL);
5431 save_fd |= O_NONBLOCK;
5432 fcntl(soc, F_SETFL, save_fd);
5433 #endif /* _WIN32 */
5434
5435 /* Bind the socket */
5436 if(bind(soc, (struct sockaddr *)&myaddr_in, sizeof(struct sockaddr_in)) == -1) {
5437 fprintf(ERROUT, "v4 bind() failed, port = %d : %s\n", port, strerror(errno));
5438 return -1;
5439 }
5440 return soc;
5441 }
5442
5443 /*__________________-----------------------------__________________
5444 _________________ openInputUDP6Socket __________________
5445 -----------------_____________________________------------------
5446 */
5447
openInputUDP6Socket(uint16_t port)5448 static int openInputUDP6Socket(uint16_t port)
5449 {
5450 int soc;
5451 struct sockaddr_in6 myaddr_in6;
5452
5453 /* Create socket */
5454 memset((char *)&myaddr_in6, 0, sizeof(struct sockaddr_in6));
5455 myaddr_in6.sin6_family = AF_INET6;
5456 /* myaddr_in6.sin6_addr = INADDR_ANY; */
5457 myaddr_in6.sin6_port = htons(port);
5458
5459 if ((soc = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
5460 fprintf(ERROUT, "v6 socket() creation failed, %s\n", strerror(errno));
5461 exit(-6);
5462 }
5463
5464 #ifndef _WIN32
5465 /* make socket non-blocking */
5466 int save_fd = fcntl(soc, F_GETFL);
5467 save_fd |= O_NONBLOCK;
5468 fcntl(soc, F_SETFL, save_fd);
5469 #endif /* _WIN32 */
5470
5471 /* Bind the socket */
5472 if(bind(soc, (struct sockaddr *)&myaddr_in6, sizeof(struct sockaddr_in6)) == -1) {
5473 fprintf(ERROUT, "v6 bind() failed, port = %d : %s\n", port, strerror(errno));
5474 return -1;
5475 }
5476 return soc;
5477 }
5478
5479 /*_________________---------------------------__________________
5480 _________________ ipv4MappedAddress __________________
5481 -----------------___________________________------------------
5482 */
5483
ipv4MappedAddress(SFLIPv6 * ipv6addr,SFLIPv4 * ip4addr)5484 static int ipv4MappedAddress(SFLIPv6 *ipv6addr, SFLIPv4 *ip4addr) {
5485 static uint8_t mapped_prefix[] = { 0,0,0,0,0,0,0,0,0,0,0xFF,0xFF };
5486 static uint8_t compat_prefix[] = { 0,0,0,0,0,0,0,0,0,0,0,0 };
5487 if(!memcmp(ipv6addr->addr, mapped_prefix, 12) ||
5488 !memcmp(ipv6addr->addr, compat_prefix, 12)) {
5489 memcpy(ip4addr, ipv6addr->addr + 12, 4);
5490 return YES;
5491 }
5492 return NO;
5493 }
5494
5495 /*_________________---------------------------__________________
5496 _________________ readPacket __________________
5497 -----------------___________________________------------------
5498 */
5499
readPacket(int soc)5500 static void readPacket(int soc)
5501 {
5502 struct sockaddr_in6 peer;
5503 int cc;
5504 socklen_t alen;
5505 char buf[SA_MAX_SFLOW_PKT_SIZ];
5506 alen = sizeof(peer);
5507 memset(&peer, 0, sizeof(peer));
5508 cc = recvfrom(soc, buf, SA_MAX_SFLOW_PKT_SIZ, 0, (struct sockaddr *)&peer, &alen);
5509 if(cc <= 0) {
5510 fprintf(ERROUT, "recvfrom() failed, %s\n", strerror(errno));
5511 return;
5512 }
5513 SFSample sample;
5514 memset(&sample, 0, sizeof(sample));
5515 sample.rawSample = (uint8_t *)buf;
5516 sample.rawSampleLen = cc;
5517 if(alen == sizeof(struct sockaddr_in)) {
5518 struct sockaddr_in *peer4 = (struct sockaddr_in *)&peer;
5519 sample.sourceIP.type = SFLADDRESSTYPE_IP_V4;
5520 memcpy(&sample.sourceIP.address.ip_v4, &peer4->sin_addr, 4);
5521 }
5522 else {
5523 SFLIPv4 v4src;
5524 sample.sourceIP.type = SFLADDRESSTYPE_IP_V6;
5525 memcpy(sample.sourceIP.address.ip_v6.addr, &peer.sin6_addr, 16);
5526 if(ipv4MappedAddress(&sample.sourceIP.address.ip_v6, &v4src)) {
5527 sample.sourceIP.type = SFLADDRESSTYPE_IP_V4;
5528 sample.sourceIP.address.ip_v4 = v4src;
5529 }
5530 }
5531 receiveSFlowDatagram(&sample);
5532 }
5533
5534 /*_________________---------------------------__________________
5535 _________________ readPcapPacket __________________
5536 -----------------___________________________------------------
5537 */
5538
5539
5540
5541
5542 /*_________________---------------------------__________________
5543 _________________ decodeLinkLayer __________________
5544 -----------------___________________________------------------
5545 store the offset to the start of the ipv4 header in the sequence_number field
5546 or -1 if not found. Decode the 802.1d if it's there.
5547 */
5548
pcapOffsetToSFlow(uint8_t * start,int len)5549 static int pcapOffsetToSFlow(uint8_t *start, int len)
5550 {
5551 uint8_t *end = start + len;
5552 uint8_t *ptr = start;
5553 uint16_t type_len;
5554
5555 switch(sfConfig.readPcapHdr.linktype) {
5556 case DLT_LINUX_SLL:
5557 {
5558 uint16_t packet_type = (ptr[0] << 8) + ptr[1];
5559 uint16_t arphrd_type = (ptr[2] << 8) + ptr[3];
5560 uint16_t lladdr_len = (ptr[4] << 8) + ptr[5];
5561 /* but lladdr field is always 8 bytes regardless */
5562 ptr += 6 + 8;
5563 type_len = (ptr[0] << 8) + ptr[1];
5564 ptr += 2;
5565 }
5566 break;
5567
5568 case DLT_EN10MB:
5569 default:
5570 /* assume Ethernet header */
5571 if(len < NFT_ETHHDR_SIZ) return -1; /* not enough for an Ethernet header */
5572 ptr += 6; /* dst */
5573 ptr += 6; /* src */
5574 type_len = (ptr[0] << 8) + ptr[1];
5575 ptr += 2;
5576 break;
5577 }
5578
5579 while(type_len == 0x8100
5580 || type_len == 0x88A8
5581 || type_len == 0x9100
5582 || type_len == 0x9200
5583 || type_len == 0x9300) {
5584 /* VLAN - next two bytes */
5585 /* _____________________________________ */
5586 /* | pri | c | vlan-id | */
5587 /* ------------------------------------- */
5588 ptr += 2;
5589 /* now get the type_len again (next two bytes) */
5590 type_len = (ptr[0] << 8) + ptr[1];
5591 ptr += 2;
5592 if(ptr >= end) return -1;
5593 }
5594
5595 /* now we're just looking for IP */
5596 if(end - ptr < NFT_MIN_SIZ) return -1; /* not enough for an IPv4 header */
5597
5598 /* peek for IPX */
5599 if(type_len == 0x0200 || type_len == 0x0201 || type_len == 0x0600) {
5600 #define IPX_HDR_LEN 30
5601 #define IPX_MAX_DATA 546
5602 int ipxChecksum = (ptr[0] == 0xff && ptr[1] == 0xff);
5603 int ipxLen = (ptr[2] << 8) + ptr[3];
5604 if(ipxChecksum &&
5605 ipxLen >= IPX_HDR_LEN &&
5606 ipxLen <= (IPX_HDR_LEN + IPX_MAX_DATA))
5607 /* we don't do anything with IPX here */
5608 return -1;
5609 }
5610
5611 if(type_len <= NFT_MAX_8023_LEN) {
5612 /* assume 802.3+802.2 header */
5613 /* check for SNAP */
5614 if(ptr[0] == 0xAA &&
5615 ptr[1] == 0xAA &&
5616 ptr[2] == 0x03) {
5617 ptr += 3;
5618 if(ptr[0] != 0 ||
5619 ptr[1] != 0 ||
5620 ptr[2] != 0) {
5621 return -1; /* no further decode for vendor-specific protocol */
5622 }
5623 ptr += 3;
5624 /* OUI == 00-00-00 means the next two bytes are the ethernet type (RFC 2895) */
5625 type_len = (ptr[0] << 8) + ptr[1];
5626 ptr += 2;
5627 }
5628 else {
5629 if (ptr[0] == 0x06 &&
5630 ptr[1] == 0x06 &&
5631 (ptr[2] & 0x01)) {
5632 /* IP over 8022 */
5633 ptr += 3;
5634 /* force the type_len to be IP so we can inline the IP decode below */
5635 type_len = 0x0800;
5636 }
5637 else return -1;
5638 }
5639 }
5640 if(ptr >= end) return -1;
5641
5642 /* assume type_len is an ethernet-type now */
5643
5644 if(type_len == 0x0800) {
5645 /* IPV4 */
5646 if((end - ptr) < sizeof(struct myiphdr)) return -1;
5647 /* look at first byte of header.... */
5648 /* ___________________________ */
5649 /* | version | hdrlen | */
5650 /* --------------------------- */
5651 if((*ptr >> 4) != 4) return -1; /* not version 4 */
5652 if((*ptr & 15) < 5) return -1; /* not IP (hdr len must be 5 quads or more) */
5653 ptr += (*ptr & 15) << 2; /* skip over header */
5654 }
5655
5656 if(type_len == 0x86DD) {
5657 /* IPV6 */
5658 /* look at first byte of header.... */
5659 if((*ptr >> 4) != 6) return -1; /* not version 6 */
5660 /* just assume no header options */
5661 ptr += 40;
5662 }
5663
5664 /* still have to skip over UDP header */
5665 ptr += 8;
5666 if(ptr >= end) return -1;
5667 return (ptr - start);
5668 }
5669
5670
5671
5672
readPcapPacket(FILE * file)5673 static int readPcapPacket(FILE *file)
5674 {
5675 uint8_t buf[SA_MAX_PCAP_PKT];
5676 struct pcap_pkthdr hdr;
5677 SFSample sample;
5678 int skipBytes = 0;
5679
5680 if(fread(&hdr, sizeof(hdr), 1, file) != 1) {
5681 if(feof(file)) return 0;
5682 fprintf(ERROUT, "unable to read pcap packet header from %s : %s\n", sfConfig.readPcapFileName, strerror(errno));
5683 exit(-32);
5684 }
5685
5686 if(sfConfig.pcapSwap) {
5687 hdr.ts_sec = MyByteSwap32(hdr.ts_sec);
5688 hdr.ts_usec = MyByteSwap32(hdr.ts_usec);
5689 hdr.caplen = MyByteSwap32(hdr.caplen);
5690 hdr.len = MyByteSwap32(hdr.len);
5691 }
5692
5693 /* Protect against possible buffer overrun from corrupted pcap file.
5694 Thanks to Naoki Ogawa for spotting this. */
5695 if(hdr.caplen > SA_MAX_PCAP_PKT) {
5696 fprintf(ERROUT, "pcap %s : capture-len (%u) too long for read buffer\n", sfConfig.readPcapFileName, hdr.caplen);
5697 return 0;
5698 }
5699
5700 if(fread(buf, hdr.caplen, 1, file) != 1) {
5701 fprintf(ERROUT, "unable to read pcap packet from %s : %s\n", sfConfig.readPcapFileName, strerror(errno));
5702 exit(-34);
5703 }
5704
5705
5706 if(hdr.caplen < hdr.len) {
5707 fprintf(ERROUT, "incomplete datagram (pcap snaplen too short)\n");
5708 }
5709 else {
5710 /* need to skip over the encapsulation in the captured packet.
5711 -- should really do this by checking for 802.2, IP options etc. but
5712 for now we just assume ethernet + IP + UDP */
5713 skipBytes = pcapOffsetToSFlow(buf, hdr.caplen);
5714 memset(&sample, 0, sizeof(sample));
5715 sample.rawSample = buf + skipBytes;
5716 sample.rawSampleLen = hdr.caplen - skipBytes;
5717 sample.pcapTimestamp = hdr.ts_sec;
5718 receiveSFlowDatagram(&sample);
5719 }
5720 return 1;
5721 }
5722
5723
5724 /*_________________---------------------------__________________
5725 _________________ parseVlanFilter __________________
5726 -----------------___________________________------------------
5727 */
5728
peekForNumber(char * p)5729 static void peekForNumber(char *p) {
5730 if(*p < '0' || *p > '9') {
5731 fprintf(ERROUT, "error parsing vlan filter ranges (next char = <%c>)\n", *p);
5732 exit(-19);
5733 }
5734 }
5735
testVlan(uint32_t num)5736 static void testVlan(uint32_t num) {
5737 if(num > FILTER_MAX_VLAN) {
5738 fprintf(ERROUT, "error parsing vlan filter (vlan = <%d> out of range)\n", num);
5739 exit(-20);
5740 }
5741 }
5742
parseVlanFilter(uint8_t * array,uint8_t flag,char * start)5743 static void parseVlanFilter(uint8_t *array, uint8_t flag, char *start)
5744 {
5745 char *p = start;
5746 char *sep = " ,";
5747 do {
5748 uint32_t first, last;
5749 p += strspn(p, sep); /* skip separators */
5750 peekForNumber(p);
5751 first = strtol(p, &p, 0); /* read an integer */
5752 testVlan(first);
5753 array[first] = flag;
5754 if(*p == '-') {
5755 /* a range. skip the '-' (so it doesn't get interpreted as unary minus) */
5756 p++;
5757 /* and read the second integer */
5758 peekForNumber(p);
5759 last = strtol(p, &p, 0);
5760 testVlan(last);
5761 if(last > first) {
5762 uint32_t i;
5763 /* iterate over the range */
5764 for(i = first; i <= last; i++) array[i] = flag;
5765 }
5766 }
5767 } while(*p != '\0');
5768 }
5769
5770 /*_________________---------------------------__________________
5771 _________________ parseFieldList __________________
5772 -----------------___________________________------------------
5773 */
5774
parseFields(char * start,char ** array)5775 static int parseFields(char *start, char **array) {
5776 char *p = start;
5777 char *sep = " ,";
5778 int tokens = 0;
5779 do {
5780 p += strspn(p, sep); /* skip separators */
5781 int len = strcspn(p, sep);
5782 if(len) {
5783 if(array) {
5784 char *str = (char *)my_calloc(len+1);
5785 memcpy(str, p, len);
5786 array[tokens] = str;
5787 }
5788 tokens++;
5789 }
5790 p += len;
5791 } while(*p != '\0');
5792 return tokens;
5793 }
5794
parseFieldList(SFFieldList * fieldList,char * start)5795 static void parseFieldList(SFFieldList *fieldList, char *start)
5796 {
5797 fieldList->n = parseFields(start, NULL);
5798 if(fieldList->n) {
5799 fieldList->fields = (char **)my_calloc(fieldList->n * sizeof(char *));
5800 fieldList->values = (SFStr *)my_calloc(fieldList->n * sizeof(SFStr));
5801 fieldList->fieldScope = (char *)my_calloc(fieldList->n * sizeof(char));
5802 parseFields(start, fieldList->fields);
5803 /* load hash table with field->slot */
5804 hcreate(fieldList->n);
5805 for(int ii = 0; ii < fieldList->n; ii++) {
5806 SFStr_init(&fieldList->values[ii]);
5807 int *pSlot = (int *)my_calloc(sizeof(int));
5808 *pSlot = ii;
5809 ENTRY e;
5810 e.key = fieldList->fields[ii];
5811 e.data = pSlot;
5812 hsearch(e, ENTER);
5813 }
5814 }
5815 }
5816
5817 /*________________---------------------------__________________
5818 ________________ lookupAddress __________________
5819 ----------------___________________________------------------
5820 */
5821
parseOrResolveAddress(char * name,struct sockaddr * sa,SFLAddress * addr,int family,int numeric)5822 static int parseOrResolveAddress(char *name, struct sockaddr *sa, SFLAddress *addr, int family, int numeric)
5823 {
5824 struct addrinfo *info = NULL;
5825 struct addrinfo hints = { 0 };
5826 hints.ai_socktype = SOCK_DGRAM; /* constrain this so we don't get lots of answers */
5827 hints.ai_family = family; /* AF_INET, AF_INET6 or 0 */
5828 if(numeric) {
5829 hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
5830 }
5831 int err = getaddrinfo(name, NULL, &hints, &info);
5832 if(err) {
5833 fprintf(ERROUT, "getaddrinfo(%s) failed: %s (expecting %s)\n",
5834 name,
5835 gai_strerror(err),
5836 numeric ? "numeric address" : "hostname or numeric address");
5837 /* try again if err == EAI_AGAIN? */
5838 return NO;
5839 }
5840
5841 if(info == NULL)
5842 return NO;
5843
5844 /* info now allocated on heap - see freeaddrinfo() below */
5845 if(!info->ai_addr) {
5846 err = YES;
5847 }
5848 else {
5849 /* answer is now in info - a linked list of answers with sockaddr values.
5850 extract the address we want from the first one. */
5851 switch(info->ai_family) {
5852 case AF_INET:
5853 {
5854 struct sockaddr_in *ipsoc = (struct sockaddr_in *)info->ai_addr;
5855 addr->type = SFLADDRESSTYPE_IP_V4;
5856 addr->address.ip_v4.addr = ipsoc->sin_addr.s_addr;
5857 if(sa) memcpy(sa, info->ai_addr, info->ai_addrlen);
5858 }
5859 break;
5860 case AF_INET6:
5861 {
5862 struct sockaddr_in6 *ip6soc = (struct sockaddr_in6 *)info->ai_addr;
5863 addr->type = SFLADDRESSTYPE_IP_V6;
5864 memcpy(&addr->address.ip_v6, &ip6soc->sin6_addr, 16);
5865 if(sa) memcpy(sa, info->ai_addr, info->ai_addrlen);
5866 }
5867 break;
5868 default:
5869 fprintf(ERROUT, "getaddrinfo(%s): unexpected address family: %d\n", name, info->ai_family);
5870 err = YES;
5871 break;
5872 }
5873 }
5874 /* free the dynamically allocated data before returning */
5875 freeaddrinfo(info);
5876 /* indicate success */
5877 return (err == NO);
5878 }
5879
5880 /*_________________---------------------------__________________
5881 _________________ addForwardingTarget __________________
5882 -----------------___________________________------------------
5883 return boolean for success or failure
5884 */
5885
addForwardingTarget(char * hostandport)5886 static int addForwardingTarget(char *hostandport)
5887 {
5888 /* expect <host>/<port> */
5889 #define MAX_HOSTANDPORT_LEN 100
5890 char hoststr[MAX_HOSTANDPORT_LEN+1];
5891 char *p;
5892 uint32_t port;
5893 struct sockaddr_in6 sa;
5894 SFLAddress tgtIP;
5895 SFForwardingTarget *tgt;
5896 SFForwardingTarget6 *tgt6;
5897 int numeric = (sfConfig.allowDNS) ? NO : YES;
5898
5899 if(hostandport == NULL) {
5900 fprintf(ERROUT, "expected <host>/<port>\n");
5901 return NO;
5902 }
5903 if(strlen(hostandport) > MAX_HOSTANDPORT_LEN) return NO;
5904 /* take a copy */
5905 strcpy(hoststr, hostandport);
5906 /* find the '/' */
5907 for(p = hoststr; *p != '\0'; p++) if(*p == '/') break;
5908 if(*p == '\0') {
5909 /* not found */
5910 fprintf(ERROUT, "host/port - no '/' found\n");
5911 return NO;
5912 }
5913 (*p) = '\0'; /* blat in a zero */
5914 p++;
5915
5916 /* now p points to port string, and hoststr is just the hostname or IP */
5917 sscanf(p, "%u", &port);
5918 if(port <= 0 || port >= 65535) {
5919 fprintf(ERROUT, "invalid forwarding target port: %u\n", port);
5920 return NO;
5921 }
5922
5923 if(parseOrResolveAddress(hoststr, (struct sockaddr *)&sa, &tgtIP, AF_UNSPEC, numeric) == NO) {
5924 return NO;
5925 }
5926 switch(tgtIP.type) {
5927 case SFLADDRESSTYPE_IP_V4:
5928 tgt = (SFForwardingTarget *)my_calloc(sizeof(SFForwardingTarget));
5929 tgt->addr = *(struct sockaddr_in *)&sa;
5930 tgt->addr.sin_port = htons(port);
5931 /* and open the socket */
5932 if((tgt->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
5933 fprintf(ERROUT, "socket open (for %s) failed: %s\n", hostandport, strerror(errno));
5934 return NO;
5935 }
5936 /* got this far, so must be OK */
5937 tgt->nxt = sfConfig.forwardingTargets;
5938 sfConfig.forwardingTargets = tgt;
5939 break;
5940
5941 case SFLADDRESSTYPE_IP_V6:
5942 tgt6 = (SFForwardingTarget6 *)my_calloc(sizeof(SFForwardingTarget6));
5943 tgt6->addr = sa;
5944 tgt6->addr.sin6_port = htons(port);
5945 /* and open the socket */
5946 if((tgt6->sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
5947 fprintf(ERROUT, "socket open (for %s) failed: %s\n", hostandport, strerror(errno));
5948 return NO;
5949 }
5950 /* got this far, so must be OK */
5951 tgt6->nxt = sfConfig.forwardingTargets6;
5952 sfConfig.forwardingTargets6 = tgt6;
5953 break;
5954
5955 default:
5956 fprintf(ERROUT, "unknown address type %s\n", hoststr);
5957 return NO;
5958 }
5959
5960 return YES;
5961 }
5962
5963 /*_________________---------------------------__________________
5964 _________________ setNetFlowCollector __________________
5965 -----------------___________________________------------------
5966 return boolean for success or failure
5967 */
5968
setNetFlowCollector(char * host)5969 static int setNetFlowCollector(char *host)
5970 {
5971 int numeric = (sfConfig.allowDNS) ? NO : YES;
5972 if(parseOrResolveAddress(host,
5973 (struct sockaddr *)&sfConfig.netFlowOutputSA,
5974 &sfConfig.netFlowOutputIP,
5975 AF_UNSPEC,
5976 numeric) == NO) {
5977 fprintf(ERROUT, "netflow collector address lookup failed\n");
5978 return NO;
5979 }
5980 return YES;
5981 }
5982
5983 /*_________________---------------------------__________________
5984 _________________ instructions __________________
5985 -----------------___________________________------------------
5986 */
5987
instructions(char * command)5988 static void instructions(char *command)
5989 {
5990 fprintf(ERROUT,"Copyright (c) InMon Corporation 2000-2019 ALL RIGHTS RESERVED\n");
5991 fprintf(ERROUT,"This software provided with NO WARRANTY WHATSOEVER\n");
5992 fprintf(ERROUT,"\n");
5993 fprintf(ERROUT,"Usage: %s [-p port]\n", command);
5994 fprintf(ERROUT,"\n");
5995 fprintf(ERROUT,"%s version: %s\n", command, VERSION);
5996 fprintf(ERROUT,"\n");
5997 fprintf(ERROUT,"usage:\n");
5998 fprintf(ERROUT, " -h | -? - this help message\n");
5999 fprintf(ERROUT, "\n");
6000 fprintf(ERROUT,"general:\n");
6001 fprintf(ERROUT, " -k - keep going on non-signal errors rather than aborting\n");
6002 fprintf(ERROUT, " -D - allow hosts to be referenced by DNS name\n");
6003 fprintf(ERROUT,"\n");
6004 fprintf(ERROUT,"forwarding:\n");
6005 fprintf(ERROUT, " -f host/port - forward sflow to IP (or hostname if -D added)\n");
6006 fprintf(ERROUT, " - ...repeat for multiple collectors\n");
6007 fprintf(ERROUT,"\n");
6008 fprintf(ERROUT,"text output:\n");
6009 fprintf(ERROUT, " -l - output in line-by-line CSV format\n");
6010 fprintf(ERROUT, " -L <fields> - output selected fields in line-by-line CSV format\n");
6011 fprintf(ERROUT, " - e.g. -L srcIP,dstIP\n");
6012 fprintf(ERROUT, " -g - output in 'grep-friendly' format\n");
6013 fprintf(ERROUT, " -j - output in JSON format (compact)\n");
6014 fprintf(ERROUT, " -J - output in JSON format (pretty-print)\n");
6015 fprintf(ERROUT, " -H - output HTTP common log file format\n");
6016 fprintf(ERROUT,"\n");
6017 fprintf(ERROUT,"tcpdump output:\n");
6018 fprintf(ERROUT, " -t - output in binary tcpdump(1) format\n");
6019 fprintf(ERROUT, " -r file - read binary tcpdump(1) format\n");
6020 fprintf(ERROUT, " -x - remove all IPV4 content\n");
6021 fprintf(ERROUT,"\n");
6022 fprintf(ERROUT,"NetFlow output:\n");
6023 fprintf(ERROUT, " -c host - netflow collector IP (or hostname if -D added)\n");
6024 fprintf(ERROUT, " -d port - netflow collector UDP port\n");
6025 fprintf(ERROUT, " -e - netflow collector peer_as (default = origin_as)\n");
6026 fprintf(ERROUT, " -s - disable scaling of netflow output by sampling rate\n");
6027 #ifdef SPOOFSOURCE
6028 fprintf(ERROUT, " -S - spoof source of netflow packets to input agent IP\n");
6029 #endif
6030 fprintf(ERROUT, " -N version - netflow version, 5 or 9 (default 5)\n");
6031 fprintf(ERROUT,"\n");
6032 fprintf(ERROUT,"Filters:\n");
6033 fprintf(ERROUT, " +v <vlans> - include vlans (e.g. +v 0-20,4091)\n");
6034 fprintf(ERROUT, " -v <vlans> - exclude vlans\n");
6035 fprintf(ERROUT, " -4 - listen on IPv4 socket only\n");
6036 fprintf(ERROUT, " -6 - listen on IPv6 socket only\n");
6037 fprintf(ERROUT, " +4 - listen on both IPv4 and IPv6 sockets\n");
6038 fprintf(ERROUT, "\n");
6039 fprintf(ERROUT, "=============== Advanced Tools ===========================================\n");
6040 fprintf(ERROUT, "| sFlow-RT (real time) - https://sflow-rt.com |\n");
6041 fprintf(ERROUT, "| sFlowTrend (FREE) - https://inmon.com/products/sFlowTrend.php |\n");
6042 fprintf(ERROUT, "| Traffic Sentinel - https://inmon.com/products/trafficsentinel.php |\n");
6043 fprintf(ERROUT, "==========================================================================\n");
6044 }
6045
6046 /*_________________---------------------------__________________
6047 _________________ process_command_line __________________
6048 -----------------___________________________------------------
6049 */
6050
process_command_line(int argc,char * argv[])6051 static void process_command_line(int argc, char *argv[])
6052 {
6053 int arg = 1, in = 0;
6054 int i;
6055 int plus,minus;
6056 size_t len_str;
6057
6058 /* set defaults */
6059 sfConfig.sFlowInputPort = 6343;
6060 sfConfig.netFlowVersion = 5;
6061 #ifdef _WIN32
6062 sfConfig.listen4 = YES;
6063 sfConfig.listen6 = NO;
6064 #else
6065 sfConfig.listen4 = NO;
6066 sfConfig.listen6 = YES;
6067 #endif
6068 sfConfig.keepGoing = NO;
6069
6070 /* walk though the args */
6071 while (arg < argc) {
6072 plus = (argv[arg][0] == '+');
6073 minus = (argv[arg][0] == '-');
6074 if(plus == NO && minus == NO) { instructions(*argv); exit(1); }
6075 in = argv[arg++][1];
6076 /* check first that options with/without arguments are correct */
6077 switch(in) {
6078 case 't':
6079 case 'T':
6080 case 'l':
6081 case 'g':
6082 case 'j':
6083 case 'J':
6084 case 'H':
6085 case 'x':
6086 case 'e':
6087 case 's':
6088 #ifdef SPOOFSOURCE
6089 case 'S':
6090 #endif
6091 case 'D':
6092 case '4':
6093 case '6':
6094 case 'k':
6095 case '?':
6096 case 'h':
6097 break;
6098 case 'L':
6099 case 'p':
6100 case 'r':
6101 case 'z':
6102 case 'c':
6103 case 'd':
6104 case 'f':
6105 case 'N':
6106 case 'v': if(arg < argc) break;
6107 default: instructions(*argv); exit(1);
6108 }
6109
6110 switch(in) {
6111 case 'p': sfConfig.sFlowInputPort = atoi(argv[arg++]); break;
6112 case 't': sfConfig.outputFormat = SFLFMT_PCAP; break;
6113 case 'T': sfConfig.outputFormat = SFLFMT_PCAP_DISCARD; break;
6114 case 'l': sfConfig.outputFormat = SFLFMT_LINE; break;
6115 case 'H': sfConfig.outputFormat = SFLFMT_CLF; break;
6116 case 'g': sfConfig.outputFormat = SFLFMT_SCRIPT; break;
6117 case 'j': sfConfig.outputFormat = SFLFMT_JSON; break;
6118 case 'J':
6119 sfConfig.outputFormat = SFLFMT_JSON;
6120 sfConfig.jsonIndent = YES;
6121 break;
6122 case 'L':
6123 sfConfig.outputFormat = SFLFMT_LINE_CUSTOM;
6124 parseFieldList(&sfConfig.outputFieldList, argv[arg++]);
6125 break;
6126 case 'r':
6127 len_str = strlen(argv[arg]); /* argv[arg] already null-terminated */
6128 sfConfig.readPcapFileName = my_calloc(len_str+1);
6129 memcpy(sfConfig.readPcapFileName, argv[arg++], len_str);
6130 break;
6131 case 'x': sfConfig.removeContent = YES; break;
6132 case 'c':
6133 if(setNetFlowCollector(argv[arg++]) == NO) exit(-8);
6134 sfConfig.outputFormat = SFLFMT_NETFLOW;
6135 break;
6136 case 'd':
6137 sfConfig.netFlowOutputPort = atoi(argv[arg++]);
6138 sfConfig.outputFormat = SFLFMT_NETFLOW;
6139 break;
6140 case 'e': sfConfig.netFlowPeerAS = YES; break;
6141 case 's': sfConfig.disableNetFlowScale = YES; break;
6142 #ifdef SPOOFSOURCE
6143 case 'S': sfConfig.spoofSource = YES; break;
6144 #endif
6145 case 'N':
6146 {
6147 sfConfig.netFlowVersion = atoi(argv[arg++]);
6148 switch(sfConfig.netFlowVersion) {
6149 case 5: sendNetFlowDatagram = sendNetFlowV5Datagram; break;
6150 case 9: sendNetFlowDatagram = sendNetFlowV9Datagram; break;
6151 default:
6152 fprintf(ERROUT, "invalid netflow version specified (use 5 or 9)\n");
6153 exit(-8);
6154 }
6155 }
6156 break;
6157 case 'f':
6158 if(addForwardingTarget(argv[arg++]) == NO) exit(-35);
6159 sfConfig.outputFormat = SFLFMT_FWD;
6160 break;
6161 case 'v':
6162 if(plus) {
6163 /* +v => include vlans */
6164 sfConfig.gotVlanFilter = YES;
6165 parseVlanFilter(sfConfig.vlanFilter, YES, argv[arg++]);
6166 }
6167 else {
6168 /* -v => exclude vlans */
6169 if(! sfConfig.gotVlanFilter) {
6170 /* when we start with an exclude list, that means the default should be YES */
6171 for(i = 0; i < FILTER_MAX_VLAN; i++) sfConfig.vlanFilter[i] = YES;
6172 sfConfig.gotVlanFilter = YES;
6173 }
6174 parseVlanFilter(sfConfig.vlanFilter, NO, argv[arg++]);
6175 }
6176 break;
6177 case '4':
6178 sfConfig.listenControlled = YES;
6179 sfConfig.listen4 = YES;
6180 sfConfig.listen6 = plus;
6181 break;
6182 case '6':
6183 sfConfig.listenControlled = YES;
6184 sfConfig.listen4 = NO;
6185 sfConfig.listen6 = YES;
6186 break;
6187 case 'k':
6188 sfConfig.keepGoing = YES;
6189 break;
6190 case 'D':
6191 sfConfig.allowDNS = YES;
6192 break;
6193 /* remaining are -h or -? */
6194 default: instructions(*argv); exit(0);
6195 }
6196 }
6197 }
6198
6199 /*_________________---------------------------__________________
6200 _________________ main __________________
6201 -----------------___________________________------------------
6202 */
6203
main(int argc,char * argv[])6204 int main(int argc, char *argv[])
6205 {
6206 int32_t soc4=-1,soc6=-1;
6207
6208 #ifdef _WIN32
6209 WSADATA wsadata;
6210 WSAStartup(0xffff, &wsadata);
6211 /* TODO: supposed to call WSACleanup() on termination */
6212 #endif
6213
6214 /* read the command line */
6215 process_command_line(argc, argv);
6216
6217 #ifdef _WIN32
6218 /* on windows we need to tell stdout if we want it to be binary */
6219 if(sfConfig.outputFormat == SFLFMT_PCAP
6220 || sfConfig.outputFormat == SFLFMT_PCAP_DISCARD)
6221 setmode(1, O_BINARY);
6222 #endif
6223
6224 /* reading from file or socket? */
6225 if(sfConfig.readPcapFileName) {
6226 if(strcmp(sfConfig.readPcapFileName, "-") == 0) sfConfig.readPcapFile = stdin;
6227 else sfConfig.readPcapFile = fopen(sfConfig.readPcapFileName, "rb");
6228 if(sfConfig.readPcapFile == NULL) {
6229 fprintf(ERROUT, "cannot open %s : %s\n", sfConfig.readPcapFileName, strerror(errno));
6230 exit(-1);
6231 }
6232 readPcapHeader();
6233 }
6234 else {
6235 /* open the input socket -- for now it's either a v4 or v6 socket, but in future
6236 we may allow both to be opened so that platforms that refuse to allow v4 packets
6237 to be received on a v6 socket can still get both. I think for that to really work,
6238 however, we will probably need to allow the bind() to be on a particular v4 or v6
6239 address. Otherwise it seems likely that we will get a clash(?) */
6240 if(sfConfig.listen6) {
6241 soc6 = openInputUDP6Socket(sfConfig.sFlowInputPort);
6242 }
6243 if(sfConfig.listen4 || (soc6 == -1 && !sfConfig.listenControlled)) {
6244 soc4 = openInputUDPSocket(sfConfig.sFlowInputPort);
6245 }
6246 if(soc4 == -1 && soc6 == -1) {
6247 fprintf(ERROUT, "unable to open UDP read socket\n");
6248 exit(-7);
6249 }
6250 }
6251
6252 /* possible open an output socket for netflow */
6253 if(sfConfig.netFlowOutputPort != 0
6254 && sfConfig.netFlowOutputIP.type != SFLADDRESSTYPE_UNDEFINED)
6255 openNetFlowSocket();
6256
6257 /* if tcpdump format, write the header */
6258 if(sfConfig.outputFormat == SFLFMT_PCAP
6259 || sfConfig.outputFormat == SFLFMT_PCAP_DISCARD)
6260 writePcapHeader();
6261 if(sfConfig.readPcapFile) {
6262 /* just use a blocking read */
6263 while(readPcapPacket(sfConfig.readPcapFile));
6264 }
6265 else {
6266 fd_set readfds;
6267 /* set the select mask */
6268 FD_ZERO(&readfds);
6269 /* loop reading packets */
6270 for(;;) {
6271 int nfds;
6272 struct timeval timeout;
6273 timeout.tv_sec = 0;
6274 timeout.tv_usec = 100000;
6275
6276 if(soc4 != -1) FD_SET(soc4, &readfds);
6277 if(soc6 != -1) FD_SET(soc6, &readfds);
6278
6279 nfds = select((soc4 > soc6 ? soc4 : soc6) + 1,
6280 &readfds,
6281 (fd_set *)NULL,
6282 (fd_set *)NULL,
6283 &timeout);
6284 /* we may return prematurely if a signal was caught, in which case
6285 * nfds will be -1 and errno will be set to EINTR. If we get any other
6286 * error, abort (unless keepGoing is set).
6287 */
6288 if(nfds < 0 && errno != EINTR) {
6289 fprintf(ERROUT, "select() returned %d\n", nfds);
6290 if(sfConfig.keepGoing) {
6291 /* we are going to try and keep going, but if we are going to do
6292 that we have to make sure we don't end up in a busy-loop or
6293 fill the disk with logging somewhere. The safest way is probably
6294 just to sleep here for a second before we go back and try again. */
6295 timeout.tv_sec = 1;
6296 timeout.tv_usec = 0;
6297 (void)select(1, NULL, NULL, NULL, &timeout);
6298 }
6299 else {
6300 exit(-9);
6301 }
6302 }
6303 if(nfds > 0) {
6304 if(soc4 != -1 && FD_ISSET(soc4, &readfds)) readPacket(soc4);
6305 if(soc6 != -1 && FD_ISSET(soc6, &readfds)) readPacket(soc6);
6306 }
6307 }
6308 }
6309 return 0;
6310 }
6311
6312
6313 #if defined(__cplusplus)
6314 } /* extern "C" */
6315 #endif
6316