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, &reg, 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, &reg, 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