1 /**
2 ** @internal
3 ** yafcore.c
4 ** YAF core I/O routines
5 **
6 ** ------------------------------------------------------------------------
7 ** Copyright (C) 2006-2019 Carnegie Mellon University. All Rights Reserved.
8 ** ------------------------------------------------------------------------
9 ** Authors: Brian Trammell, Chris Inacio, Emily Ecoff <ecoff@cert.org>
10 ** ------------------------------------------------------------------------
11 ** @OPENSOURCE_HEADER_START@
12 ** Use of the YAF system and related source code is subject to the terms
13 ** of the following licenses:
14 **
15 ** GNU Public License (GPL) Rights pursuant to Version 2, June 1991
16 ** Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
17 **
18 ** NO WARRANTY
19 **
20 ** ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER
21 ** PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY
22 ** PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN
23 ** "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
24 ** KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT
25 ** LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE,
26 ** MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE
27 ** OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT,
28 ** SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY
29 ** TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF
30 ** WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES.
31 ** LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF
32 ** CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON
33 ** CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE
34 ** DELIVERABLES UNDER THIS LICENSE.
35 **
36 ** Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie
37 ** Mellon University, its trustees, officers, employees, and agents from
38 ** all claims or demands made against them (and any related losses,
39 ** expenses, or attorney's fees) arising out of, or relating to Licensee's
40 ** and/or its sub licensees' negligent use or willful misuse of or
41 ** negligent conduct or willful misconduct regarding the Software,
42 ** facilities, or other rights or assistance granted by Carnegie Mellon
43 ** University under this License, including, but not limited to, any
44 ** claims of product liability, personal injury, death, damage to
45 ** property, or violation of any laws or regulations.
46 **
47 ** Carnegie Mellon University Software Engineering Institute authored
48 ** documents are sponsored by the U.S. Department of Defense under
49 ** Contract FA8721-05-C-0003. Carnegie Mellon University retains
50 ** copyrights in all material produced under this contract. The U.S.
51 ** Government retains a non-exclusive, royalty-free license to publish or
52 ** reproduce these documents, or allow others to do so, for U.S.
53 ** Government purposes only pursuant to the copyright license under the
54 ** contract clause at 252.227.7013.
55 **
56 ** @OPENSOURCE_HEADER_END@
57 ** ------------------------------------------------------------------------
58 */
59
60 #define _YAF_SOURCE_
61 #include "yafctx.h"
62 #include <yaf/yafcore.h>
63 #include <yaf/decode.h>
64 #include <airframe/airutil.h>
65 #include <yaf/yafrag.h>
66
67 #define INFOMODEL_EXCLUDE_yaf_dpi 1
68 #define INFOMODEL_EXCLUDE_yaf_dhcp 1
69 #include "infomodel.h"
70
71 #ifdef YAF_ENABLE_HOOKS
72 #include <yaf/yafhooks.h>
73 #endif
74
75 #define FBSTMLINIT(s, i, t) fbSubTemplateMultiListEntryInit(s, i, t, 1)
76 #define FBSTMLNEXT(p, s) fbSubTemplateMultiListGetNextEntry(p, s)
77
78 /** These are the template ID's for the templates that YAF uses to
79 select the output. Template ID's are maintained for a set of
80 basic flow types data
81 * BASE which gets various additions added as the flow requires,
82 * FULL base plus the internal fields are added
83 * EXT (extended) which has the additional records in the
84 yaf_extime_spec (extended time specification)
85
86 WARNING: these need to be adjusted according to changes in the
87 general & special dimensions */
88 #define YAF_FLOW_BASE_TID 0xB000 /* no general or special definitions */
89 #define YAF_FLOW_FULL_TID 0xB800 /* base no internal*/
90 #define YAF_FLOW_EXT_TID 0xB7FF /* everything except internal */
91
92 #define YAF_PROCESS_STATS_TID 0xD003
93 #define YAF_TOMBSTONE_TID 0xD004
94 #define YAF_TOMBSTONE_ACCESS_TID 0xD005
95 #define YAF_TYPE_METADATA_TID 0xD006
96 #define YAF_TEMPLATE_METADATA_TID 0xD007
97
98
99 #define YAF_FLOW_BASE_NAME "yaf_flow_base"
100 #define YAF_FLOW_FULL_NAME "yaf_flow_full"
101 #define YAF_FLOW_EXT_NAME "yaf_flow_ext"
102
103 #define YAF_PROCESS_STATS_NAME "yaf_process_stats"
104 #define YAF_TOMBSTONE_NAME "tombstone_record"
105 #define YAF_TOMBSTONE_ACCESS_NAME "tombstone_access"
106
107 /* 49154 - 49160 */
108 #define YAF_APP_FLOW_TID 0xC001 /* not used */
109 #define YAF_ENTROPY_FLOW_TID 0xC002
110 #define YAF_TCP_FLOW_TID 0xC003
111 #define YAF_MAC_FLOW_TID 0xC004
112 #define YAF_STATS_FLOW_TID 0xC005
113 #define YAF_P0F_FLOW_TID 0xC006
114 #define YAF_FPEXPORT_FLOW_TID 0xC007
115 #define YAF_PAYLOAD_FLOW_TID 0xC008
116 #define YAF_MPTCP_FLOW_TID 0xC009
117
118 #define YAF_APP_FLOW_NAME "UNUSED" /* not used */
119 #define YAF_ENTROPY_FLOW_NAME "yaf_entropy"
120 #define YAF_ENTROPY_FLOW_REV_NAME "yaf_entropy_rev"
121 #define YAF_TCP_FLOW_NAME "yaf_tcp"
122 #define YAF_TCP_FLOW_REV_NAME "yaf_tcp_rev"
123 #define YAF_MAC_FLOW_NAME "yaf_mac"
124 #define YAF_STATS_FLOW_NAME "yaf_flow_stats"
125 #define YAF_STATS_FLOW_REV_NAME "yaf_flow_stats_rev"
126 #define YAF_P0F_FLOW_NAME "yaf_p0f"
127 #define YAF_P0F_FLOW_REV_NAME "yaf_p0f_rev"
128 #define YAF_FPEXPORT_FLOW_NAME "yaf_fpexport"
129 #define YAF_FPEXPORT_FLOW_REV_NAME "yaf_fpexport_rev"
130 #define YAF_PAYLOAD_FLOW_NAME "yaf_payload"
131 #define YAF_PAYLOAD_FLOW_REV_NAME "yaf_payload_rev"
132 #define YAF_MPTCP_FLOW_NAME "yaf_mptcp"
133 #define YAF_MPTCP_FLOW_REV_NAME "yaf_mptcp_rev"
134
135 /** The dimensions are flags which determine which sets of fields will
136 be exported out to an IPFIX record. They are entries in a bitmap
137 used to control the template. e.g. TCP flow information (seq num,
138 tcp flags, etc.) only get added to the output record when the
139 YTF_SILK flag is set; it only gets set when the transport protocol
140 is set to 0x06 and YAF is ran with --silk. */
141
142 /** General dimensions */
143 #define YTF_BIF 0x0010
144 /* Special dimensions */
145 #define YTF_TOTAL 0x0001
146 #define YTF_DELTA 0x0002
147 #define YTF_MPLS 0x0004
148 #define YTF_SILK 0x0020
149 #define YTF_DAGIF 0x0040
150 #define YTF_FLE 0x0080
151 #define YTF_RLE 0x0100
152 #define YTF_IP4 0x0200
153 #define YTF_IP6 0x0400
154 #define YTF_INTERNAL 0x0800
155 #define YTF_ALL 0x0EFF /* this has to be everything _except_ RLE enabled */
156 #define YTF_REV 0xFF0F
157
158 #define YTF_BIF_NAME "bif"
159 #define YTF_TOTAL_NAME "total"
160 #define YTF_DELTA_NAME "delta"
161 #define YTF_MPLS_NAME "mpls"
162 #define YTF_SILK_NAME "silk"
163 #define YTF_DAGIF_NAME "dagif"
164 #define YTF_FLE_NAME "fle"
165 #define YTF_RLE_NAME "rle"
166 #define YTF_IP4_NAME "ip4"
167 #define YTF_IP6_NAME "ip6"
168 #define YTF_INTERNAL_NAME "internal"
169 #define YTF_ALL_NAME "all"
170 #define YTF_REV_NAME "rev"
171
172 /** If any of the FLE/RLE values are larger than this constant
173 then we have to use FLE, otherwise, we choose RLE to
174 conserve space/bandwidth etc.*/
175 #define YAF_RLEMAX (1L << 31)
176
177 #define YF_PRINT_DELIM "|"
178
179 /** include the CERT IE extensions for YAF */
180 #define INFOMODEL_EXCLUDE_yaf_dpi 1
181 #define INFOMODEL_EXCLUDE_yaf_dhcp 1
182 #include "infomodel.h"
183
184 /* IPFIX definition of the full YAF flow record */
185 static fbInfoElementSpec_t yaf_flow_spec[] = {
186 /* Millisecond start and end (epoch) (native time) */
187 { "flowStartMilliseconds", 8, 0 },
188 { "flowEndMilliseconds", 8, 0 },
189 /* Counters */
190 { "octetTotalCount", 8, YTF_FLE | YTF_TOTAL },
191 { "reverseOctetTotalCount", 8, YTF_FLE | YTF_TOTAL | YTF_BIF },
192 { "packetTotalCount", 8, YTF_FLE | YTF_TOTAL },
193 { "reversePacketTotalCount", 8, YTF_FLE | YTF_TOTAL | YTF_BIF },
194 /* delta Counters */
195 { "octetDeltaCount", 8, YTF_FLE | YTF_DELTA },
196 { "reverseOctetDeltaCount", 8, YTF_FLE | YTF_DELTA | YTF_BIF },
197 { "packetDeltaCount", 8, YTF_FLE | YTF_DELTA },
198 { "reversePacketDeltaCount", 8, YTF_FLE | YTF_DELTA | YTF_BIF },
199 /* Reduced-length counters */
200 { "octetTotalCount", 4, YTF_RLE | YTF_TOTAL },
201 { "reverseOctetTotalCount", 4, YTF_RLE | YTF_TOTAL| YTF_BIF },
202 { "packetTotalCount", 4, YTF_RLE | YTF_TOTAL },
203 { "reversePacketTotalCount", 4, YTF_RLE | YTF_TOTAL | YTF_BIF },
204 /* Reduced-length delta counters */
205 { "octetDeltaCount", 4, YTF_RLE | YTF_DELTA },
206 { "reverseOctetDeltaCount", 4, YTF_RLE | YTF_DELTA | YTF_BIF },
207 { "packetDeltaCount", 4, YTF_RLE | YTF_DELTA },
208 { "reversePacketDeltaCount", 4, YTF_RLE | YTF_DELTA | YTF_BIF },
209 /* 5-tuple and flow status */
210 { "sourceIPv6Address", 16, YTF_IP6 },
211 { "destinationIPv6Address", 16, YTF_IP6 },
212 { "sourceIPv4Address", 4, YTF_IP4 },
213 { "destinationIPv4Address", 4, YTF_IP4 },
214 { "sourceTransportPort", 2, 0 },
215 { "destinationTransportPort", 2, 0 },
216 { "flowAttributes", 2, 0 },
217 { "reverseFlowAttributes", 2, YTF_BIF },
218 { "protocolIdentifier", 1, 0 },
219 { "flowEndReason", 1, 0 },
220 #if defined(YAF_ENABLE_APPLABEL)
221 { "silkAppLabel", 2, 0 },
222 #else
223 { "paddingOctets", 2, YTF_INTERNAL },
224 #endif
225 /* Round-trip time */
226 { "reverseFlowDeltaMilliseconds", 4, YTF_BIF }, /* 32-bit */
227 /*TCP Info would need to go here 4 SiLK & 4b padding*/
228 { "tcpSequenceNumber", 4, YTF_SILK },
229 { "reverseTcpSequenceNumber", 4, YTF_SILK | YTF_BIF },
230 { "initialTCPFlags", 1, YTF_SILK },
231 { "unionTCPFlags", 1, YTF_SILK },
232 { "reverseInitialTCPFlags", 1, YTF_SILK | YTF_BIF },
233 { "reverseUnionTCPFlags", 1, YTF_SILK | YTF_BIF },
234 { "vlanId", 2, 0 },
235 { "reverseVlanId", 2, YTF_BIF },
236 { "ingressInterface", 4, YTF_DAGIF },
237 { "egressInterface", 4, YTF_DAGIF },
238 { "ipClassOfService", 1, 0 },
239 { "reverseIpClassOfService", 1, YTF_BIF },
240 { "mplsTopLabelStackSection", 3, YTF_MPLS },
241 { "mplsLabelStackSection2", 3, YTF_MPLS },
242 { "mplsLabelStackSection3", 3, YTF_MPLS },
243 #if defined(YAF_ENABLE_NDPI)
244 { "paddingOctets", 1, YTF_INTERNAL },
245 { "nDPIL7Protocol", 2, 0 },
246 { "nDPIL7SubProtocol", 2, 0 },
247 #else
248 { "paddingOctets", 5, YTF_INTERNAL },
249 #endif
250 { "subTemplateMultiList", FB_IE_VARLEN, 0 },
251 FB_IESPEC_NULL
252 };
253
254
255 # if defined(YAF_ENABLE_ENTROPY)
256 /* entropy fields */
257 static fbInfoElementSpec_t yaf_entropy_spec[] = {
258 { "payloadEntropy", 1, 0 },
259 { "reversePayloadEntropy", 1, YTF_BIF },
260 FB_IESPEC_NULL
261 };
262 #endif
263
264 static fbInfoElementSpec_t yaf_tcp_spec[] = {
265 /* TCP-specific information */
266 { "tcpSequenceNumber", 4, 0 },
267 { "initialTCPFlags", 1, 0 },
268 { "unionTCPFlags", 1, 0 },
269 { "reverseInitialTCPFlags", 1, YTF_BIF },
270 { "reverseUnionTCPFlags", 1, YTF_BIF },
271 { "reverseTcpSequenceNumber", 4, YTF_BIF },
272 FB_IESPEC_NULL
273 };
274
275 /* MAC-specific information */
276 static fbInfoElementSpec_t yaf_mac_spec[] = {
277 { "sourceMacAddress", 6, 0 },
278 { "destinationMacAddress", 6, 0 },
279 FB_IESPEC_NULL
280 };
281
282 static fbInfoElementSpec_t yaf_mptcp_spec[] = {
283 { "mptcpInitialDataSequenceNumber", 8, 0 },
284 { "mptcpReceiverToken", 4, 0 },
285 { "mptcpMaximumSegmentSize", 2, 0 },
286 { "mptcpAddressID", 1, 0 },
287 { "mptcpFlags", 1, 0 },
288 FB_IESPEC_NULL
289 };
290
291
292 # if YAF_ENABLE_P0F
293 static fbInfoElementSpec_t yaf_p0f_spec[] = {
294 { "osName", FB_IE_VARLEN, 0 },
295 { "osVersion", FB_IE_VARLEN, 0 },
296 { "osFingerPrint", FB_IE_VARLEN, 0 },
297 { "reverseOsName", FB_IE_VARLEN, YTF_BIF },
298 { "reverseOsVersion", FB_IE_VARLEN, YTF_BIF },
299 { "reverseOsFingerPrint", FB_IE_VARLEN, YTF_BIF },
300 FB_IESPEC_NULL
301 };
302 # endif
303
304 # if YAF_ENABLE_FPEXPORT
305 static fbInfoElementSpec_t yaf_fpexport_spec[] = {
306 { "firstPacketBanner", FB_IE_VARLEN, 0 },
307 { "secondPacketBanner", FB_IE_VARLEN, 0 },
308 { "reverseFirstPacketBanner", FB_IE_VARLEN, YTF_BIF },
309 FB_IESPEC_NULL
310 };
311 # endif
312
313 # if YAF_ENABLE_PAYLOAD
314 /* Variable-length payload fields */
315 static fbInfoElementSpec_t yaf_payload_spec[] = {
316 { "payload", FB_IE_VARLEN, 0 },
317 { "reversePayload", FB_IE_VARLEN, YTF_BIF },
318 FB_IESPEC_NULL
319 };
320 # endif
321
322 /* IPFIX definition of the YAF flow record time extension */
323 static fbInfoElementSpec_t yaf_extime_spec[] = {
324 /* Microsecond start and end (RFC1305-style) (extended time) */
325 { "flowStartMicroseconds", 8, 0 },
326 { "flowEndMicroseconds", 8, 0 },
327 /* Second start, end, and duration (extended time) */
328 { "flowStartSeconds", 4, 0 },
329 { "flowEndSeconds", 4, 0 },
330 /* Flow durations (extended time) */
331 { "flowDurationMicroseconds", 4, 0 },
332 { "flowDurationMilliseconds", 4, 0 },
333 /* Microsecond delta start and end (extended time) */
334 { "flowStartDeltaMicroseconds", 4, 0 },
335 { "flowEndDeltaMicroseconds", 4, 0 },
336 FB_IESPEC_NULL
337 };
338
339 static fbInfoElementSpec_t yaf_process_stats_spec[] = {
340 { "observationDomainId", 4, 0 },
341 { "exportingProcessId", 4, 0 },
342 { "exporterIPv4Address", 4, 0 },
343 { "observationTimeSeconds", 4, 0 },
344 { "systemInitTimeMilliseconds", 8, 0 },
345 { "exportedFlowRecordTotalCount", 8, 0 },
346 { "packetTotalCount", 8, 0 },
347 { "droppedPacketTotalCount", 8, 0 },
348 { "ignoredPacketTotalCount", 8, 0 },
349 { "notSentPacketTotalCount", 8, 0 },
350 { "expiredFragmentCount", 4, 0 },
351 { "assembledFragmentCount", 4, 0 },
352 { "flowTableFlushEventCount", 4, 0 },
353 { "flowTablePeakCount", 4, 0 },
354 { "meanFlowRate", 4, 0 },
355 { "meanPacketRate", 4, 0 },
356 FB_IESPEC_NULL
357 };
358
359 static fbInfoElementSpec_t yaf_tombstone_spec[] = {
360 { "observationDomainId", 4, 0 },
361 { "exportingProcessId", 4, 0 },
362 { "exporterConfiguredId", 2, 0 },
363 { "paddingOctets", 6, 0 },
364 { "tombstoneId", 4, 0 },
365 { "observationTimeSeconds", 4, 0 },
366 { "tombstoneAccessList", FB_IE_VARLEN, 0 },
367 FB_IESPEC_NULL
368 };
369
370 static fbInfoElementSpec_t yaf_tombstone_access_spec[] = {
371 { "certToolId", 4, 0 },
372 { "observationTimeSeconds", 4, 0 },
373 FB_IESPEC_NULL
374 };
375
376 static fbInfoElementSpec_t yaf_flow_stats_spec[] = {
377 { "dataByteCount", 8, 0 },
378 { "averageInterarrivalTime", 8, 0 },
379 { "standardDeviationInterarrivalTime", 8, 0 },
380 { "tcpUrgTotalCount", 4, 0 },
381 { "smallPacketCount", 4, 0 },
382 { "nonEmptyPacketCount", 4, 0 },
383 { "largePacketCount", 4, 0 },
384 { "firstNonEmptyPacketSize", 2, 0 },
385 { "maxPacketSize", 2, 0 },
386 { "standardDeviationPayloadLength", 2, 0 },
387 { "firstEightNonEmptyPacketDirections", 1, 0 },
388 { "paddingOctets", 1, 1 },
389 { "reverseDataByteCount", 8, YTF_BIF },
390 { "reverseAverageInterarrivalTime", 8, YTF_BIF },
391 { "reverseStandardDeviationInterarrivalTime", 8, YTF_BIF },
392 { "reverseTcpUrgTotalCount", 4, YTF_BIF },
393 { "reverseSmallPacketCount", 4, YTF_BIF },
394 { "reverseNonEmptyPacketCount", 4, YTF_BIF },
395 { "reverseLargePacketCount", 4, YTF_BIF },
396 { "reverseFirstNonEmptyPacketSize", 2, YTF_BIF },
397 { "reverseMaxPacketSize", 2, YTF_BIF },
398 { "reverseStandardDeviationPayloadLength", 2, YTF_BIF },
399 { "paddingOctets", 2, 1 },
400 FB_IESPEC_NULL
401 };
402
403
404 typedef struct yfFlowStatsRecord_st {
405 uint64_t dataByteCount;
406 uint64_t averageInterarrivalTime;
407 uint64_t standardDeviationInterarrivalTime;
408 uint32_t tcpUrgTotalCount;
409 uint32_t smallPacketCount;
410 uint32_t nonEmptyPacketCount;
411 uint32_t largePacketCount;
412 uint16_t firstNonEmptyPacketSize;
413 uint16_t maxPacketSize;
414 uint16_t standardDeviationPayloadLength;
415 uint8_t firstEightNonEmptyPacketDirections;
416 uint8_t padding[1];
417 /* reverse Fields */
418 uint64_t reverseDataByteCount;
419 uint64_t reverseAverageInterarrivalTime;
420 uint64_t reverseStandardDeviationInterarrivalTime;
421 uint32_t reverseTcpUrgTotalCount;
422 uint32_t reverseSmallPacketCount;
423 uint32_t reverseNonEmptyPacketCount;
424 uint32_t reverseLargePacketCount;
425 uint16_t reverseFirstNonEmptyPacketSize;
426 uint16_t reverseMaxPacketSize;
427 uint16_t reverseStandardDeviationPayloadLength;
428 uint8_t padding2[2];
429 } yfFlowStatsRecord_t;
430
431 typedef struct yfTemplates_st {
432 fbTemplate_t *ipfixStatsTemplate;
433 fbTemplate_t *tombstoneRecordTemplate;
434 fbTemplate_t *tombstoneAccessTemplate;
435 fbTemplate_t *fstatsTemplate;
436 fbTemplate_t *revfstatsTemplate;
437 #if YAF_ENABLE_ENTROPY
438 fbTemplate_t *entropyTemplate;
439 fbTemplate_t *revEntropyTemplate;
440 #endif
441 fbTemplate_t *tcpTemplate;
442 fbTemplate_t *revTcpTemplate;
443 fbTemplate_t *macTemplate;
444 fbTemplate_t *mptcpTemplate;
445 #if YAF_ENABLE_P0F
446 fbTemplate_t *p0fTemplate;
447 fbTemplate_t *revP0fTemplate;
448 #endif
449 #if YAF_ENABLE_FPEXPORT
450 fbTemplate_t *fpexportTemplate;
451 fbTemplate_t *revFpexportTemplate;
452 #endif
453 #if YAF_ENABLE_PAYLOAD
454 fbTemplate_t *payloadTemplate;
455 fbTemplate_t *revPayloadTemplate;
456 #endif
457 } yfTemplates_t;
458
459 static yfTemplates_t yaf_tmpl;
460
461 /* IPv6-mapped IPv4 address prefix */
462 static uint8_t yaf_ip6map_pfx[12] =
463 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
464
465 /* Full YAF flow record. */
466 typedef struct yfIpfixFlow_st {
467 uint64_t flowStartMilliseconds;
468 uint64_t flowEndMilliseconds;
469 uint64_t octetTotalCount;
470 uint64_t reverseOctetTotalCount;
471 uint64_t packetTotalCount;
472 uint64_t reversePacketTotalCount;
473 uint64_t octetDeltaCount;
474 uint64_t reverseOctetDeltaCount;
475 uint64_t packetDeltaCount;
476 uint64_t reversePacketDeltaCount;
477 uint8_t sourceIPv6Address[16];
478 uint8_t destinationIPv6Address[16];
479 uint32_t sourceIPv4Address;
480 uint32_t destinationIPv4Address;
481 uint16_t sourceTransportPort;
482 uint16_t destinationTransportPort;
483 uint16_t flowAttributes;
484 uint16_t reverseFlowAttributes;
485 uint8_t protocolIdentifier;
486 uint8_t flowEndReason;
487 #if YAF_ENABLE_APPLABEL
488 uint16_t silkAppLabel;
489 #else
490 uint8_t paddingOctets[2];
491 #endif
492 int32_t reverseFlowDeltaMilliseconds;
493 /* TCP stuff for SiLK */
494 uint32_t tcpSequenceNumber;
495 uint32_t reverseTcpSequenceNumber;
496 uint8_t initialTCPFlags;
497 uint8_t unionTCPFlags;
498 uint8_t reverseInitialTCPFlags;
499 uint8_t reverseUnionTCPFlags;
500 /* MAC Specific Info */
501 uint16_t vlanId;
502 uint16_t reverseVlanId;
503 uint32_t ingressInterface;
504 uint32_t egressInterface;
505 /* MPLS! */
506 uint8_t ipClassOfService;
507 uint8_t reverseIpClassOfService;
508 uint8_t mpls_label1[3];
509 uint8_t mpls_label2[3];
510 uint8_t mpls_label3[3];
511 #if YAF_ENABLE_NDPI
512 uint8_t paddingOctets2[1];
513 uint16_t ndpi_master;
514 uint16_t ndpi_sub;
515 #else
516 uint8_t paddingOctets3[5];
517 #endif
518 fbSubTemplateMultiList_t subTemplateMultiList;
519 } yfIpfixFlow_t;
520
521
522 #if YAF_ENABLE_ENTROPY
523 typedef struct yfEntropyFlow_st {
524 uint8_t entropy;
525 uint8_t reverseEntropy;
526 } yfEntropyFlow_t;
527 #endif
528
529 typedef struct yfTcpFlow_st {
530 uint32_t tcpSequenceNumber;
531 uint8_t initialTCPFlags;
532 uint8_t unionTCPFlags;
533 uint8_t reverseInitialTCPFlags;
534 uint8_t reverseUnionTCPFlags;
535 uint32_t reverseTcpSequenceNumber;
536 } yfTcpFlow_t;
537
538 typedef struct yfMacFlow_st {
539 uint8_t sourceMacAddress[6];
540 uint8_t destinationMacAddress[6];
541 } yfMacFlow_t;
542
543 # if YAF_ENABLE_P0F
544 typedef struct yfP0fFlow_st {
545 fbVarfield_t osName;
546 fbVarfield_t osVersion;
547 fbVarfield_t osFingerPrint;
548 fbVarfield_t reverseOsName;
549 fbVarfield_t reverseOsVersion;
550 fbVarfield_t reverseOsFingerPrint;
551 } yfP0fFlow_t;
552 # endif
553
554 # if YAF_ENABLE_FPEXPORT
555 typedef struct yfFPExportFlow_st {
556 fbVarfield_t firstPacketBanner;
557 fbVarfield_t secondPacketBanner;
558 fbVarfield_t reverseFirstPacketBanner;
559 } yfFPExportFlow_t;
560 # endif
561
562 # if YAF_ENABLE_PAYLOAD
563 typedef struct yfPayloadFlow_st {
564 fbVarfield_t payload;
565 fbVarfield_t reversePayload;
566 } yfPayloadFlow_t;
567 # endif
568
569 typedef struct yfIpfixExtFlow_st {
570 yfIpfixFlow_t f;
571 uint64_t flowStartMicroseconds;
572 uint64_t flowEndMicroseconds;
573 uint32_t flowStartSeconds;
574 uint32_t flowEndSeconds;
575 uint32_t flowDurationMicroseconds;
576 uint32_t flowDurationMilliseconds;
577 uint32_t flowStartDeltaMicroseconds;
578 uint32_t flowEndDeltaMicroseconds;
579 } yfIpfixExtFlow_t;
580
581 typedef struct yfIpfixStats_st {
582 uint32_t observationDomainId;
583 uint32_t exportingProcessId;
584 uint32_t exporterIPv4Address;
585 uint32_t observationTimeSeconds;
586 uint64_t systemInitTimeMilliseconds;
587 uint64_t exportedFlowTotalCount;
588 uint64_t packetTotalCount;
589 uint64_t droppedPacketTotalCount;
590 uint64_t ignoredPacketTotalCount;
591 uint64_t notSentPacketTotalCount;
592 uint32_t expiredFragmentCount;
593 uint32_t assembledFragmentCount;
594 uint32_t flowTableFlushEvents;
595 uint32_t flowTablePeakCount;
596 uint32_t meanFlowRate;
597 uint32_t meanPacketRate;
598 } yfIpfixStats_t;
599
600 typedef struct yfTombstoneRecord_st {
601 uint32_t observationDomainId;
602 uint32_t exportingProcessId;
603 uint16_t exporterConfiguredId;
604 uint8_t paddingOctets[6];
605 uint32_t tombstoneId;
606 uint32_t observationTimeSeconds;
607 fbSubTemplateList_t accessList;
608 } yfTombstoneRecord_t;
609
610 typedef struct yfTombstoneAccess_st {
611 uint32_t certToolId;
612 uint32_t observationTimeSeconds;
613 } yfTombstoneAccess_t;
614
615 /* Core library configuration variables */
616 static int yaf_core_export_payload = 0;
617 static gboolean yaf_core_map_ipv6 = FALSE;
618
619 /**
620 * yfAlignmentCheck
621 *
622 * this checks the alignment of the template and corresponding record
623 * ideally, all this magic would happen at compile time, but it
624 * doesn't currently, (can't really do it in C,) so we do it at
625 * run time
626 *
627 *
628 * @param err a Glib error structure pointer initialized with an
629 * empty error on input, if an alignment error is detected
630 * then a new error will be put into the pointer.
631 *
632 */
yfAlignmentCheck()633 void yfAlignmentCheck()
634 {
635 size_t prevOffset = 0;
636 size_t prevSize = 0;
637
638 #define DO_SIZE(S_,F_) (SIZE_T_CAST)sizeof(((S_ *)(0))->F_)
639 #define EA_STRING(S_,F_) "alignment error in struct " #S_ " for element " \
640 #F_ " offset %#"SIZE_T_FORMATX" size %" \
641 SIZE_T_FORMAT" (pad %"SIZE_T_FORMAT")", \
642 (SIZE_T_CAST)offsetof(S_,F_), DO_SIZE(S_,F_), \
643 (SIZE_T_CAST)(offsetof(S_,F_) % DO_SIZE(S_,F_))
644 #define EG_STRING(S_,F_) "gap error in struct " #S_ " for element " #F_ \
645 " offset %#"SIZE_T_FORMATX" size %"SIZE_T_FORMAT, \
646 (SIZE_T_CAST)offsetof(S_,F_), \
647 DO_SIZE(S_,F_)
648 #define RUN_CHECKS(S_,F_,A_) { \
649 if (((offsetof(S_,F_) % DO_SIZE(S_,F_)) != 0) && A_) { \
650 g_error(EA_STRING(S_,F_)); \
651 } \
652 if (offsetof(S_,F_) != (prevOffset+prevSize)) { \
653 g_error(EG_STRING(S_,F_)); \
654 return; \
655 } \
656 prevOffset = offsetof(S_,F_); \
657 prevSize = DO_SIZE(S_,F_); \
658 /* fprintf(stderr, "%17s %40s %#5lx %3d %#5lx\n", #S_, #F_, \
659 offsetof(S_,F_), DO_SIZE(S_,F_), \
660 offsetof(S_,F_)+DO_SIZE(S_,F_));*/ \
661 }
662
663 RUN_CHECKS(yfIpfixFlow_t,flowStartMilliseconds,1);
664 RUN_CHECKS(yfIpfixFlow_t,flowEndMilliseconds,1);
665 RUN_CHECKS(yfIpfixFlow_t,octetTotalCount,1);
666 RUN_CHECKS(yfIpfixFlow_t,reverseOctetTotalCount,1);
667 RUN_CHECKS(yfIpfixFlow_t,packetTotalCount,1);
668 RUN_CHECKS(yfIpfixFlow_t,reversePacketTotalCount,1);
669 RUN_CHECKS(yfIpfixFlow_t,octetDeltaCount,1);
670 RUN_CHECKS(yfIpfixFlow_t,reverseOctetDeltaCount,1);
671 RUN_CHECKS(yfIpfixFlow_t,packetDeltaCount,1);
672 RUN_CHECKS(yfIpfixFlow_t,reversePacketDeltaCount,1);
673 RUN_CHECKS(yfIpfixFlow_t,sourceIPv6Address,1);
674 RUN_CHECKS(yfIpfixFlow_t,destinationIPv6Address,1);
675 RUN_CHECKS(yfIpfixFlow_t,sourceIPv4Address,1);
676 RUN_CHECKS(yfIpfixFlow_t,destinationIPv4Address,1);
677 RUN_CHECKS(yfIpfixFlow_t,sourceTransportPort,1);
678 RUN_CHECKS(yfIpfixFlow_t,destinationTransportPort,1);
679 RUN_CHECKS(yfIpfixFlow_t,flowAttributes,1);
680 RUN_CHECKS(yfIpfixFlow_t,reverseFlowAttributes,1);
681 RUN_CHECKS(yfIpfixFlow_t,protocolIdentifier,1);
682 RUN_CHECKS(yfIpfixFlow_t,flowEndReason,1);
683 #if YAF_ENABLE_APPLABEL
684 RUN_CHECKS(yfIpfixFlow_t,silkAppLabel,1);
685 #else
686 RUN_CHECKS(yfIpfixFlow_t,paddingOctets,0);
687 #endif
688 RUN_CHECKS(yfIpfixFlow_t,reverseFlowDeltaMilliseconds,1);
689
690 /* TCP stuff for SiLK only! */
691 RUN_CHECKS(yfIpfixFlow_t,tcpSequenceNumber,1);
692 RUN_CHECKS(yfIpfixFlow_t,reverseTcpSequenceNumber,1);
693 RUN_CHECKS(yfIpfixFlow_t,initialTCPFlags,1);
694 RUN_CHECKS(yfIpfixFlow_t,unionTCPFlags,1);
695 RUN_CHECKS(yfIpfixFlow_t,reverseInitialTCPFlags,1);
696 RUN_CHECKS(yfIpfixFlow_t,reverseUnionTCPFlags,1);
697
698 RUN_CHECKS(yfIpfixFlow_t,vlanId,1);
699 RUN_CHECKS(yfIpfixFlow_t,reverseVlanId,1);
700
701 RUN_CHECKS(yfIpfixFlow_t,ingressInterface,1);
702 RUN_CHECKS(yfIpfixFlow_t,egressInterface,1);
703
704 RUN_CHECKS(yfIpfixFlow_t,ipClassOfService,1);
705 RUN_CHECKS(yfIpfixFlow_t,reverseIpClassOfService,1);
706 RUN_CHECKS(yfIpfixFlow_t,mpls_label1,1);
707 RUN_CHECKS(yfIpfixFlow_t,mpls_label2,1);
708 RUN_CHECKS(yfIpfixFlow_t,mpls_label3,1);
709 #if YAF_ENABLE_NDPI
710 RUN_CHECKS(yfIpfixFlow_t,paddingOctets2,0);
711 RUN_CHECKS(yfIpfixFlow_t,ndpi_master,1);
712 RUN_CHECKS(yfIpfixFlow_t,ndpi_sub,1);
713 #else
714 RUN_CHECKS(yfIpfixFlow_t,paddingOctets3,0);
715 #endif
716 RUN_CHECKS(yfIpfixFlow_t,subTemplateMultiList,0);
717 prevOffset = 0;
718 prevSize = 0;
719
720 RUN_CHECKS(yfIpfixExtFlow_t,f,1);
721 RUN_CHECKS(yfIpfixExtFlow_t,flowStartMicroseconds,1);
722 RUN_CHECKS(yfIpfixExtFlow_t,flowEndMicroseconds,1);
723 RUN_CHECKS(yfIpfixExtFlow_t,flowStartSeconds,1);
724 RUN_CHECKS(yfIpfixExtFlow_t,flowEndSeconds,1);
725 RUN_CHECKS(yfIpfixExtFlow_t,flowDurationMicroseconds,1);
726 RUN_CHECKS(yfIpfixExtFlow_t,flowDurationMilliseconds,1);
727 RUN_CHECKS(yfIpfixExtFlow_t,flowStartDeltaMicroseconds,1);
728 RUN_CHECKS(yfIpfixExtFlow_t,flowEndDeltaMicroseconds,1);
729 prevOffset = 0;
730 prevSize = 0;
731
732 RUN_CHECKS(yfIpfixStats_t, observationDomainId, 1);
733 RUN_CHECKS(yfIpfixStats_t, exportingProcessId, 1);
734 RUN_CHECKS(yfIpfixStats_t, exporterIPv4Address,1);
735 RUN_CHECKS(yfIpfixStats_t, observationTimeSeconds, 1);
736 RUN_CHECKS(yfIpfixStats_t, systemInitTimeMilliseconds,1);
737 RUN_CHECKS(yfIpfixStats_t, exportedFlowTotalCount,1);
738 RUN_CHECKS(yfIpfixStats_t, packetTotalCount, 1);
739 RUN_CHECKS(yfIpfixStats_t, droppedPacketTotalCount,1);
740 RUN_CHECKS(yfIpfixStats_t, ignoredPacketTotalCount, 1);
741 RUN_CHECKS(yfIpfixStats_t, notSentPacketTotalCount, 1);
742 RUN_CHECKS(yfIpfixStats_t, expiredFragmentCount,1);
743 RUN_CHECKS(yfIpfixStats_t, assembledFragmentCount,1);
744 RUN_CHECKS(yfIpfixStats_t, flowTableFlushEvents,1);
745 RUN_CHECKS(yfIpfixStats_t, flowTablePeakCount,1);
746 RUN_CHECKS(yfIpfixStats_t, meanFlowRate, 1);
747 RUN_CHECKS(yfIpfixStats_t, meanPacketRate, 1);
748
749 prevOffset = 0;
750 prevSize = 0;
751
752 RUN_CHECKS(yfTombstoneRecord_t, observationDomainId, 1);
753 RUN_CHECKS(yfTombstoneRecord_t, exportingProcessId, 1);
754 RUN_CHECKS(yfTombstoneRecord_t, exporterConfiguredId, 1);
755 RUN_CHECKS(yfTombstoneRecord_t, paddingOctets, 0);
756 RUN_CHECKS(yfTombstoneRecord_t, tombstoneId, 1);
757 RUN_CHECKS(yfTombstoneRecord_t, observationTimeSeconds, 1);
758
759 prevOffset = 0;
760 prevSize = 0;
761
762 RUN_CHECKS(yfTombstoneAccess_t, certToolId, 1);
763 RUN_CHECKS(yfTombstoneAccess_t, observationTimeSeconds, 1);
764
765 prevOffset = 0;
766 prevSize = 0;
767
768 RUN_CHECKS(yfFlowStatsRecord_t, dataByteCount, 1);
769 RUN_CHECKS(yfFlowStatsRecord_t, averageInterarrivalTime, 1);
770 RUN_CHECKS(yfFlowStatsRecord_t, standardDeviationInterarrivalTime, 1);
771 RUN_CHECKS(yfFlowStatsRecord_t, tcpUrgTotalCount, 1);
772 RUN_CHECKS(yfFlowStatsRecord_t, smallPacketCount, 1);
773 RUN_CHECKS(yfFlowStatsRecord_t, nonEmptyPacketCount, 1);
774 RUN_CHECKS(yfFlowStatsRecord_t, largePacketCount, 1);
775 RUN_CHECKS(yfFlowStatsRecord_t, firstNonEmptyPacketSize, 1);
776 RUN_CHECKS(yfFlowStatsRecord_t, maxPacketSize, 1);
777 RUN_CHECKS(yfFlowStatsRecord_t, standardDeviationPayloadLength, 1);
778 RUN_CHECKS(yfFlowStatsRecord_t, firstEightNonEmptyPacketDirections, 1);
779 RUN_CHECKS(yfFlowStatsRecord_t, padding, 0);
780 RUN_CHECKS(yfFlowStatsRecord_t, reverseDataByteCount, 1);
781 RUN_CHECKS(yfFlowStatsRecord_t, reverseAverageInterarrivalTime, 1);
782 RUN_CHECKS(yfFlowStatsRecord_t,reverseStandardDeviationInterarrivalTime,1);
783 RUN_CHECKS(yfFlowStatsRecord_t, reverseTcpUrgTotalCount, 1);
784 RUN_CHECKS(yfFlowStatsRecord_t, reverseSmallPacketCount, 1);
785 RUN_CHECKS(yfFlowStatsRecord_t, reverseNonEmptyPacketCount, 1);
786 RUN_CHECKS(yfFlowStatsRecord_t, reverseLargePacketCount, 1);
787 RUN_CHECKS(yfFlowStatsRecord_t, reverseFirstNonEmptyPacketSize, 1);
788 RUN_CHECKS(yfFlowStatsRecord_t, reverseMaxPacketSize, 1);
789 RUN_CHECKS(yfFlowStatsRecord_t, reverseStandardDeviationPayloadLength,1);
790 RUN_CHECKS(yfFlowStatsRecord_t, padding2, 0);
791
792 #undef DO_SIZE
793 #undef EA_STRING
794 #undef EG_STRING
795 #undef RUN_CHECKS
796
797 }
798
yfWriterExportPayload(int max_payload)799 void yfWriterExportPayload(
800 int max_payload)
801 {
802 yaf_core_export_payload = max_payload;
803 }
804
yfWriterExportMappedV6(gboolean map_mode)805 void yfWriterExportMappedV6(
806 gboolean map_mode)
807 {
808 yaf_core_map_ipv6 = map_mode;
809 }
810
811
812 /**
813 * yfFlowPrepare
814 *
815 * initialize the state of a flow to be "clean" so that they
816 * can be reused
817 *
818 */
yfFlowPrepare(yfFlow_t * flow)819 void yfFlowPrepare(
820 yfFlow_t *flow)
821 {
822
823 #if YAF_ENABLE_HOOKS
824 unsigned int loop;
825 #endif
826
827 # if YAF_ENABLE_PAYLOAD
828 flow->val.paylen = 0;
829 flow->val.payload = NULL;
830 flow->rval.paylen = 0;
831 flow->rval.payload = NULL;
832 # endif
833
834
835 # ifdef YAF_ENABLE_HOOKS
836 for (loop = 0; loop < YAF_MAX_HOOKS; loop++) {
837 flow->hfctx[loop] = 0x0;
838 }
839 # endif
840
841 memset(flow->sourceMacAddr, 0, ETHERNET_MAC_ADDR_LENGTH);
842 memset(flow->destinationMacAddr, 0, ETHERNET_MAC_ADDR_LENGTH);
843
844 }
845
846
847 /**
848 *yfFlowCleanup
849 *
850 * cleans up after a flow is no longer needed by deallocating
851 * the dynamic memory allocated to the flow (think payload)
852 *
853 */
yfFlowCleanup(yfFlow_t * flow)854 void yfFlowCleanup(
855 yfFlow_t *flow)
856 {
857 #if YAF_ENABLE_PAYLOAD
858 if (flow->val.payload) {
859 g_free(flow->val.payload);
860 flow->val.payload = NULL;
861 }
862
863 if (flow->rval.payload) {
864 g_free(flow->rval.payload);
865 flow->rval.payload = NULL;
866 }
867 #endif
868 }
869
870 /**
871 *yfPayloadCopyIn
872 *
873 *
874 *
875 *
876 */
yfPayloadCopyIn(fbVarfield_t * payvar,yfFlowVal_t * val)877 static void yfPayloadCopyIn(
878 fbVarfield_t *payvar,
879 yfFlowVal_t *val)
880 {
881 # if YAF_ENABLE_PAYLOAD
882 if (payvar->len) {
883 if (!val->payload) {
884 val->payload = g_malloc0(payvar->len);
885 } else {
886 val->payload = g_realloc(val->payload, payvar->len);
887 }
888 val->paylen = payvar->len;
889 memcpy(val->payload, payvar->buf, payvar->len);
890 } else {
891 if (val->payload) g_free(val->payload);
892 val->payload = NULL;
893 val->paylen = 0;
894 }
895 # endif
896 }
897
898 /**
899 * yfInfoModel
900 *
901 *
902 */
yfInfoModel()903 static fbInfoModel_t *yfInfoModel()
904 {
905 static fbInfoModel_t *yaf_model = NULL;
906 #if YAF_ENABLE_HOOKS
907 fbInfoElement_t *yaf_hook_elements = NULL;
908 #endif
909 if (!yaf_model) {
910 yaf_model = fbInfoModelAlloc();
911
912 infomodelAddGlobalElements(yaf_model);
913
914 #if YAF_ENABLE_HOOKS
915 yaf_hook_elements = yfHookGetInfoModel();
916 if (yaf_hook_elements) {
917 fbInfoModelAddElementArray(yaf_model, yaf_hook_elements);
918 }
919 #endif
920 }
921
922 return yaf_model;
923 }
924
925 /**
926 * yfAddTemplate
927 *
928 */
yfAddTemplate(fbSession_t * session,fbInfoElementSpec_t * spec,uint16_t tid,const gchar * name,const gchar * description,gboolean reverse,GError ** err)929 static fbTemplate_t *yfAddTemplate(
930 fbSession_t *session,
931 fbInfoElementSpec_t *spec,
932 uint16_t tid,
933 const gchar *name,
934 const gchar *description,
935 gboolean reverse,
936 GError **err)
937 {
938 fbInfoModel_t *model = yfInfoModel();
939 fbTemplate_t *tmpl = fbTemplateAlloc(model);
940 uint32_t flags = 0;
941 uint16_t rtid = tid;
942
943 if (reverse) {
944 flags = 0xffffffff;
945 rtid = tid | YTF_BIF;
946 }
947
948 g_debug("yaf: %x (%s), %d (%x)", tid, name, reverse, tid | (reverse ? YTF_BIF : 0));
949
950 if (!fbTemplateAppendSpecArray(tmpl, spec, flags, err)) {
951 return NULL;
952 }
953
954 #if YAF_ENABLE_METADATA_EXPORT
955 if (!fbSessionAddTemplateWithMetadata(session, FALSE, rtid,
956 tmpl, name, description, err))
957 {
958 return NULL;
959 }
960 #else
961 if (!fbSessionAddTemplate(session, FALSE, rtid, tmpl, err))
962 {
963 return NULL;
964 }
965 #endif
966
967 if (reverse) {
968 if (!fbSessionAddTemplate(session, TRUE, tid, tmpl, err))
969 {
970 return NULL;
971 }
972 }
973
974 return tmpl;
975 }
976
977 /**
978 * yfInitExporterSession
979 *
980 *
981 */
yfInitExporterSession(uint32_t domain,gboolean export_meta,GError ** err)982 static fbSession_t *yfInitExporterSession(
983 uint32_t domain,
984 gboolean export_meta,
985 GError **err)
986 {
987 fbInfoModel_t *model = yfInfoModel();
988 fbTemplate_t *tmpl = NULL;
989 fbSession_t *session = NULL;
990
991 /* Allocate the session */
992 session = fbSessionAlloc(model);
993
994 /* set observation domain */
995 fbSessionSetDomain(session, domain);
996
997 /* Create the full record template */
998 tmpl = fbTemplateAlloc(model);
999 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec, YTF_ALL, err)) {
1000 return NULL;
1001 }
1002
1003 if (export_meta) {
1004 #if YAF_ENABLE_METADATA_EXPORT
1005 if (!fbSessionSetMetadataExportElements(
1006 session, TRUE, YAF_TYPE_METADATA_TID, err))
1007 {
1008 return NULL;
1009 }
1010
1011 if (!fbSessionSetMetadataExportTemplates(
1012 session, TRUE, YAF_TEMPLATE_METADATA_TID, err))
1013 {
1014 return NULL;
1015 }
1016 #endif
1017 }
1018
1019 #if YAF_ENABLE_METADATA_EXPORT
1020 if (!fbSessionAddTemplateWithMetadata(session, FALSE, YAF_FLOW_FULL_TID,
1021 tmpl, YAF_FLOW_FULL_NAME, NULL, err))
1022 {
1023 return NULL;
1024 }
1025 #else
1026 /* Add the full record template to the session */
1027 if (!fbSessionAddTemplate(session, FALSE, YAF_FLOW_FULL_TID, tmpl, err)) {
1028 return NULL;
1029 }
1030
1031 #endif
1032 if (!fbSessionAddTemplate(session, TRUE, YAF_FLOW_FULL_TID, tmpl, err)) {
1033 return NULL;
1034 }
1035
1036
1037 /* Create the Options Template */
1038 yaf_tmpl.ipfixStatsTemplate = fbTemplateAlloc(model);
1039 if (!fbTemplateAppendSpecArray(yaf_tmpl.ipfixStatsTemplate,
1040 yaf_process_stats_spec, 0, err))
1041 {
1042 return NULL;
1043 }
1044
1045 /* Scope fields are exporterIPv4Address, observationDomainId,
1046 and exportingProcessID */
1047 fbTemplateSetOptionsScope(yaf_tmpl.ipfixStatsTemplate, 3);
1048 #if YAF_ENABLE_METADATA_EXPORT
1049 if (!fbSessionAddTemplateWithMetadata(session, FALSE, YAF_PROCESS_STATS_TID,
1050 yaf_tmpl.ipfixStatsTemplate,
1051 YAF_PROCESS_STATS_NAME, NULL, err))
1052 {
1053 return NULL;
1054 }
1055 #else
1056 if (!fbSessionAddTemplate(session, FALSE, YAF_PROCESS_STATS_TID,
1057 yaf_tmpl.ipfixStatsTemplate, err))
1058 {
1059 return NULL;
1060 }
1061 #endif
1062 if (!fbSessionAddTemplate(session, TRUE, YAF_PROCESS_STATS_TID,
1063 yaf_tmpl.ipfixStatsTemplate, err))
1064 {
1065 return NULL;
1066 }
1067
1068 /* Create the Tombstone record Template */
1069 yaf_tmpl.tombstoneRecordTemplate = fbTemplateAlloc(model);
1070 if (!fbTemplateAppendSpecArray(yaf_tmpl.tombstoneRecordTemplate,
1071 yaf_tombstone_spec, 0, err))
1072 {
1073 return NULL;
1074 }
1075 /* Scope fields are exportingProcessID, observationDomainId,
1076 and exporterConfiguredId */
1077 fbTemplateSetOptionsScope(yaf_tmpl.tombstoneRecordTemplate, 3);
1078 #if YAF_ENABLE_METADATA_EXPORT
1079 if (!fbSessionAddTemplateWithMetadata(session, FALSE, YAF_TOMBSTONE_TID,
1080 yaf_tmpl.tombstoneRecordTemplate,
1081 YAF_TOMBSTONE_NAME, NULL, err))
1082 {
1083 return NULL;
1084 }
1085 #else
1086 if (!fbSessionAddTemplate(session, FALSE, YAF_TOMBSTONE_TID,
1087 yaf_tmpl.tombstoneRecordTemplate, err))
1088 {
1089 return NULL;
1090 }
1091 #endif
1092 if (!fbSessionAddTemplate(session, TRUE, YAF_TOMBSTONE_TID,
1093 yaf_tmpl.tombstoneRecordTemplate, err))
1094 {
1095 return NULL;
1096 }
1097
1098 /* Create the Tombstone Access SubTemplate */
1099 yaf_tmpl.tombstoneAccessTemplate = fbTemplateAlloc(model);
1100 if (!fbTemplateAppendSpecArray(yaf_tmpl.tombstoneAccessTemplate,
1101 yaf_tombstone_access_spec, 0, err))
1102 {
1103 return NULL;
1104 }
1105 #if YAF_ENABLE_METADATA_EXPORT
1106 if (!fbSessionAddTemplateWithMetadata(session, FALSE, YAF_TOMBSTONE_ACCESS_TID,
1107 yaf_tmpl.tombstoneAccessTemplate,
1108 YAF_TOMBSTONE_ACCESS_NAME, NULL, err))
1109 {
1110 return NULL;
1111 }
1112 #else
1113 if (!fbSessionAddTemplate(session, FALSE, YAF_TOMBSTONE_ACCESS_TID,
1114 yaf_tmpl.tombstoneAccessTemplate, err))
1115 {
1116 return NULL;
1117 }
1118 #endif
1119 if (!fbSessionAddTemplate(session, TRUE, YAF_TOMBSTONE_ACCESS_TID,
1120 yaf_tmpl.tombstoneAccessTemplate, err))
1121 {
1122 return NULL;
1123 }
1124
1125
1126 /* Flow Stats Template */
1127 yaf_tmpl.fstatsTemplate = yfAddTemplate(session, yaf_flow_stats_spec,
1128 YAF_STATS_FLOW_TID,
1129 YAF_STATS_FLOW_NAME, NULL,
1130 FALSE, err);
1131 if (!yaf_tmpl.fstatsTemplate) {
1132 return NULL;
1133 }
1134
1135 yaf_tmpl.revfstatsTemplate = yfAddTemplate(session, yaf_flow_stats_spec,
1136 YAF_STATS_FLOW_TID,
1137 YAF_STATS_FLOW_REV_NAME, NULL,
1138 TRUE, err);
1139 if (!yaf_tmpl.revfstatsTemplate) {
1140 return NULL;
1141 }
1142
1143 #if YAF_ENABLE_ENTROPY
1144 yaf_tmpl.entropyTemplate = yfAddTemplate(session, yaf_entropy_spec,
1145 YAF_ENTROPY_FLOW_TID,
1146 YAF_ENTROPY_FLOW_NAME, NULL,
1147 FALSE, err);
1148
1149 if (!yaf_tmpl.entropyTemplate) {
1150 return NULL;
1151 }
1152
1153 yaf_tmpl.revEntropyTemplate = yfAddTemplate(session, yaf_entropy_spec,
1154 YAF_ENTROPY_FLOW_TID,
1155 YAF_ENTROPY_FLOW_REV_NAME,
1156 NULL, TRUE, err);
1157 if (!yaf_tmpl.revEntropyTemplate) {
1158 return NULL;
1159 }
1160
1161 #endif
1162
1163 yaf_tmpl.tcpTemplate = yfAddTemplate(session, yaf_tcp_spec,
1164 YAF_TCP_FLOW_TID, YAF_TCP_FLOW_NAME,
1165 NULL, FALSE, err);
1166
1167 if (!yaf_tmpl.tcpTemplate) {
1168 return NULL;
1169 }
1170
1171 yaf_tmpl.revTcpTemplate = yfAddTemplate(session, yaf_tcp_spec,
1172 YAF_TCP_FLOW_TID,
1173 YAF_TCP_FLOW_REV_NAME, NULL,
1174 TRUE, err);
1175
1176 if (!yaf_tmpl.revTcpTemplate) {
1177 return NULL;
1178 }
1179
1180 yaf_tmpl.macTemplate = yfAddTemplate(session, yaf_mac_spec,
1181 YAF_MAC_FLOW_TID, YAF_MAC_FLOW_NAME,
1182 NULL, FALSE, err);
1183
1184 if (!yaf_tmpl.macTemplate) {
1185 return NULL;
1186 }
1187
1188 yaf_tmpl.mptcpTemplate = yfAddTemplate(session, yaf_mptcp_spec,
1189 YAF_MPTCP_FLOW_TID,
1190 YAF_MPTCP_FLOW_NAME, NULL,
1191 FALSE, err);
1192 if (!yaf_tmpl.mptcpTemplate) {
1193 return NULL;
1194 }
1195
1196 #if YAF_ENABLE_P0F
1197 yaf_tmpl.p0fTemplate = yfAddTemplate(session, yaf_p0f_spec,
1198 YAF_P0F_FLOW_TID, YAF_P0F_FLOW_NAME,
1199 NULL, FALSE, err);
1200
1201 if (!yaf_tmpl.p0fTemplate) {
1202 return NULL;
1203 }
1204
1205 yaf_tmpl.revP0fTemplate = yfAddTemplate(session, yaf_p0f_spec,
1206 YAF_P0F_FLOW_TID,
1207 YAF_P0F_FLOW_REV_NAME,
1208 NULL, TRUE, err);
1209
1210 if (!yaf_tmpl.revP0fTemplate) {
1211 return NULL;
1212 }
1213 #endif
1214
1215 #if YAF_ENABLE_FPEXPORT
1216 yaf_tmpl.fpexportTemplate = yfAddTemplate(session, yaf_fpexport_spec,
1217 YAF_FPEXPORT_FLOW_TID,
1218 YAF_FPEXPORT_FLOW_NAME, NULL,
1219 FALSE, err);
1220
1221 if (!yaf_tmpl.fpexportTemplate) {
1222 return NULL;
1223 }
1224
1225 yaf_tmpl.revFpexportTemplate = yfAddTemplate(session, yaf_fpexport_spec,
1226 YAF_FPEXPORT_FLOW_TID,
1227 YAF_FPEXPORT_FLOW_REV_NAME,
1228 NULL, TRUE, err);
1229 if (!yaf_tmpl.revFpexportTemplate) {
1230 return NULL;
1231 }
1232 #endif
1233
1234 #if YAF_ENABLE_PAYLOAD
1235 yaf_tmpl.payloadTemplate = yfAddTemplate(session, yaf_payload_spec,
1236 YAF_PAYLOAD_FLOW_TID,
1237 YAF_PAYLOAD_FLOW_NAME, NULL,
1238 FALSE, err);
1239
1240 if (!yaf_tmpl.payloadTemplate) {
1241 return NULL;
1242 }
1243
1244 yaf_tmpl.revPayloadTemplate = yfAddTemplate(session, yaf_payload_spec,
1245 YAF_PAYLOAD_FLOW_TID,
1246 YAF_PAYLOAD_FLOW_REV_NAME,
1247 NULL, TRUE, err);
1248
1249 if (!yaf_tmpl.revPayloadTemplate) {
1250 return NULL;
1251 }
1252 #endif
1253
1254 #if YAF_ENABLE_HOOKS
1255 /* Add the hook template fields if available */
1256
1257 if (!yfHookGetTemplate(session)) {
1258 g_debug("Hook Templates could not be added to the session");
1259 }
1260
1261 #endif
1262
1263 /* Done. Return the session. */
1264 return session;
1265 }
1266
1267
1268 #ifdef HAVE_SPREAD
1269 /**
1270 * yfAddTemplateSpread
1271 *
1272 *
1273 */
yfAddTemplateSpread(fbSession_t * session,fbInfoElementSpec_t * spec,char ** groups,uint16_t tid,const gchar * name,const gchar * description,gboolean reverse,GError ** err)1274 static fbTemplate_t *yfAddTemplateSpread(
1275 fbSession_t *session,
1276 fbInfoElementSpec_t *spec,
1277 char **groups,
1278 uint16_t tid,
1279 const gchar *name,
1280 const gchar *description,
1281 gboolean reverse,
1282 GError **err)
1283 {
1284 fbInfoModel_t *model = yfInfoModel();
1285 fbTemplate_t *tmpl = fbTemplateAlloc(model);
1286 uint32_t flags = 0;
1287 uint16_t rtid = tid;
1288
1289 if (reverse) {
1290 flags = 0xffffffff;
1291 rtid = tid | YTF_BIF;
1292 }
1293
1294 g_debug("yaf spread: %x (%s), %d (%x)", tid, name, reverse, tid | (reverse ? YTF_BIF : 0));
1295 if (!fbTemplateAppendSpecArray(tmpl, spec, flags, err))
1296 {
1297 return NULL;
1298 }
1299
1300 #if YAF_ENABLE_METADATA_EXPORT
1301 if (!fbSessionAddTemplatesMulticastWithMetadata(session, groups, FALSE, rtid,
1302 tmpl, name, description, err))
1303 {
1304 return NULL;
1305 }
1306 #else
1307 if (!fbSessionAddTemplatesMulticast(session, groups, FALSE,
1308 rtid, tmpl, err))
1309 {
1310 return NULL;
1311 }
1312 #endif
1313
1314 if (reverse) {
1315
1316 if (!fbSessionAddTemplate(session, TRUE, tid, tmpl, err))
1317 {
1318 return NULL;
1319 }
1320
1321 }
1322
1323 return tmpl;
1324 }
1325
1326
1327
1328
1329 /**
1330 * yfInitExporterSpreadSession
1331 *
1332 *
1333 */
yfInitExporterSpreadSession(fBuf_t * fbuf,fbSession_t * session,fbSpreadParams_t * spread,uint32_t domain,uint16_t * spreadIndex,gboolean export_meta,GError ** err)1334 static fbSession_t *yfInitExporterSpreadSession(
1335 fBuf_t *fbuf,
1336 fbSession_t *session,
1337 fbSpreadParams_t *spread,
1338 uint32_t domain,
1339 uint16_t *spreadIndex,
1340 gboolean export_meta,
1341 GError **err)
1342 {
1343
1344 fbInfoModel_t *model = yfInfoModel();
1345 fbTemplate_t *tmpl = NULL;
1346 #if YAF_ENABLE_HOOKS
1347 int n = 0;
1348 #endif
1349
1350 if (export_meta) {
1351 #if YAF_ENABLE_METADATA_EXPORT
1352 if (!fbSessionSpreadSetMetadataExportElements(
1353 session, spread->groups, TRUE, YAF_TYPE_METADATA_TID, err))
1354 {
1355 return NULL;
1356 }
1357
1358 if (!fbSessionSpreadSetMetadataExportTemplates(
1359 session, spread->groups, TRUE, YAF_TEMPLATE_METADATA_TID, err))
1360 {
1361 return NULL;
1362 }
1363 #endif
1364 }
1365
1366 /*Create the full record template */
1367 tmpl = fbTemplateAlloc(model);
1368
1369 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec, YTF_ALL, err))
1370 return NULL;
1371 /* Add the full record template to the session */
1372 if (!fbSessionAddTemplate(session, TRUE, YAF_FLOW_FULL_TID, tmpl, err)) {
1373 return NULL;
1374 }
1375 #if YAF_ENABLE_METADATA_EXPORT
1376 if (!fbSessionAddTemplatesMulticastWithMetadata(
1377 session, spread->groups, FALSE, YAF_FLOW_FULL_TID, tmpl,
1378 YAF_FLOW_FULL_NAME, NULL, err))
1379 {
1380 return NULL;
1381 }
1382 #else
1383 if (!fbSessionAddTemplatesMulticast(
1384 session, spread->groups, FALSE, YAF_FLOW_FULL_TID, tmpl, err))
1385 {
1386 return NULL;
1387 }
1388 #endif
1389
1390 /* Create the Options Template */
1391 yaf_tmpl.ipfixStatsTemplate = fbTemplateAlloc(model);
1392 if (!fbTemplateAppendSpecArray(yaf_tmpl.ipfixStatsTemplate,
1393 yaf_process_stats_spec, 0, err))
1394 {
1395 return NULL;
1396 }
1397
1398 /* Scope fields are exporterIPv4Address, observationDomainId,
1399 and exportingProcessID */
1400 fbTemplateSetOptionsScope(yaf_tmpl.ipfixStatsTemplate, 3);
1401 if (!fbSessionAddTemplate(session, TRUE, YAF_PROCESS_STATS_TID,
1402 yaf_tmpl.ipfixStatsTemplate, err))
1403 {
1404 return NULL;
1405 }
1406
1407 #if YAF_ENABLE_METADATA_EXPORT
1408 if (!fbSessionAddTemplatesMulticastWithMetadata(session, spread->groups, FALSE,
1409 YAF_PROCESS_STATS_TID,
1410 yaf_tmpl.ipfixStatsTemplate,
1411 YAF_PROCESS_STATS_NAME, NULL, err))
1412 {
1413 return NULL;
1414 }
1415 #else
1416 if (!fbSessionAddTemplatesMulticast(session, spread->groups, FALSE,
1417 YAF_PROCESS_STATS_TID,
1418 yaf_tmpl.ipfixStatsTemplate, err))
1419 {
1420 return NULL;
1421 }
1422 #endif
1423
1424 /* Create the Tombstone Record Template */
1425 yaf_tmpl.tombstoneRecordTemplate = fbTemplateAlloc(model);
1426 if (!fbTemplateAppendSpecArray(yaf_tmpl.tombstoneRecordTemplate,
1427 yaf_tombstone_spec, 0, err))
1428 {
1429 return NULL;
1430 }
1431
1432 /* Scope fields are exportingProcessID, observationDomainId,
1433 and exporterConfiguredId */
1434 fbTemplateSetOptionsScope(yaf_tmpl.tombstoneRecordTemplate, 3);
1435 if (!fbSessionAddTemplate(session, TRUE, YAF_TOMBSTONE_TID,
1436 yaf_tmpl.tombstoneRecordTemplate, err))
1437 {
1438 return NULL;
1439 }
1440
1441 #if YAF_ENABLE_METADATA_EXPORT
1442 if (!fbSessionAddTemplatesMulticastWithMetadata(session, spread->groups, FALSE,
1443 YAF_TOMBSTONE_TID,
1444 yaf_tmpl.tombstoneRecordTemplate,
1445 YAF_TOMBSTONE_NAME, NULL, err))
1446 {
1447 return NULL;
1448 }
1449 #else
1450 if (!fbSessionAddTemplatesMulticast(session, spread->groups, FALSE,
1451 YAF_TOMBSTONE_TID,
1452 yaf_tmpl.tombstoneRecordTemplate, err))
1453 {
1454 return NULL;
1455 }
1456 #endif
1457
1458
1459 /* Create the Tombstone Access SubTemplate */
1460 yaf_tmpl.tombstoneAccessTemplate = fbTemplateAlloc(model);
1461 if (!fbTemplateAppendSpecArray(yaf_tmpl.tombstoneAccessTemplate,
1462 yaf_tombstone_access_spec, 0, err))
1463 {
1464 return NULL;
1465 }
1466 if (!fbSessionAddTemplate(session, TRUE, YAF_TOMBSTONE_ACCESS_TID,
1467 yaf_tmpl.tombstoneAccessTemplate, err))
1468 {
1469 return NULL;
1470 }
1471 #if YAF_ENABLE_METADATA_EXPORT
1472 if (!fbSessionAddTemplatesMulticastWithMetadata(session, spread->groups, FALSE,
1473 YAF_TOMBSTONE_ACCESS_TID,
1474 yaf_tmpl.tombstoneAccessTemplate,
1475 YAF_TOMBSTONE_ACCESS_NAME, NULL, err))
1476 {
1477 return NULL;
1478 }
1479 #else
1480 if (!fbSessionAddTemplatesMulticast(session, spread->groups, FALSE,
1481 YAF_TOMBSTONE_ACCESS_TID,
1482 yaf_tmpl.tombstoneAccessTemplate, err))
1483 {
1484 return NULL;
1485 }
1486 #endif
1487
1488
1489
1490
1491 /* Flow Stats Template */
1492 yaf_tmpl.fstatsTemplate = yfAddTemplateSpread(session, yaf_flow_stats_spec,
1493 spread->groups,
1494 YAF_STATS_FLOW_TID,
1495 YAF_STATS_FLOW_NAME, NULL,
1496 FALSE, err);
1497 if (!yaf_tmpl.fstatsTemplate) {
1498 return NULL;
1499 }
1500
1501 yaf_tmpl.revfstatsTemplate = yfAddTemplateSpread(session, yaf_flow_stats_spec,
1502 spread->groups,
1503 YAF_STATS_FLOW_TID,
1504 YAF_STATS_FLOW_REV_NAME, NULL,
1505 TRUE, err);
1506 if (!yaf_tmpl.revfstatsTemplate) {
1507 return NULL;
1508 }
1509
1510 #if YAF_ENABLE_ENTROPY
1511 yaf_tmpl.entropyTemplate = yfAddTemplateSpread(session, yaf_entropy_spec,
1512 spread->groups,
1513 YAF_ENTROPY_FLOW_TID,
1514 YAF_ENTROPY_FLOW_NAME, NULL,
1515 FALSE, err);
1516
1517 if (!yaf_tmpl.entropyTemplate) {
1518 return NULL;
1519 }
1520
1521 yaf_tmpl.revEntropyTemplate = yfAddTemplateSpread(session, yaf_entropy_spec,
1522 spread->groups,
1523 YAF_ENTROPY_FLOW_TID,
1524 YAF_ENTROPY_FLOW_REV_NAME,
1525 NULL, TRUE, err);
1526 if (!yaf_tmpl.revEntropyTemplate) {
1527 return NULL;
1528 }
1529
1530 #endif
1531
1532 yaf_tmpl.tcpTemplate = yfAddTemplateSpread(session, yaf_tcp_spec,
1533 spread->groups,
1534 YAF_TCP_FLOW_TID, YAF_TCP_FLOW_NAME,
1535 NULL, FALSE, err);
1536
1537 if (!yaf_tmpl.tcpTemplate) {
1538 return NULL;
1539 }
1540
1541 yaf_tmpl.revTcpTemplate = yfAddTemplateSpread(session, yaf_tcp_spec,
1542 spread->groups,
1543 YAF_TCP_FLOW_TID,
1544 YAF_TCP_FLOW_REV_NAME, NULL,
1545 TRUE, err);
1546
1547 if (!yaf_tmpl.revTcpTemplate) {
1548 return NULL;
1549 }
1550
1551 yaf_tmpl.macTemplate = yfAddTemplateSpread(session, yaf_mac_spec,
1552 spread->groups,
1553 YAF_MAC_FLOW_TID, YAF_MAC_FLOW_NAME,
1554 NULL, FALSE, err);
1555
1556 if (!yaf_tmpl.macTemplate) {
1557 return NULL;
1558 }
1559
1560 yaf_tmpl.mptcpTemplate = yfAddTemplateSpread(session, yaf_mptcp_spec,
1561 spread->groups,
1562 YAF_MPTCP_FLOW_TID,
1563 YAF_MPTCP_FLOW_NAME, NULL,
1564 FALSE, err);
1565 if (!yaf_tmpl.mptcpTemplate) {
1566 return NULL;
1567 }
1568
1569 #if YAF_ENABLE_P0F
1570 yaf_tmpl.p0fTemplate = yfAddTemplateSpread(session, yaf_p0f_spec,
1571 spread->groups,
1572 YAF_P0F_FLOW_TID, YAF_P0F_FLOW_NAME,
1573 NULL, FALSE, err);
1574
1575 if (!yaf_tmpl.p0fTemplate) {
1576 return NULL;
1577 }
1578
1579 yaf_tmpl.revP0fTemplate = yfAddTemplateSpread(session, yaf_p0f_spec,
1580 spread->groups,
1581 YAF_P0F_FLOW_TID,
1582 YAF_P0F_FLOW_REV_NAME,
1583 NULL, TRUE, err);
1584
1585 if (!yaf_tmpl.revP0fTemplate) {
1586 return NULL;
1587 }
1588 #endif
1589
1590 #if YAF_ENABLE_FPEXPORT
1591 yaf_tmpl.fpexportTemplate = yfAddTemplateSpread(session, yaf_fpexport_spec,
1592 spread->groups,
1593 YAF_FPEXPORT_FLOW_TID,
1594 YAF_FPEXPORT_FLOW_NAME, NULL,
1595 FALSE, err);
1596
1597 if (!yaf_tmpl.fpexportTemplate) {
1598 return NULL;
1599 }
1600
1601 yaf_tmpl.revFpexportTemplate = yfAddTemplateSpread(session, yaf_fpexport_spec,
1602 spread->groups,
1603 YAF_FPEXPORT_FLOW_TID,
1604 YAF_FPEXPORT_FLOW_REV_NAME,
1605 NULL, TRUE, err);
1606 if (!yaf_tmpl.revFpexportTemplate) {
1607 return NULL;
1608 }
1609 #endif
1610
1611 #if YAF_ENABLE_PAYLOAD
1612 yaf_tmpl.payloadTemplate = yfAddTemplateSpread(session, yaf_payload_spec,
1613 spread->groups,
1614 YAF_PAYLOAD_FLOW_TID,
1615 YAF_PAYLOAD_FLOW_NAME, NULL,
1616 FALSE, err);
1617
1618 if (!yaf_tmpl.payloadTemplate) {
1619 return NULL;
1620 }
1621
1622 yaf_tmpl.revPayloadTemplate = yfAddTemplateSpread(session, yaf_payload_spec,
1623 spread->groups,
1624 YAF_PAYLOAD_FLOW_TID,
1625 YAF_PAYLOAD_FLOW_REV_NAME,
1626 NULL, TRUE, err);
1627
1628 if (!yaf_tmpl.revPayloadTemplate) {
1629 return NULL;
1630 }
1631 #endif
1632
1633 #if YAF_ENABLE_HOOKS
1634 /* Add the hook template fields if available */
1635 while (spread->groups[n]) {
1636 fBufSetSpreadExportGroup(fbuf, &(spread->groups[n]), 1, err);
1637 if (!yfHookGetTemplate(session)) {
1638 g_warning("Hook Templates could not be added to the session");
1639 return NULL;
1640 }
1641 n++;
1642 }
1643 #endif
1644 /* Done. Return the session. */
1645 return session;
1646 }
1647
1648 /**
1649 * yfSpreadGroupby
1650 *
1651 *
1652 */
yfSpreadGroupby(uint8_t spreadGroupByType,uint16_t silkAppLabel,uint16_t vlanId,uint16_t destinationTransportPort,uint8_t protocolIdentifier,uint8_t ipVersion)1653 static uint16_t yfSpreadGroupby(
1654 uint8_t spreadGroupByType,
1655 uint16_t silkAppLabel,
1656 uint16_t vlanId,
1657 uint16_t destinationTransportPort,
1658 uint8_t protocolIdentifier,
1659 uint8_t ipVersion)
1660 {
1661 switch (spreadGroupByType) {
1662 case 1:
1663 return destinationTransportPort;
1664 case 2:
1665 return vlanId;
1666 case 3:
1667 return silkAppLabel;
1668 case 4:
1669 return (uint16_t)protocolIdentifier;
1670 case 5:
1671 return (uint16_t)ipVersion;
1672 default:
1673 return 0;
1674 }
1675 }
1676
1677
1678 /**
1679 * yfWriterForSpread
1680 *
1681 *
1682 *
1683 */
yfWriterForSpread(fbSpreadParams_t * spread,uint32_t domain,uint16_t * spreadGroupIndex,gboolean export_metadata,GError ** err)1684 fBuf_t *yfWriterForSpread(
1685 fbSpreadParams_t *spread,
1686 uint32_t domain,
1687 uint16_t *spreadGroupIndex,
1688 gboolean export_metadata,
1689 GError **err)
1690 {
1691 fBuf_t *fbuf = NULL;
1692 fbSession_t *session ;
1693 fbExporter_t *exporter;
1694 fbInfoModel_t *model = yfInfoModel();
1695
1696 session = fbSessionAlloc(model);
1697
1698 spread->session = session;
1699
1700 fbSessionSetDomain(session, domain);
1701
1702 exporter = fbExporterAllocSpread(spread);
1703
1704 fbuf = fBufAllocForExport(session, exporter);
1705
1706 /* If we are using spread group by - we need to multicast templates */
1707 if (spreadGroupIndex) {
1708 if (!(session = yfInitExporterSpreadSession(fbuf, session, spread,
1709 domain, spreadGroupIndex,
1710 export_metadata,
1711 err)))
1712 {
1713 goto err;
1714 }
1715 } else {
1716 /* initialize session and exporter */
1717 if (!(session = yfInitExporterSession(domain, export_metadata, err)))
1718 {
1719 goto err;
1720 }
1721 }
1722
1723 /* set observation domain */
1724 fbSessionSetDomain(session, domain);
1725
1726 /* write YAF flow templates */
1727
1728 if (!fbSessionExportTemplates(session, err)) goto err;
1729 /* set internal template */
1730 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) {
1731 goto err;
1732 }
1733
1734 /* all done */
1735 return fbuf;
1736
1737 err:
1738 if (fbuf) fBufFree(fbuf);
1739
1740 return NULL;
1741
1742 }
1743
1744 /**
1745 *yfSetSpreadExportTemplate
1746 *
1747 *
1748 *
1749 */
yfSetSpreadExportTemplate(fBuf_t * fbuf,fbSpreadParams_t * spread,uint16_t tid,char ** groups,int num_groups,GError ** err)1750 static gboolean yfSetSpreadExportTemplate(
1751 fBuf_t *fbuf,
1752 fbSpreadParams_t *spread,
1753 uint16_t tid,
1754 char **groups,
1755 int num_groups,
1756 GError **err)
1757 {
1758 fbSession_t *session = NULL;
1759 fbTemplate_t *tmpl = NULL;
1760
1761 /* Try to set export template */
1762
1763 if (fBufSetExportTemplate(fbuf, tid, err)) {
1764 return TRUE;
1765 }
1766
1767 /* Check for error other than missing template */
1768 if (!g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) {
1769 return FALSE;
1770 }
1771
1772 /* Okay. We have a missing template. Clear the error and try to load it. */
1773 g_clear_error(err);
1774 session = fBufGetSession(fbuf);
1775 tmpl = fbTemplateAlloc(yfInfoModel());
1776
1777 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec,
1778 (tid & (~YAF_FLOW_BASE_TID)), err))
1779 {
1780 return FALSE;
1781 }
1782 /* Multicast templates to all groups */
1783 if (!(fbSessionAddTemplatesMulticast(session, spread->groups, FALSE,
1784 tid, tmpl, err)))
1785 {
1786 return FALSE;
1787 }
1788
1789 /* Now reset groups on the buffer */
1790 fBufSetSpreadExportGroup(fbuf, groups, num_groups, err);
1791 /* Template should be loaded. Try setting the template again. */
1792 return fBufSetExportTemplate(fbuf, tid, err);
1793 }
1794
1795
1796 #endif /* HAVE SPREAD */
1797
1798
1799
1800 /**
1801 *yfSetExportTemplate
1802 *
1803 *
1804 *
1805 */
1806
1807 #define TEMPLATE_NAME_INIT_LEN 32
1808
yfSetExportTemplate(fBuf_t * fbuf,uint16_t tid,GError ** err)1809 static gboolean yfSetExportTemplate(
1810 fBuf_t *fbuf,
1811 uint16_t tid,
1812 GError **err)
1813 {
1814 fbSession_t *session = NULL;
1815 fbTemplate_t *tmpl = NULL;
1816 GString *template_name = NULL;
1817
1818 /* Try to set export template */
1819 if (fBufSetExportTemplate(fbuf, tid, err)) {
1820 return TRUE;
1821 }
1822
1823 /* Check for error other than missing template */
1824 if (!g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) {
1825 return FALSE;
1826 }
1827
1828 /* Okay. We have a missing template. Clear the error and try to load it. */
1829 g_clear_error(err);
1830
1831 template_name = g_string_sized_new(TEMPLATE_NAME_INIT_LEN);
1832
1833 session = fBufGetSession(fbuf);
1834 tmpl = fbTemplateAlloc(yfInfoModel());
1835
1836
1837 if ( (tid & YAF_FLOW_BASE_TID) == YAF_FLOW_BASE_TID )
1838 {
1839 g_string_append_printf(template_name, "yaf_flow");
1840
1841 if ( tid & YTF_DELTA ) {
1842 g_string_append_printf(template_name, "_%s", YTF_DELTA_NAME);
1843 } else {
1844 g_string_append_printf(template_name, "_%s", YTF_TOTAL_NAME);
1845 }
1846
1847 if (tid & YTF_BIF) {
1848 g_string_append_printf(template_name, "_%s", YTF_BIF_NAME);
1849 }
1850
1851 if (tid & YTF_SILK) {
1852 g_string_append_printf(template_name, "_%s", YTF_SILK_NAME);
1853 }
1854
1855 if (tid & YTF_MPLS) {
1856 g_string_append_printf(template_name, "_%s", YTF_MPLS_NAME);
1857 }
1858
1859 if (tid & YTF_RLE) {
1860 g_string_append_printf(template_name, "_%s", YTF_RLE_NAME);
1861 } else {
1862 g_string_append_printf(template_name, "_%s", YTF_FLE_NAME);
1863 }
1864
1865 if (tid & YTF_IP6) {
1866 g_string_append_printf(template_name, "_%s", YTF_IP6_NAME);
1867 } else {
1868 g_string_append_printf(template_name, "_%s", YTF_IP4_NAME);
1869 }
1870
1871 if (tid & YTF_DAGIF) {
1872 g_string_append_printf(template_name, "_%s", YTF_DAGIF_NAME);
1873 }
1874
1875 }
1876
1877 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec,
1878 (tid & (~YAF_FLOW_BASE_TID)), err)) {
1879 return FALSE;
1880 }
1881
1882 /* printf("yfSetExportTemplate: %x, %s\n", tid, template_name->str); */
1883 #if YAF_ENABLE_METADATA_EXPORT
1884 if (!fbSessionAddTemplateWithMetadata(session, FALSE, tid, tmpl,
1885 template_name->str, NULL, err))
1886 {
1887 g_error("error setting template metadata: tid: %x, name: %s\n",
1888 tid, template_name->str);
1889 g_string_free(template_name, TRUE);
1890 return FALSE;
1891 }
1892 #else
1893 if (!fbSessionAddTemplate(session, FALSE, tid, tmpl, err)) {
1894 g_string_free(template_name, TRUE);
1895 return FALSE;
1896 }
1897 #endif
1898
1899 /*g_debug("adding new template %02x", tid);*/
1900 g_string_free(template_name, TRUE);
1901
1902 /* Template should be loaded. Try setting the template again. */
1903 return fBufSetExportTemplate(fbuf, tid, err);
1904 }
1905
1906 /**
1907 *yfWriterForFile
1908 *
1909 *
1910 */
yfWriterForFile(const char * path,uint32_t domain,gboolean export_meta,GError ** err)1911 fBuf_t *yfWriterForFile(
1912 const char *path,
1913 uint32_t domain,
1914 gboolean export_meta,
1915 GError **err)
1916 {
1917 fBuf_t *fbuf = NULL;
1918 fbExporter_t *exporter;
1919 fbSession_t *session;
1920
1921 /* Allocate an exporter for the file */
1922 exporter = fbExporterAllocFile(path);
1923
1924 /* Create a new buffer */
1925 if (!(session = yfInitExporterSession(domain, export_meta, err))) goto err;
1926
1927 fbuf = fBufAllocForExport(session, exporter);
1928
1929 /* write YAF flow templates */
1930 if (!fbSessionExportTemplates(session, err)) goto err;
1931
1932 /* set internal template */
1933 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) goto err;
1934
1935 /* all done */
1936 return fbuf;
1937
1938 err:
1939 /* free buffer if necessary */
1940 if (fbuf) fBufFree(fbuf);
1941 return NULL;
1942 }
1943
1944
1945 /**
1946 *yfWriterForFP
1947 *
1948 *
1949 *
1950 */
yfWriterForFP(FILE * fp,uint32_t domain,gboolean export_meta,GError ** err)1951 fBuf_t *yfWriterForFP(
1952 FILE *fp,
1953 uint32_t domain,
1954 gboolean export_meta,
1955 GError **err)
1956 {
1957 fBuf_t *fbuf = NULL;
1958 fbExporter_t *exporter;
1959 fbSession_t *session;
1960
1961 /* Allocate an exporter for the file */
1962 exporter = fbExporterAllocFP(fp);
1963 /* Create a new buffer */
1964 if (!(session = yfInitExporterSession(domain, export_meta, err))) goto err;
1965
1966 fbuf = fBufAllocForExport(session, exporter);
1967
1968 /* write YAF flow templates */
1969
1970 if (!fbSessionExportTemplates(session, err)) goto err;
1971
1972 /* set internal template */
1973 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) goto err;
1974
1975 /* all done */
1976 return fbuf;
1977
1978 err:
1979 /* free buffer if necessary */
1980 if (fbuf) fBufFree(fbuf);
1981 return NULL;
1982 }
1983
1984
1985 /**
1986 *yfWriterForSpec
1987 *
1988 *
1989 *
1990 */
yfWriterForSpec(fbConnSpec_t * spec,uint32_t domain,gboolean export_meta,GError ** err)1991 fBuf_t *yfWriterForSpec(
1992 fbConnSpec_t *spec,
1993 uint32_t domain,
1994 gboolean export_meta,
1995 GError **err)
1996 {
1997 fBuf_t *fbuf = NULL;
1998 fbSession_t *session;
1999 fbExporter_t *exporter;
2000
2001 /* initialize session and exporter */
2002 if (!(session = yfInitExporterSession(domain, export_meta, err))) goto err;
2003
2004 exporter = fbExporterAllocNet(spec);
2005 fbuf = fBufAllocForExport(session, exporter);
2006
2007 /* set observation domain */
2008 fbSessionSetDomain(session, domain);
2009
2010 /* write YAF flow templates */
2011 if (!fbSessionExportTemplates(session, err)) goto err;
2012
2013 /* set internal template */
2014 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) goto err;
2015
2016 /* all done */
2017 return fbuf;
2018
2019 err:
2020 /* free buffer if necessary */
2021 if (fbuf) fBufFree(fbuf);
2022 return NULL;
2023 }
2024
2025 /**
2026 *yfWriteOptionsDataFlows
2027 *
2028 *
2029 */
yfWriteOptionsDataFlows(void * yfContext,uint32_t pcap_drop,GTimer * timer,GError ** err)2030 gboolean yfWriteOptionsDataFlows(
2031 void *yfContext,
2032 uint32_t pcap_drop,
2033 GTimer *timer,
2034 GError **err)
2035 {
2036 yfContext_t *ctx = (yfContext_t *)yfContext;
2037
2038 if(!yfWriteStatsFlow(yfContext, pcap_drop, timer, err)){
2039 return FALSE;
2040 }
2041 if(!ctx->cfg->no_tombstone){
2042 if(!yfWriteTombstoneFlow(yfContext, err)){
2043 return FALSE;
2044 }
2045 }
2046 return TRUE;
2047 }
2048
2049 /**
2050 *yfWriteStatsFlow
2051 *
2052 *
2053 */
yfWriteStatsFlow(void * yfContext,uint32_t pcap_drop,GTimer * timer,GError ** err)2054 gboolean yfWriteStatsFlow(
2055 void *yfContext,
2056 uint32_t pcap_drop,
2057 GTimer *timer,
2058 GError **err)
2059 {
2060 yfIpfixStats_t rec;
2061 yfContext_t *ctx = (yfContext_t *)yfContext;
2062 fBuf_t *fbuf = ctx->fbuf;
2063 uint32_t mask = 0x000000FF;
2064 char buf[200];
2065 uint32_t total_frags = 0;
2066 static struct hostent *host;
2067 static uint32_t host_ip = 0;
2068
2069 #if HAVE_SPREAD
2070 fbSpreadParams_t *spParam = &(ctx->cfg->spreadparams);
2071 #endif
2072
2073 yfGetFlowTabStats(ctx->flowtab, &(rec.packetTotalCount),
2074 &(rec.exportedFlowTotalCount),
2075 &(rec.notSentPacketTotalCount),
2076 &(rec.flowTablePeakCount), &(rec.flowTableFlushEvents));
2077 if (ctx->fragtab) {
2078 yfGetFragTabStats(ctx->fragtab, &(rec.expiredFragmentCount),
2079 &(rec.assembledFragmentCount), &total_frags);
2080 } else {
2081 rec.expiredFragmentCount = 0;
2082 rec.assembledFragmentCount = 0;
2083 }
2084
2085 if (!fbuf) {
2086 g_set_error(err, YAF_ERROR_DOMAIN, YAF_ERROR_IO,
2087 "Error Writing Stats Message: No fbuf [output] Available");
2088 return FALSE;
2089 }
2090
2091 /* Get IP of sensor for scope */
2092 if (!host) {
2093 gethostname(buf, 200);
2094 host = (struct hostent *)gethostbyname(buf);
2095 if (host) {
2096 host_ip = (host->h_addr[0] & mask) << 24;
2097 host_ip |= (host->h_addr[1] & mask) << 16;
2098 host_ip |= (host->h_addr[2] & mask) << 8;
2099 host_ip |= (host->h_addr[3] & mask);
2100 }
2101 }
2102
2103 /* Rejected/Ignored Packet Total Count from decode.c */
2104 rec.ignoredPacketTotalCount = yfGetDecodeStats(ctx->dectx);
2105
2106 /* Dropped packets - from yafcap.c & libpcap */
2107 rec.droppedPacketTotalCount = pcap_drop;
2108 rec.exporterIPv4Address = host_ip;
2109
2110 rec.observationDomainId = ctx->cfg->odid;
2111 rec.exportingProcessId = getpid();
2112 rec.observationTimeSeconds = (int)time(NULL);
2113
2114 rec.meanFlowRate = rec.exportedFlowTotalCount/g_timer_elapsed(timer, NULL);
2115 rec.meanPacketRate = rec.packetTotalCount / g_timer_elapsed(timer, NULL);
2116
2117 rec.systemInitTimeMilliseconds = ctx->yaf_start_time;
2118
2119 g_debug("YAF statistics: Flows: %llu Packets: %llu Dropped: %lu Ignored: %lu "
2120 "Out of Sequence: %"PRIu64" Expired Frags: %u Assembled Frags: %u",
2121 (long long unsigned int)rec.exportedFlowTotalCount,
2122 (long long unsigned int)rec.packetTotalCount,
2123 rec.droppedPacketTotalCount, rec.ignoredPacketTotalCount,
2124 rec.notSentPacketTotalCount, rec.expiredFragmentCount,
2125 rec.assembledFragmentCount);
2126
2127 /* Set Internal Template for Buffer to Options TID */
2128 if (!fBufSetInternalTemplate(fbuf, YAF_PROCESS_STATS_TID, err))
2129 return FALSE;
2130
2131 #if HAVE_SPREAD
2132 if (ctx->cfg->spreadGroupIndex) {
2133 fBufSetSpreadExportGroup(fbuf, spParam->groups,
2134 ctx->cfg->numSpreadGroups, err);
2135 }
2136 #endif
2137
2138 /* Set Export Template for Buffer to Options TMPL */
2139 if (!yfSetExportTemplate(fbuf, YAF_PROCESS_STATS_TID, err)) {
2140 return FALSE;
2141 }
2142
2143 /* Append Record */
2144 if (!fBufAppend(fbuf, (uint8_t *)&rec, sizeof(rec), err)) {
2145 return FALSE;
2146 }
2147
2148 /* emit buffer */
2149 if (!fBufEmit(fbuf, err)) {
2150 return FALSE;
2151 }
2152
2153 /* Set Internal TID Back to Flow Record */
2154 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) {
2155 return FALSE;
2156 }
2157
2158 return TRUE;
2159 }
2160
2161 /**
2162 *yfWriteTombstoneFlow
2163 *
2164 *
2165 */
yfWriteTombstoneFlow(void * yfContext,GError ** err)2166 gboolean yfWriteTombstoneFlow(
2167 void *yfContext,
2168 GError **err)
2169 {
2170 yfTombstoneRecord_t rec;
2171 yfContext_t *ctx = (yfContext_t *)yfContext;
2172 fBuf_t *fbuf = ctx->fbuf;
2173 static uint32_t tombstoneId = 0;
2174 uint32_t currentTime;
2175 yfTombstoneAccess_t *accessListPtr;
2176
2177
2178 #if HAVE_SPREAD
2179 fbSpreadParams_t *spParam = &(ctx->cfg->spreadparams);
2180 #endif
2181
2182 if (!fbuf) {
2183 g_set_error(err, YAF_ERROR_DOMAIN, YAF_ERROR_IO,
2184 "Error Writing Stats Message: No fbuf [output] Available");
2185 return FALSE;
2186 }
2187
2188 /* Set Internal Template for Buffer to Options TID */
2189 if (!fBufSetInternalTemplate(fbuf, YAF_TOMBSTONE_TID, err))
2190 return FALSE;
2191
2192 #if HAVE_SPREAD
2193 if (ctx->cfg->spreadGroupIndex) {
2194 fBufSetSpreadExportGroup(fbuf, spParam->groups,
2195 ctx->cfg->numSpreadGroups, err);
2196 }
2197 #endif
2198
2199 /* Set Export Template for Buffer to Options TMPL */
2200 if (!yfSetExportTemplate(fbuf, YAF_TOMBSTONE_TID, err)) {
2201 return FALSE;
2202 }
2203
2204 memset(rec.paddingOctets, 0, sizeof(rec.paddingOctets));
2205 currentTime = (uint32_t)time(NULL);
2206 rec.tombstoneId = tombstoneId++;
2207 rec.exporterConfiguredId = ctx->cfg->tombstone_configured_id;
2208 rec.exportingProcessId = getpid();
2209 rec.observationTimeSeconds = currentTime;
2210 rec.observationDomainId = ctx->cfg->odid;
2211 accessListPtr = (yfTombstoneAccess_t *)fbSubTemplateListInit(
2212 &(rec.accessList), 0,
2213 YAF_TOMBSTONE_ACCESS_TID,
2214 yaf_tmpl.tombstoneAccessTemplate, 1);
2215
2216 accessListPtr->certToolId = 1;
2217 accessListPtr->observationTimeSeconds = currentTime;
2218
2219 /* Append Record */
2220 if (!fBufAppend(fbuf, (uint8_t *)&rec, sizeof(rec), err)) {
2221 return FALSE;
2222 }
2223
2224 /* emit buffer */
2225 if (!fBufEmit(fbuf, err)) {
2226 return FALSE;
2227 }
2228
2229 g_message("Sent Tombstone record: observationDomain:%d, "
2230 "exporterId:%d:%d, tombstoneId: %d",
2231 rec.observationDomainId, rec.exporterConfiguredId,
2232 rec.exportingProcessId, rec.tombstoneId);
2233
2234 fbSubTemplateListClear(&(rec.accessList));
2235
2236 /* Set Internal TID Back to Flow Record */
2237 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err)) {
2238 return FALSE;
2239 }
2240
2241 return TRUE;
2242 }
2243
2244 /**
2245 *yfWriteFlow
2246 *
2247 *
2248 *
2249 */
yfWriteFlow(void * yfContext,yfFlow_t * flow,GError ** err)2250 gboolean yfWriteFlow(
2251 void *yfContext,
2252 yfFlow_t *flow,
2253 GError **err)
2254 {
2255 yfIpfixFlow_t rec;
2256 uint16_t wtid;
2257 uint16_t etid = 0; /* extra templates */
2258 fbSubTemplateMultiListEntry_t *stml = NULL;
2259 yfTcpFlow_t *tcprec = NULL;
2260 yfMacFlow_t *macrec = NULL;
2261 yfMPTCPFlow_t *mptcprec = NULL;
2262 int tmplcount = 0;
2263 gboolean ok;
2264 gboolean stats = FALSE;
2265 int32_t temp = 0;
2266 int loop, count;
2267 #if YAF_ENABLE_ENTROPY
2268 yfEntropyFlow_t *entropyrec;
2269 #endif
2270 #if YAF_ENABLE_P0F
2271 yfP0fFlow_t *p0frec;
2272 #endif
2273 #if YAF_ENABLE_FPEXPORT
2274 yfFPExportFlow_t *fpexportrec;
2275 #endif
2276 #if YAF_ENABLE_PAYLOAD
2277 yfPayloadFlow_t *payrec;
2278 #endif
2279 yfContext_t *ctx = (yfContext_t *)yfContext;
2280 fBuf_t *fbuf = ctx->fbuf;
2281 yfFlowStatsRecord_t *statsflow = NULL;
2282 #if HAVE_SPREAD
2283 char *spgroups[25];
2284 int i = 0, k = 0;
2285 fbSpreadParams_t *spParam = &(ctx->cfg->spreadparams);
2286 uint16_t spGroupBy = 0;
2287 #endif
2288
2289 if (ctx->cfg->no_output) {
2290 return TRUE;
2291 }
2292
2293 /* copy time */
2294 rec.flowStartMilliseconds = flow->stime;
2295 rec.flowEndMilliseconds = flow->etime;
2296 rec.reverseFlowDeltaMilliseconds = flow->rdtime;
2297
2298 /* copy addresses */
2299 if (yaf_core_map_ipv6 && (flow->key.version == 4)) {
2300 memcpy(rec.sourceIPv6Address, yaf_ip6map_pfx,
2301 sizeof(yaf_ip6map_pfx));
2302 *(uint32_t *)(&(rec.sourceIPv6Address[sizeof(yaf_ip6map_pfx)])) =
2303 g_htonl(flow->key.addr.v4.sip);
2304 memcpy(rec.destinationIPv6Address, yaf_ip6map_pfx,
2305 sizeof(yaf_ip6map_pfx));
2306 *(uint32_t *)(&(rec.destinationIPv6Address[sizeof(yaf_ip6map_pfx)])) =
2307 g_htonl(flow->key.addr.v4.dip);
2308 } else if (flow->key.version == 4) {
2309 rec.sourceIPv4Address = flow->key.addr.v4.sip;
2310 rec.destinationIPv4Address = flow->key.addr.v4.dip;
2311 } else if (flow->key.version == 6) {
2312 memcpy(rec.sourceIPv6Address, flow->key.addr.v6.sip,
2313 sizeof(rec.sourceIPv6Address));
2314 memcpy(rec.destinationIPv6Address, flow->key.addr.v6.dip,
2315 sizeof(rec.destinationIPv6Address));
2316 } else {
2317 g_set_error(err, YAF_ERROR_DOMAIN, YAF_ERROR_ARGUMENT,
2318 "Illegal IP version %u", flow->key.version);
2319 }
2320
2321
2322 /* choose options for basic template */
2323 wtid = YAF_FLOW_BASE_TID;
2324 rec.vlanId = flow->val.vlan;
2325 /* right? */
2326 rec.reverseVlanId = flow->rval.vlan;
2327
2328 /* copy key and counters */
2329 rec.sourceTransportPort = flow->key.sp;
2330 rec.destinationTransportPort = flow->key.dp;
2331 rec.flowAttributes = flow->val.attributes;
2332 rec.reverseFlowAttributes = flow->rval.attributes;
2333 rec.protocolIdentifier = flow->key.proto;
2334 rec.flowEndReason = flow->reason;
2335
2336 if (ctx->cfg->deltaMode) {
2337 rec.octetDeltaCount = flow->val.oct;
2338 rec.reverseOctetDeltaCount = flow->rval.oct;
2339 rec.packetDeltaCount = flow->val.pkt;
2340 rec.reversePacketDeltaCount = flow->rval.pkt;
2341 wtid |= YTF_DELTA;
2342 } else {
2343 rec.octetTotalCount = flow->val.oct;
2344 rec.reverseOctetTotalCount = flow->rval.oct;
2345 rec.packetTotalCount = flow->val.pkt;
2346 rec.reversePacketTotalCount = flow->rval.pkt;
2347 wtid |= YTF_TOTAL;
2348 }
2349
2350 rec.ingressInterface = ctx->cfg->ingressInt;
2351 rec.egressInterface = ctx->cfg->egressInt;
2352
2353 /* Type Of Service */
2354 rec.ipClassOfService = flow->key.tos;
2355 rec.reverseIpClassOfService = flow->rtos;
2356
2357 #if YAF_ENABLE_DAG_SEPARATE_INTERFACES
2358 rec.ingressInterface = flow->key.netIf;
2359 rec.egressInterface = flow->key.netIf | 0x100;
2360 #endif
2361
2362 #if YAF_ENABLE_SEPARATE_INTERFACES
2363 rec.ingressInterface = flow->val.netIf;
2364 if (flow->rval.pkt) {
2365 rec.egressInterface = flow->rval.netIf;
2366 } else {
2367 rec.egressInterface = flow->val.netIf | 0x100;
2368 }
2369 #endif
2370
2371 #if YAF_ENABLE_APPLABEL
2372 rec.silkAppLabel = flow->appLabel;
2373
2374 #if HAVE_SPREAD
2375 spGroupBy = yfSpreadGroupby(ctx->cfg->spreadGroupby, rec.silkAppLabel,
2376 rec.vlanId, rec.destinationTransportPort,
2377 rec.protocolIdentifier, flow->key.version);
2378 #endif
2379 #else
2380 #if HAVE_SPREAD
2381 spGroupBy = yfSpreadGroupby(ctx->cfg->spreadGroupby, 0, rec.vlanId,
2382 rec.destinationTransportPort,
2383 rec.protocolIdentifier, flow->key.version);
2384 #endif
2385 #endif
2386
2387 #if YAF_ENABLE_NDPI
2388 rec.ndpi_master = flow->ndpi_master;
2389 rec.ndpi_sub = flow->ndpi_sub;
2390 #endif
2391
2392 #if YAF_MPLS
2393 /* since the mpls label isn't defined as an integer in fixbuf, it's
2394 not endian-converted on transcode, so we fix that here */
2395 /* temp = htonl(flow->mpls->mpls_label[0]) >> 8;*/
2396 memcpy(rec.mpls_label1, &(flow->mpls->mpls_label[0]), 3);
2397 /*temp = htonl(flow->mpls->mpls_label[1]) >> 8;*/
2398 memcpy(rec.mpls_label2, &(flow->mpls->mpls_label[1]), 3);
2399 /*temp = htonl(flow->mpls->mpls_label[2]) >> 8;*/
2400 memcpy(rec.mpls_label3, &(flow->mpls->mpls_label[2]), 3);
2401 #endif
2402
2403 #if HAVE_SPREAD
2404 /* Find out which groups we need to send this flow to */
2405 for (i = 0; i < ctx->cfg->numSpreadGroups; i++) {
2406 if (ctx->cfg->spreadGroupIndex[i] == spGroupBy ||
2407 ctx->cfg->spreadGroupIndex[i] == 0) {
2408 spgroups[k] = (spParam->groups[i]);
2409 k++;
2410 }
2411 }
2412 #endif
2413
2414 if (flow->rval.pkt) {
2415 wtid |= YTF_BIF;
2416 etid = YTF_BIF;
2417 }
2418
2419 if (rec.protocolIdentifier == YF_PROTO_TCP) {
2420 if (ctx->cfg->silkmode) {
2421 rec.tcpSequenceNumber = flow->val.isn;
2422 rec.reverseTcpSequenceNumber = flow->rval.isn;
2423 rec.initialTCPFlags = flow->val.iflags;
2424 rec.reverseInitialTCPFlags = flow->rval.iflags;
2425 rec.unionTCPFlags = flow->val.uflags;
2426 rec.reverseUnionTCPFlags = flow->rval.uflags;
2427 wtid |= YTF_SILK;
2428 } else {
2429 tmplcount++;
2430 }
2431 }
2432
2433 #if YAF_MPLS
2434 wtid |= YTF_MPLS;
2435 #endif
2436
2437 if (flow->val.oct < YAF_RLEMAX && flow->rval.oct < YAF_RLEMAX &&
2438 flow->val.pkt < YAF_RLEMAX && flow->rval.pkt < YAF_RLEMAX)
2439 {
2440 wtid |= YTF_RLE;
2441 } else {
2442 wtid |= YTF_FLE;
2443 }
2444
2445 if (yaf_core_map_ipv6 || (flow->key.version == 6)) {
2446 wtid |= YTF_IP6;
2447 } else {
2448 wtid |= YTF_IP4;
2449 }
2450
2451 if (rec.ingressInterface || rec.egressInterface) {
2452 wtid |= YTF_DAGIF;
2453 }
2454
2455 #if YAF_ENABLE_DAG_SEPARATE_INTERFACES || YAF_ENABLE_SEPARATE_INTERFACES
2456 if (ctx->cfg->exportInterface) {
2457 wtid |= YTF_DAGIF;
2458 }
2459 #endif
2460
2461
2462
2463 #if HAVE_SPREAD
2464 /* If we are selectively setting groups to send this to - set groups
2465 on the export buffer */
2466 if (ctx->cfg->spreadGroupIndex) {
2467 if (k) {
2468 fBufSetSpreadExportGroup(fbuf, spgroups, k, err);
2469 } else {
2470 return TRUE;
2471 }
2472 /* Now make sure the groups have those templates */
2473 if (!yfSetSpreadExportTemplate(fbuf, spParam, wtid, spgroups, k, err)){
2474 return FALSE;
2475 }
2476 } else {
2477 /* we are sending to all groups */
2478 if (!yfSetExportTemplate(fbuf, wtid, err)) {
2479 return FALSE;
2480 }
2481 }
2482 #else
2483
2484 if (!yfSetExportTemplate(fbuf, wtid, err)) {
2485 return FALSE;
2486 }
2487 #endif
2488
2489 if (ctx->cfg->macmode) {
2490 tmplcount++;
2491 }
2492
2493 if (ctx->cfg->statsmode && flow->val.stats) {
2494 if (flow->val.stats->payoct || flow->rval.stats) {
2495 tmplcount++;
2496 stats = TRUE;
2497 }
2498 }
2499
2500 if ((flow->mptcp.token)) {
2501 tmplcount++;
2502 }
2503
2504 #if YAF_ENABLE_PAYLOAD
2505 /* point to payload */
2506 if ((0 < yaf_core_export_payload) &&
2507 (flow->val.paylen || flow->rval.paylen))
2508 {
2509 tmplcount++;
2510 }
2511 /* copy payload-derived information */
2512
2513 #if YAF_ENABLE_HOOKS
2514 tmplcount += yfHookGetTemplateCount(flow);
2515 #endif
2516
2517 #if YAF_ENABLE_ENTROPY
2518 if (flow->val.entropy || flow->rval.entropy) {
2519 tmplcount++;
2520 }
2521 #endif
2522
2523
2524 #if YAF_ENABLE_P0F
2525 if (flow->val.osname || flow->val.osver ||
2526 flow->rval.osname || flow->rval.osver ||
2527 flow->val.osFingerPrint || flow->rval.osFingerPrint)
2528 {
2529 tmplcount++;
2530 }
2531 #endif
2532
2533 #if YAF_ENABLE_FPEXPORT
2534 if (flow->val.firstPacket || flow->rval.firstPacket ||
2535 flow->val.secondPacket)
2536 {
2537 tmplcount++;
2538 }
2539 #endif
2540
2541 #endif
2542
2543 /* Initialize SubTemplateMultiList with number of templates we are to add*/
2544 fbSubTemplateMultiListInit(&(rec.subTemplateMultiList), 3, tmplcount);
2545
2546 /* Add TCP Template - IF TCP Flow and SiLK Mode is OFF */
2547 if (flow->key.proto == YF_PROTO_TCP && !ctx->cfg->silkmode) {
2548 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2549 if (etid) {
2550 tcprec = (yfTcpFlow_t *)FBSTMLINIT(stml,
2551 (YAF_TCP_FLOW_TID | etid),
2552 yaf_tmpl.revTcpTemplate);
2553 tcprec->reverseTcpSequenceNumber = flow->rval.isn;
2554 tcprec->reverseInitialTCPFlags = flow->rval.iflags;
2555 tcprec->reverseUnionTCPFlags = flow->rval.uflags;
2556 } else {
2557 tcprec = (yfTcpFlow_t *)FBSTMLINIT(stml, YAF_TCP_FLOW_TID,
2558 yaf_tmpl.tcpTemplate);
2559 }
2560 tcprec->tcpSequenceNumber = flow->val.isn;
2561 tcprec->initialTCPFlags = flow->val.iflags;
2562 tcprec->unionTCPFlags = flow->val.uflags;
2563 tmplcount--;
2564 }
2565
2566 /* Add MAC Addresses */
2567 if (ctx->cfg->macmode) {
2568 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2569 macrec = (yfMacFlow_t *)FBSTMLINIT(stml, YAF_MAC_FLOW_TID,
2570 yaf_tmpl.macTemplate);
2571 memcpy(macrec->sourceMacAddress, flow->sourceMacAddr,
2572 ETHERNET_MAC_ADDR_LENGTH);
2573 memcpy(macrec->destinationMacAddress, flow->destinationMacAddr,
2574 ETHERNET_MAC_ADDR_LENGTH);
2575 tmplcount--;
2576 }
2577
2578 if (flow->mptcp.token) {
2579 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2580 mptcprec = (yfMPTCPFlow_t *)FBSTMLINIT(stml, YAF_MPTCP_FLOW_TID,
2581 yaf_tmpl.mptcpTemplate);
2582 memcpy(mptcprec, &(flow->mptcp), sizeof(yfMPTCPFlow_t));
2583 tmplcount --;
2584 }
2585
2586 #if YAF_ENABLE_PAYLOAD
2587 /* Add Payload Template */
2588 if ((0 < yaf_core_export_payload) &&
2589 (flow->val.paylen || flow->rval.paylen))
2590 {
2591 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2592 if (etid) {
2593 payrec = (yfPayloadFlow_t *)FBSTMLINIT(stml,
2594 YAF_PAYLOAD_FLOW_TID | etid,
2595 yaf_tmpl.revPayloadTemplate);
2596 if (flow->rval.paylen > yaf_core_export_payload) {
2597 payrec->reversePayload.len = yaf_core_export_payload;
2598 } else {
2599 payrec->reversePayload.len = flow->rval.paylen;
2600 }
2601 payrec->reversePayload.buf = flow->rval.payload;
2602 } else {
2603 payrec = (yfPayloadFlow_t *)FBSTMLINIT(stml,
2604 YAF_PAYLOAD_FLOW_TID,
2605 yaf_tmpl.payloadTemplate);
2606 }
2607 payrec->payload.buf = flow->val.payload;
2608 if (flow->val.paylen > yaf_core_export_payload) {
2609 payrec->payload.len = yaf_core_export_payload;
2610 } else {
2611 payrec->payload.len = flow->val.paylen;
2612 }
2613 tmplcount--;
2614 }
2615 #endif
2616
2617
2618 #if YAF_ENABLE_ENTROPY
2619 /* Add Entropy Template */
2620 if (flow->val.entropy || flow->rval.entropy) {
2621 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2622 if (etid) {
2623 entropyrec = (yfEntropyFlow_t *)FBSTMLINIT(stml,
2624 YAF_ENTROPY_FLOW_TID | etid,
2625 yaf_tmpl.revEntropyTemplate);
2626 entropyrec->reverseEntropy = flow->rval.entropy;
2627 } else {
2628 entropyrec = (yfEntropyFlow_t *)FBSTMLINIT(stml,
2629 YAF_ENTROPY_FLOW_TID,
2630 yaf_tmpl.entropyTemplate);
2631 }
2632 entropyrec->entropy = flow->val.entropy;
2633 tmplcount--;
2634 }
2635 #endif
2636
2637 #if YAF_ENABLE_P0F
2638 /* Add P0F Template */
2639 if (flow->val.osname || flow->val.osver || flow->rval.osname ||
2640 flow->rval.osver || flow->val.osFingerPrint ||flow->rval.osFingerPrint)
2641 {
2642 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2643 if (etid) {
2644 p0frec = (yfP0fFlow_t *)FBSTMLINIT(stml,
2645 YAF_P0F_FLOW_TID | etid,
2646 yaf_tmpl.revP0fTemplate);
2647 if (NULL != flow->rval.osname) {
2648 p0frec->reverseOsName.buf = (uint8_t *)flow->rval.osname;
2649 p0frec->reverseOsName.len = strlen(flow->rval.osname);
2650 } else {
2651 p0frec->reverseOsName.len = 0;
2652 }
2653 if (NULL != flow->rval.osver) {
2654 p0frec->reverseOsVersion.buf = (uint8_t *)flow->rval.osver;
2655 p0frec->reverseOsVersion.len = strlen(flow->rval.osver);
2656 } else {
2657 p0frec->reverseOsVersion.len = 0;
2658 }
2659 if (NULL != flow->rval.osFingerPrint) {
2660 p0frec->reverseOsFingerPrint.buf = (uint8_t *)
2661 flow->rval.osFingerPrint;
2662 p0frec->reverseOsFingerPrint.len =
2663 strlen(flow->rval.osFingerPrint);
2664 } else {
2665 p0frec->reverseOsFingerPrint.len = 0;
2666 }
2667 } else {
2668 p0frec = (yfP0fFlow_t *)FBSTMLINIT(stml, YAF_P0F_FLOW_TID,
2669 yaf_tmpl.p0fTemplate);
2670 }
2671 if (NULL != flow->val.osname) {
2672 p0frec->osName.buf = (uint8_t *)flow->val.osname;
2673 p0frec->osName.len = strlen(flow->val.osname);
2674 } else {
2675 p0frec->osName.len = 0;
2676 }
2677
2678 if (NULL != flow->val.osver) {
2679 p0frec->osVersion.buf = (uint8_t *)flow->val.osver;
2680 p0frec->osVersion.len = strlen(flow->val.osver);
2681 } else {
2682 p0frec->osVersion.len = 0;
2683 }
2684
2685 if (NULL != flow->val.osFingerPrint) {
2686 p0frec->osFingerPrint.buf = (uint8_t *) flow->val.osFingerPrint;
2687 p0frec->osFingerPrint.len = strlen(flow->val.osFingerPrint);
2688 } else {
2689 p0frec->osFingerPrint.len = 0;
2690 }
2691 tmplcount--;
2692 }
2693 #endif
2694
2695 #if YAF_ENABLE_FPEXPORT
2696 /* Add FingerPrint Template */
2697 if (flow->val.firstPacket || flow->rval.firstPacket ||
2698 flow->val.secondPacket)
2699 {
2700 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2701
2702 if (etid) {
2703 fpexportrec = (yfFPExportFlow_t *)FBSTMLINIT(stml,
2704 (YAF_FPEXPORT_FLOW_TID | etid),
2705 yaf_tmpl.revFpexportTemplate);
2706 fpexportrec->reverseFirstPacketBanner.buf = flow->rval.firstPacket;
2707 fpexportrec->reverseFirstPacketBanner.len =
2708 flow->rval.firstPacketLen;
2709 } else {
2710 fpexportrec = (yfFPExportFlow_t *)FBSTMLINIT(stml,
2711 YAF_FPEXPORT_FLOW_TID,
2712 yaf_tmpl.fpexportTemplate);
2713 }
2714 fpexportrec->firstPacketBanner.buf = flow->val.firstPacket;
2715 fpexportrec->firstPacketBanner.len = flow->val.firstPacketLen;
2716 fpexportrec->secondPacketBanner.buf = flow->val.secondPacket;
2717 fpexportrec->secondPacketBanner.len = flow->val.secondPacketLen;
2718 tmplcount--;
2719 }
2720 #endif
2721
2722 if (stats) {
2723 uint16_t pktavg = 0;
2724 stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml);
2725 if (etid) {
2726 statsflow =
2727 (yfFlowStatsRecord_t *)FBSTMLINIT(stml,
2728 (YAF_STATS_FLOW_TID | etid),
2729 yaf_tmpl.revfstatsTemplate);
2730 statsflow->reverseTcpUrgTotalCount = flow->rval.stats->tcpurgct;
2731 statsflow->reverseSmallPacketCount = flow->rval.stats->smallpktct;
2732 statsflow->reverseFirstNonEmptyPacketSize =
2733 flow->rval.stats->firstpktsize;
2734 statsflow->reverseNonEmptyPacketCount =
2735 flow->rval.stats->nonemptypktct;
2736 statsflow->reverseLargePacketCount =
2737 flow->rval.stats->largepktct;
2738 statsflow->reverseDataByteCount = flow->rval.stats->payoct;
2739 count = (statsflow->reverseNonEmptyPacketCount > 10) ? 10 : statsflow->reverseNonEmptyPacketCount;
2740 if (flow->rval.stats->nonemptypktct) {
2741 pktavg =flow->rval.stats->payoct/flow->rval.stats->nonemptypktct;
2742 }
2743 for (loop = 0; loop < count; loop++) {
2744 temp += (pow(abs(flow->rval.stats->pktsize[loop] - pktavg), 2));
2745 }
2746 if (count) {
2747 statsflow->reverseStandardDeviationPayloadLength =
2748 sqrt(temp / count);
2749 }
2750 if (flow->rval.pkt > 1) {
2751 uint64_t time_temp = 0;
2752 statsflow->reverseAverageInterarrivalTime =
2753 flow->rval.stats->aitime /(flow->rval.pkt - 1);
2754 count = (flow->rval.pkt > 11) ? 10 : (flow->rval.pkt - 1);
2755 for (loop = 0; loop < count; loop++) {
2756 time_temp += (pow(labs(flow->rval.stats->iaarray[loop] -
2757 statsflow->reverseAverageInterarrivalTime), 2));
2758 }
2759 statsflow->reverseStandardDeviationInterarrivalTime =
2760 sqrt(time_temp / count);
2761 }
2762 statsflow->reverseMaxPacketSize = flow->rval.stats->maxpktsize;
2763 } else {
2764 statsflow = (yfFlowStatsRecord_t *)FBSTMLINIT(stml,
2765 YAF_STATS_FLOW_TID,
2766 yaf_tmpl.fstatsTemplate);
2767 }
2768 pktavg = 0;
2769 statsflow->tcpUrgTotalCount = flow->val.stats->tcpurgct;
2770 statsflow->smallPacketCount = flow->val.stats->smallpktct;
2771 statsflow->firstNonEmptyPacketSize = flow->val.stats->firstpktsize;
2772 statsflow->nonEmptyPacketCount = flow->val.stats->nonemptypktct;
2773 statsflow->dataByteCount = flow->val.stats->payoct;
2774 statsflow->maxPacketSize = flow->val.stats->maxpktsize;
2775 statsflow->firstEightNonEmptyPacketDirections = flow->pktdir;
2776 statsflow->largePacketCount = flow->val.stats->largepktct;
2777 temp = 0;
2778 count = (statsflow->nonEmptyPacketCount < 10) ? statsflow->nonEmptyPacketCount : 10;
2779 if (flow->val.stats->nonemptypktct) {
2780 pktavg = flow->val.stats->payoct / flow->val.stats->nonemptypktct;
2781 }
2782 for (loop = 0; loop < count; loop++) {
2783 temp += (pow(abs(flow->val.stats->pktsize[loop] - pktavg), 2));
2784 }
2785 if (count) {
2786 statsflow->standardDeviationPayloadLength =
2787 sqrt(temp / count);
2788 }
2789 if (flow->val.pkt > 1) {
2790 uint64_t time_temp = 0;
2791 statsflow->averageInterarrivalTime = flow->val.stats->aitime /
2792 (flow->val.pkt - 1);
2793 count = (flow->val.pkt > 11) ? 10 : (flow->val.pkt - 1);
2794 for (loop = 0; loop < count; loop++) {
2795 time_temp += (pow(labs(flow->val.stats->iaarray[loop] -
2796 statsflow->averageInterarrivalTime),2));
2797 }
2798 statsflow->standardDeviationInterarrivalTime=sqrt(time_temp/count);
2799 }
2800 tmplcount--;
2801 }
2802
2803 #if YAF_ENABLE_HOOKS
2804 /* write hook record - only add if there are some available in list*/
2805 if (!yfWriteFlowHook(&(rec.subTemplateMultiList), stml, flow, err)) {
2806 return FALSE;
2807 }
2808 # endif
2809
2810 /* IF UDP - Check to see if we need to re-export templates */
2811 /* We do not advise in using UDP (nicer than saying you're stupid) */
2812 if ((ctx->cfg->connspec.transport == FB_UDP) ||
2813 (ctx->cfg->connspec.transport == FB_DTLS_UDP))
2814 {
2815 /* 3 is the factor from RFC 5101 as a recommendation of how often
2816 between timeouts to resend */
2817 if ((flow->etime > ctx->lastUdpTempTime) &&
2818 ((flow->etime - ctx->lastUdpTempTime) >
2819 ((ctx->cfg->yaf_udp_template_timeout)/3)))
2820 {
2821 /* resend templates */
2822 ok = fbSessionExportTemplates(fBufGetSession(ctx->fbuf), err);
2823 ctx->lastUdpTempTime = flow->etime;
2824 if (!ok) {
2825 g_warning("Failed to renew UDP Templates: %s",
2826 (*err)->message);
2827 g_clear_error(err);
2828 }
2829 }
2830 if (!(ctx->cfg->livetype)) {
2831 /* slow down UDP export if reading from a file */
2832 usleep(2);
2833 }
2834 }
2835
2836 /* Now append the record to the buffer */
2837 if (!fBufAppend(fbuf, (uint8_t *)&rec, sizeof(rec), err)) {
2838 return FALSE;
2839 }
2840
2841 #if YAF_ENABLE_HOOKS
2842 /* clear basic lists */
2843 yfHookFreeLists(flow);
2844 #endif
2845 /* Clear MultiList */
2846 fbSubTemplateMultiListClear(&(rec.subTemplateMultiList));
2847
2848 return TRUE;
2849 }
2850
2851 /**
2852 *yfWriterClose
2853 *
2854 *
2855 *
2856 */
yfWriterClose(fBuf_t * fbuf,gboolean flush,GError ** err)2857 gboolean yfWriterClose(
2858 fBuf_t *fbuf,
2859 gboolean flush,
2860 GError **err)
2861 {
2862 gboolean ok = TRUE;
2863
2864 if (flush) {
2865 ok = fBufEmit(fbuf, err);
2866 }
2867
2868 fBufFree(fbuf);
2869
2870 return ok;
2871 }
2872
2873 /**
2874 * yfTemplateCallback
2875 *
2876 *
2877 */
yfTemplateCallback(fbSession_t * session,uint16_t tid,fbTemplate_t * tmpl,void * app_ctx,void ** tmpl_ctx,fbTemplateCtxFree_fn * fn)2878 static void yfTemplateCallback(
2879 fbSession_t *session,
2880 uint16_t tid,
2881 fbTemplate_t *tmpl,
2882 void *app_ctx,
2883 void **tmpl_ctx,
2884 fbTemplateCtxFree_fn *fn)
2885 {
2886 uint16_t ntid;
2887
2888 ntid = tid & YTF_REV;
2889
2890 if (YAF_FLOW_BASE_TID == (tid & 0xF000)) {
2891 fbSessionAddTemplatePair(session, tid, tid);
2892 }
2893
2894 if (ntid == YAF_ENTROPY_FLOW_TID) {
2895 fbSessionAddTemplatePair(session, tid, tid);
2896 } else if (ntid == YAF_TCP_FLOW_TID) {
2897 fbSessionAddTemplatePair(session, tid, tid);
2898 } else if (ntid == YAF_MAC_FLOW_TID) {
2899 fbSessionAddTemplatePair(session, tid, tid);
2900 } else if (ntid == YAF_PAYLOAD_FLOW_TID) {
2901 fbSessionAddTemplatePair(session, tid, tid);
2902 } else {
2903 /* Dont decode templates yafscii doesn't care about */
2904 fbSessionAddTemplatePair(session, tid, 0);
2905 }
2906
2907 }
2908
2909 /**
2910 *yfInitCollectorSession
2911 *
2912 *
2913 *
2914 */
yfInitCollectorSession(GError ** err)2915 static fbSession_t *yfInitCollectorSession(
2916 GError **err)
2917 {
2918 fbInfoModel_t *model = yfInfoModel();
2919 fbTemplate_t *tmpl = NULL;
2920 fbSession_t *session = NULL;
2921
2922 /* Allocate the session */
2923 session = fbSessionAlloc(model);
2924
2925 /* Add the full record template */
2926 tmpl = fbTemplateAlloc(model);
2927
2928 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec, YTF_ALL, err))
2929 return NULL;
2930 if (!fbSessionAddTemplate(session, TRUE, YAF_FLOW_FULL_TID, tmpl, err))
2931 return NULL;
2932
2933 #if YAF_ENABLE_ENTROPY
2934 yaf_tmpl.entropyTemplate = fbTemplateAlloc(model);
2935 if (!fbTemplateAppendSpecArray(yaf_tmpl.entropyTemplate, yaf_entropy_spec,
2936 0xffffffff, err)){
2937 return NULL;
2938 }
2939 if (!fbSessionAddTemplate(session, TRUE, YAF_ENTROPY_FLOW_TID,
2940 yaf_tmpl.entropyTemplate, err))
2941 {
2942 return NULL;
2943 }
2944 #endif
2945 yaf_tmpl.tcpTemplate = fbTemplateAlloc(model);
2946 if (!fbTemplateAppendSpecArray(yaf_tmpl.tcpTemplate, yaf_tcp_spec,
2947 0xffffffff, err))
2948 {
2949 return NULL;
2950 }
2951 if (!fbSessionAddTemplate(session, TRUE, YAF_TCP_FLOW_TID,
2952 yaf_tmpl.tcpTemplate, err))
2953 {
2954 return NULL;
2955 }
2956
2957 yaf_tmpl.macTemplate = fbTemplateAlloc(model);
2958 if (!fbTemplateAppendSpecArray(yaf_tmpl.macTemplate, yaf_mac_spec,
2959 0xffffffff, err))
2960 {
2961 return NULL;
2962 }
2963 if (!fbSessionAddTemplate(session, TRUE, YAF_MAC_FLOW_TID,
2964 yaf_tmpl.macTemplate, err))
2965 {
2966 return NULL;
2967 }
2968
2969 #if YAF_ENABLE_P0F
2970 yaf_tmpl.p0fTemplate = fbTemplateAlloc(model);
2971 if (!fbTemplateAppendSpecArray(yaf_tmpl.p0fTemplate, yaf_p0f_spec,
2972 0xffffffff, err))
2973 {
2974 return NULL;
2975 }
2976 if (!fbSessionAddTemplate(session, TRUE, YAF_P0F_FLOW_TID,
2977 yaf_tmpl.p0fTemplate, err))
2978 {
2979 return NULL;
2980 }
2981 #endif
2982
2983 #if YAF_ENABLE_FPEXPORT
2984 yaf_tmpl.fpexportTemplate = fbTemplateAlloc(model);
2985 if (!fbTemplateAppendSpecArray(yaf_tmpl.fpexportTemplate,
2986 yaf_fpexport_spec, 0xffffffff, err))
2987 {
2988 return NULL;
2989 }
2990 if (!fbSessionAddTemplate(session, TRUE, YAF_FPEXPORT_FLOW_TID,
2991 yaf_tmpl.fpexportTemplate, err))
2992 {
2993 return NULL;
2994 }
2995 #endif
2996
2997 #if YAF_ENABLE_PAYLOAD
2998 yaf_tmpl.payloadTemplate = fbTemplateAlloc(model);
2999 if(!fbTemplateAppendSpecArray(yaf_tmpl.payloadTemplate, yaf_payload_spec,
3000 0xffffffff, err))
3001 {
3002 return NULL;
3003 }
3004 if (!fbSessionAddTemplate(session, TRUE, YAF_PAYLOAD_FLOW_TID,
3005 yaf_tmpl.payloadTemplate, err))
3006 {
3007 return NULL;
3008 }
3009 #endif
3010
3011 /* Add the extended record template */
3012 tmpl = fbTemplateAlloc(model);
3013 if (!fbTemplateAppendSpecArray(tmpl, yaf_flow_spec, YTF_ALL, err))
3014 return NULL;
3015 if (!fbTemplateAppendSpecArray(tmpl, yaf_extime_spec, YTF_ALL, err))
3016 return NULL;
3017 if (!fbSessionAddTemplate(session, TRUE, YAF_FLOW_EXT_TID, tmpl, err))
3018 return NULL;
3019
3020 /* Done. Return the session. */
3021
3022 /** Add the template callback so we don't try to decode DPI */
3023 fbSessionAddNewTemplateCallback(session, yfTemplateCallback, NULL);
3024
3025 return session;
3026 }
3027
3028 /**
3029 *yfReaderForFP
3030 *
3031 *
3032 *
3033 */
yfReaderForFP(fBuf_t * fbuf,FILE * fp,GError ** err)3034 fBuf_t *yfReaderForFP(
3035 fBuf_t *fbuf,
3036 FILE *fp,
3037 GError **err)
3038 {
3039 fbSession_t *session;
3040 fbCollector_t *collector;
3041
3042 /* Allocate a collector for the file */
3043 collector = fbCollectorAllocFP(NULL, fp);
3044
3045 /* Allocate a buffer, or reset the collector */
3046 if (fbuf) {
3047 fBufSetCollector(fbuf, collector);
3048 } else {
3049 if (!(session = yfInitCollectorSession(err))) goto err;
3050 fbuf = fBufAllocForCollection(session, collector);
3051 }
3052
3053 /* FIXME do a preread? */
3054
3055 return fbuf;
3056
3057 err:
3058 /* free buffer if necessary */
3059 if (fbuf) fBufFree(fbuf);
3060 return NULL;
3061 }
3062
3063 /**
3064 *yfListenerForSpec
3065 *
3066 *
3067 *
3068 */
yfListenerForSpec(fbConnSpec_t * spec,fbListenerAppInit_fn appinit,fbListenerAppFree_fn appfree,GError ** err)3069 fbListener_t *yfListenerForSpec(
3070 fbConnSpec_t *spec,
3071 fbListenerAppInit_fn appinit,
3072 fbListenerAppFree_fn appfree,
3073 GError **err)
3074 {
3075 fbSession_t *session;
3076
3077 if (!(session = yfInitCollectorSession(err))) return NULL;
3078
3079 return fbListenerAlloc(spec, session, appinit, appfree, err);
3080 }
3081
3082
3083 /**
3084 *yfReadFlow
3085 *
3086 * read an IPFIX record in, with respect to fields YAF cares about
3087 *
3088 */
yfReadFlow(fBuf_t * fbuf,yfFlow_t * flow,GError ** err)3089 gboolean yfReadFlow(
3090 fBuf_t *fbuf,
3091 yfFlow_t *flow,
3092 GError **err)
3093 {
3094 yfIpfixFlow_t rec;
3095 size_t len;
3096 fbSubTemplateMultiListEntry_t *stml = NULL;
3097 yfTcpFlow_t *tcprec = NULL;
3098 fbTemplate_t *next_tmpl = NULL;
3099 yfMacFlow_t *macrec = NULL;
3100 #if YAF_ENABLE_ENTROPY
3101 yfEntropyFlow_t *entropyrec = NULL;
3102 #endif
3103 #if YAF_ENABLE_PAYLOAD
3104 yfPayloadFlow_t *payrec = NULL;
3105 #endif
3106
3107 len = sizeof(yfIpfixFlow_t);
3108
3109 /* Check if Options Template - if so - ignore */
3110 next_tmpl = fBufNextCollectionTemplate(fbuf, NULL, err);
3111 if (next_tmpl) {
3112 if (fbTemplateGetOptionsScope(next_tmpl)) {
3113 /* Stats Msg - Don't actually Decode */
3114 if (!fBufNext(fbuf, (uint8_t *)&rec, &len, err)) {
3115 return FALSE;
3116 }
3117 return TRUE;
3118 }
3119 } else {
3120 return FALSE;
3121 }
3122
3123 /* read next YAF record */
3124 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_FULL_TID, err))
3125 return FALSE;
3126 if (!fBufNext(fbuf, (uint8_t *)&rec, &len, err))
3127 return FALSE;
3128
3129 /* copy time */
3130 flow->stime = rec.flowStartMilliseconds;
3131 flow->etime = rec.flowEndMilliseconds;
3132 flow->rdtime = rec.reverseFlowDeltaMilliseconds;
3133 /* copy addresses */
3134 if (rec.sourceIPv4Address || rec.destinationIPv4Address) {
3135 flow->key.version = 4;
3136 flow->key.addr.v4.sip = rec.sourceIPv4Address;
3137 flow->key.addr.v4.dip = rec.destinationIPv4Address;
3138 } else {
3139 flow->key.version = 6;
3140 memcpy(flow->key.addr.v6.sip, rec.sourceIPv6Address,
3141 sizeof(flow->key.addr.v6.sip));
3142 memcpy(flow->key.addr.v6.dip, rec.destinationIPv6Address,
3143 sizeof(flow->key.addr.v6.dip));
3144 }
3145
3146 /* copy key and counters */
3147 flow->key.sp = rec.sourceTransportPort;
3148 flow->key.dp = rec.destinationTransportPort;
3149 flow->key.proto = rec.protocolIdentifier;
3150 flow->val.oct = rec.octetTotalCount;
3151 flow->val.pkt = rec.packetTotalCount;
3152 if (flow->val.oct == 0 && flow->val.pkt == 0) {
3153 flow->val.oct = rec.octetDeltaCount;
3154 flow->val.pkt = rec.packetDeltaCount;
3155 }
3156 flow->key.vlanId = rec.vlanId;
3157 flow->val.vlan = rec.vlanId;
3158 flow->rval.vlan = rec.reverseVlanId;
3159 flow->rval.oct = rec.reverseOctetTotalCount;
3160 flow->rval.pkt = rec.reversePacketTotalCount;
3161 flow->reason = rec.flowEndReason;
3162
3163 #if YAF_ENABLE_APPLABEL
3164 flow->appLabel = rec.silkAppLabel;
3165 #endif
3166 #if YAF_ENABLE_ENTROPY
3167 flow->val.entropy = 0;
3168 flow->rval.entropy = 0;
3169 #endif
3170 flow->val.isn = rec.tcpSequenceNumber;
3171 flow->val.iflags = rec.initialTCPFlags;
3172 flow->val.uflags = rec.unionTCPFlags;
3173 flow->rval.isn = rec.reverseTcpSequenceNumber;
3174 flow->rval.iflags = rec.reverseInitialTCPFlags;
3175 flow->rval.uflags = rec.reverseUnionTCPFlags;
3176
3177 /* Get subTemplateMultiList Entry */
3178 while ((stml = FBSTMLNEXT(&(rec.subTemplateMultiList), stml)))
3179 {
3180 switch ((stml->tmplID & YTF_REV)) {
3181
3182 #if YAF_ENABLE_ENTROPY
3183 case YAF_ENTROPY_FLOW_TID:
3184 entropyrec = (yfEntropyFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, entropyrec);
3185 flow->val.entropy = entropyrec->entropy;
3186 if ((stml->tmplID & YTF_BIF)) {
3187 flow->rval.entropy = entropyrec->reverseEntropy;
3188 }
3189 break;
3190 #endif
3191 case YAF_TCP_FLOW_TID:
3192 tcprec = (yfTcpFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, tcprec);
3193 flow->val.isn = tcprec->tcpSequenceNumber;
3194 flow->val.iflags = tcprec->initialTCPFlags;
3195 flow->val.uflags = tcprec->unionTCPFlags;
3196 if ((stml->tmplID & YTF_BIF)) {
3197 flow->rval.isn = tcprec->reverseTcpSequenceNumber;
3198 flow->rval.iflags = tcprec->reverseInitialTCPFlags;
3199 flow->rval.uflags = tcprec->reverseUnionTCPFlags;
3200 }
3201 break;
3202 case YAF_MAC_FLOW_TID:
3203 macrec = (yfMacFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, macrec);
3204 memcpy(flow->sourceMacAddr, macrec->sourceMacAddress,
3205 ETHERNET_MAC_ADDR_LENGTH);
3206 memcpy(flow->destinationMacAddr, macrec->destinationMacAddress,
3207 ETHERNET_MAC_ADDR_LENGTH);
3208 break;
3209 #if YAF_ENABLE_PAYLOAD
3210 case YAF_PAYLOAD_FLOW_TID:
3211 /* copy payload */
3212 payrec = (yfPayloadFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, payrec);
3213 yfPayloadCopyIn(&payrec->payload, &flow->val);
3214 if ((stml->tmplID & YTF_BIF)) {
3215 yfPayloadCopyIn(&payrec->reversePayload, &flow->rval);
3216 }
3217 break;
3218 # endif
3219 default:
3220 /* don't know about this template */
3221 break;
3222 }
3223 }
3224
3225 fbSubTemplateMultiListClear(&(rec.subTemplateMultiList));
3226
3227 return TRUE;
3228 }
3229
3230 /**
3231 *yfNTPDecode
3232 *
3233 * decodes a 64-bit NTP time variable and returns it in terms of
3234 * milliseconds
3235 *
3236 *
3237 */
yfNTPDecode(uint64_t ntp)3238 static uint64_t yfNTPDecode(
3239 uint64_t ntp)
3240 {
3241 double dntp;
3242 uint64_t millis;
3243
3244 if (!ntp) return 0;
3245
3246 dntp = (ntp & 0xFFFFFFFF00000000LL) >> 32;
3247 dntp += ((ntp & 0x00000000FFFFFFFFLL) * 1.0) / (2LL << 32);
3248 millis = dntp * 1000;
3249 return millis;
3250 }
3251
3252
3253 /**
3254 *yfReadFlowExtended
3255 *
3256 * read an IPFIX flow record in (with respect to fields YAF cares about)
3257 * using YAF's extended precision time recording
3258 *
3259 */
yfReadFlowExtended(fBuf_t * fbuf,yfFlow_t * flow,GError ** err)3260 gboolean yfReadFlowExtended(
3261 fBuf_t *fbuf,
3262 yfFlow_t *flow,
3263 GError **err)
3264 {
3265 yfIpfixExtFlow_t rec;
3266 fbTemplate_t *next_tmpl = NULL;
3267 size_t len;
3268 fbSubTemplateMultiListEntry_t *stml = NULL;
3269 yfTcpFlow_t *tcprec = NULL;
3270 yfMacFlow_t *macrec = NULL;
3271 #if YAF_ENABLE_ENTROPY
3272 yfEntropyFlow_t *entropyrec = NULL;
3273 #endif
3274 #if YAF_ENABLE_PAYLOAD
3275 yfPayloadFlow_t *payrec = NULL;
3276 #endif
3277
3278 /* read next YAF record; retrying on missing template or EOF. */
3279 len = sizeof(yfIpfixExtFlow_t);
3280 if (!fBufSetInternalTemplate(fbuf, YAF_FLOW_EXT_TID, err))
3281 return FALSE;
3282
3283 while (1) {
3284
3285 /* Check if Options Template - if so - ignore */
3286 next_tmpl = fBufNextCollectionTemplate(fbuf, NULL, err);
3287 if (next_tmpl) {
3288 if (fbTemplateGetOptionsScope(next_tmpl)) {
3289 if (!(fBufNext(fbuf, (uint8_t *)&rec, &len, err))) {
3290 return FALSE;
3291 }
3292 continue;
3293 }
3294 } else {
3295 return FALSE;
3296 }
3297 if (fBufNext(fbuf, (uint8_t *)&rec, &len, err)) {
3298 break;
3299 } else {
3300 if (g_error_matches(*err, FB_ERROR_DOMAIN, FB_ERROR_TMPL)) {
3301 /* try again on missing template */
3302 g_debug("skipping IPFIX data set: %s", (*err)->message);
3303 g_clear_error(err);
3304 continue;
3305 } else {
3306 /* real, actual error */
3307 return FALSE;
3308 }
3309 }
3310 }
3311
3312 /* Run the Gauntlet of Time. */
3313 if (rec.f.flowStartMilliseconds) {
3314 flow->stime = rec.f.flowStartMilliseconds;
3315 if (rec.f.flowEndMilliseconds >= rec.f.flowStartMilliseconds) {
3316 flow->etime = rec.f.flowEndMilliseconds;
3317 } else {
3318 flow->etime = flow->stime + rec.flowDurationMilliseconds;
3319 }
3320 } else if (rec.flowStartMicroseconds) {
3321 /* Decode NTP-format microseconds */
3322 flow->stime = yfNTPDecode(rec.flowStartMicroseconds);
3323 if (rec.flowEndMicroseconds >= rec.flowStartMicroseconds) {
3324 flow->etime = yfNTPDecode(rec.flowEndMicroseconds);
3325 } else {
3326 flow->etime = flow->stime + (rec.flowDurationMicroseconds / 1000);
3327 }
3328 } else if (rec.flowStartSeconds) {
3329 /* Seconds? Well. Okay... */
3330 flow->stime = rec.flowStartSeconds * 1000;
3331 flow->etime = rec.flowEndSeconds * 1000;
3332 } else if (rec.flowStartDeltaMicroseconds) {
3333 /* Handle delta microseconds. */
3334 flow->stime = fBufGetExportTime(fbuf) * 1000 -
3335 rec.flowStartDeltaMicroseconds / 1000;
3336 if (rec.flowEndDeltaMicroseconds &&
3337 rec.flowEndDeltaMicroseconds <= rec.flowStartDeltaMicroseconds) {
3338 flow->etime = fBufGetExportTime(fbuf) * 1000 -
3339 rec.flowEndDeltaMicroseconds / 1000;
3340 } else {
3341 flow->etime = flow->stime + (rec.flowDurationMicroseconds / 1000);
3342 }
3343 } else {
3344 /* Out of time. Use current timestamp, zero duration */
3345 struct timeval ct;
3346 g_assert(!gettimeofday(&ct, NULL));
3347 flow->stime = ((uint64_t)ct.tv_sec * 1000) +
3348 ((uint64_t)ct.tv_usec / 1000);
3349 flow->etime = flow->stime;
3350 }
3351
3352 /* copy private time field - reverse delta */
3353 flow->rdtime = rec.f.reverseFlowDeltaMilliseconds;
3354
3355 /* copy addresses */
3356 if (rec.f.sourceIPv4Address || rec.f.destinationIPv4Address) {
3357 flow->key.version = 4;
3358 flow->key.addr.v4.sip = rec.f.sourceIPv4Address;
3359 flow->key.addr.v4.dip = rec.f.destinationIPv4Address;
3360 } else {
3361 flow->key.version = 6;
3362 memcpy(flow->key.addr.v6.sip, rec.f.sourceIPv6Address,
3363 sizeof(flow->key.addr.v6.sip));
3364 memcpy(flow->key.addr.v6.dip, rec.f.destinationIPv6Address,
3365 sizeof(flow->key.addr.v6.dip));
3366 }
3367
3368 /* copy key and counters */
3369 flow->key.sp = rec.f.sourceTransportPort;
3370 flow->key.dp = rec.f.destinationTransportPort;
3371 flow->key.proto = rec.f.protocolIdentifier;
3372 flow->val.oct = rec.f.octetTotalCount;
3373 flow->val.pkt = rec.f.packetTotalCount;
3374 flow->rval.oct = rec.f.reverseOctetTotalCount;
3375 flow->rval.pkt = rec.f.reversePacketTotalCount;
3376 flow->key.vlanId = rec.f.vlanId;
3377 flow->val.vlan = rec.f.vlanId;
3378 flow->rval.vlan = rec.f.reverseVlanId;
3379 flow->reason = rec.f.flowEndReason;
3380 /* Handle delta counters */
3381 if (!(flow->val.oct)) {
3382 flow->val.oct = rec.f.octetDeltaCount;
3383 flow->rval.oct = rec.f.reverseOctetDeltaCount;
3384 }
3385 if (!(flow->val.pkt)) {
3386 flow->val.pkt = rec.f.packetDeltaCount;
3387 flow->rval.pkt = rec.f.reversePacketDeltaCount;
3388 }
3389
3390 #if YAF_ENABLE_APPLABEL
3391 flow->appLabel = rec.f.silkAppLabel;
3392 #endif
3393 #if YAF_ENABLE_NDPI
3394 flow->ndpi_master = rec.f.ndpi_master;
3395 flow->ndpi_sub = rec.f.ndpi_sub;
3396 #endif
3397
3398 #if YAF_ENABLE_ENTROPY
3399 flow->val.entropy = 0;
3400 flow->rval.entropy = 0;
3401 #endif
3402 flow->val.isn = rec.f.tcpSequenceNumber;
3403 flow->val.iflags = rec.f.initialTCPFlags;
3404 flow->val.uflags = rec.f.unionTCPFlags;
3405 flow->rval.isn = rec.f.reverseTcpSequenceNumber;
3406 flow->rval.iflags = rec.f.reverseInitialTCPFlags;
3407 flow->rval.uflags = rec.f.reverseUnionTCPFlags;
3408
3409 while ((stml = FBSTMLNEXT(&(rec.f.subTemplateMultiList), stml)))
3410 {
3411 switch ((stml->tmplID & YTF_REV)) {
3412 #if YAF_ENABLE_ENTROPY
3413 case YAF_ENTROPY_FLOW_TID:
3414 entropyrec = (yfEntropyFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, entropyrec);
3415 flow->val.entropy = entropyrec->entropy;
3416 if ((stml->tmplID & YTF_BIF)) {
3417 flow->rval.entropy = entropyrec->reverseEntropy;
3418 }
3419 break;
3420 #endif
3421 case YAF_TCP_FLOW_TID:
3422 tcprec = (yfTcpFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, tcprec);
3423 flow->val.isn = tcprec->tcpSequenceNumber;
3424 flow->val.iflags = tcprec->initialTCPFlags;
3425 flow->val.uflags = tcprec->unionTCPFlags;
3426 if ((stml->tmplID & YTF_BIF)) {
3427 flow->rval.isn = tcprec->reverseTcpSequenceNumber;
3428 flow->rval.iflags = tcprec->reverseInitialTCPFlags;
3429 flow->rval.uflags = tcprec->reverseUnionTCPFlags;
3430 }
3431 break;
3432 case YAF_MAC_FLOW_TID:
3433 macrec = (yfMacFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, macrec);
3434 memcpy(flow->sourceMacAddr, macrec->sourceMacAddress,
3435 ETHERNET_MAC_ADDR_LENGTH);
3436 memcpy(flow->destinationMacAddr, macrec->destinationMacAddress,
3437 ETHERNET_MAC_ADDR_LENGTH);
3438 break;
3439 #if YAF_ENABLE_PAYLOAD
3440 case YAF_PAYLOAD_FLOW_TID:
3441 /* copy payload */
3442 payrec = (yfPayloadFlow_t *)fbSubTemplateMultiListEntryNextDataPtr(stml, payrec);
3443 yfPayloadCopyIn(&payrec->payload, &flow->val);
3444 if ((stml->tmplID & YTF_BIF)) {
3445 yfPayloadCopyIn(&payrec->reversePayload, &flow->rval);
3446 }
3447 break;
3448 # endif
3449 default:
3450 fbSubTemplateMultiListEntryNextDataPtr(stml, NULL);
3451 break;
3452 }
3453 }
3454
3455 fbSubTemplateMultiListClear(&(rec.f.subTemplateMultiList));
3456
3457 return TRUE;
3458 }
3459
3460 /**
3461 *yfPrintFlags
3462 *
3463 *
3464 *
3465 */
yfPrintFlags(GString * str,uint8_t flags)3466 static void yfPrintFlags(
3467 GString *str,
3468 uint8_t flags)
3469 {
3470 if (flags & YF_TF_ECE) g_string_append_c(str, 'E');
3471 if (flags & YF_TF_CWR) g_string_append_c(str, 'C');
3472 if (flags & YF_TF_URG) g_string_append_c(str, 'U');
3473 if (flags & YF_TF_ACK) g_string_append_c(str, 'A');
3474 if (flags & YF_TF_PSH) g_string_append_c(str, 'P');
3475 if (flags & YF_TF_RST) g_string_append_c(str, 'R');
3476 if (flags & YF_TF_SYN) g_string_append_c(str, 'S');
3477 if (flags & YF_TF_FIN) g_string_append_c(str, 'F');
3478 if (!flags) g_string_append_c(str, '0');
3479 }
3480
3481 /**
3482 *yfPrintString
3483 *
3484 *
3485 *
3486 */
yfPrintString(GString * rstr,yfFlow_t * flow)3487 void yfPrintString(
3488 GString *rstr,
3489 yfFlow_t *flow)
3490 {
3491 char sabuf[AIR_IP6ADDR_BUF_MINSZ],
3492 dabuf[AIR_IP6ADDR_BUF_MINSZ];
3493
3494 /* print start as date and time */
3495 air_mstime_g_string_append(rstr, flow->stime, AIR_TIME_ISO8601);
3496
3497 /* print end as time and duration if not zero-duration */
3498 if (flow->stime != flow->etime) {
3499 g_string_append_printf(rstr, " - ");
3500 air_mstime_g_string_append(rstr, flow->etime, AIR_TIME_ISO8601_HMS);
3501 g_string_append_printf(rstr, " (%.3f sec)",
3502 (flow->etime - flow->stime) / 1000.0);
3503 }
3504
3505 /* print protocol and addresses */
3506 if (flow->key.version == 4) {
3507 air_ipaddr_buf_print(sabuf, flow->key.addr.v4.sip);
3508 air_ipaddr_buf_print(dabuf, flow->key.addr.v4.dip);
3509 } else if (flow->key.version == 6) {
3510 air_ip6addr_buf_print(sabuf, flow->key.addr.v6.sip);
3511 air_ip6addr_buf_print(dabuf, flow->key.addr.v6.dip);
3512 } else {
3513 sabuf[0] = (char)0;
3514 dabuf[0] = (char)0;
3515 }
3516
3517 switch (flow->key.proto) {
3518 case YF_PROTO_TCP:
3519 if (flow->rval.oct) {
3520 g_string_append_printf(rstr, " tcp %s:%u => %s:%u %08x:%08x ",
3521 sabuf, flow->key.sp, dabuf, flow->key.dp,
3522 flow->val.isn, flow->rval.isn);
3523 } else {
3524 g_string_append_printf(rstr, " tcp %s:%u => %s:%u %08x ",
3525 sabuf, flow->key.sp, dabuf, flow->key.dp,
3526 flow->val.isn);
3527 }
3528
3529 yfPrintFlags(rstr, flow->val.iflags);
3530 g_string_append_c(rstr,'/');
3531 yfPrintFlags(rstr, flow->val.uflags);
3532 if (flow->rval.oct) {
3533 g_string_append_c(rstr,':');
3534 yfPrintFlags(rstr, flow->rval.iflags);
3535 g_string_append_c(rstr,'/');
3536 yfPrintFlags(rstr, flow->rval.uflags);
3537 }
3538 break;
3539 case YF_PROTO_UDP:
3540 g_string_append_printf(rstr, " udp %s:%u => %s:%u",
3541 sabuf, flow->key.sp, dabuf, flow->key.dp);
3542 break;
3543 case YF_PROTO_ICMP:
3544 g_string_append_printf(rstr, " icmp [%u:%u] %s => %s",
3545 (flow->key.dp >> 8), (flow->key.dp & 0xFF),
3546 sabuf, dabuf);
3547 break;
3548 case YF_PROTO_ICMP6:
3549 g_string_append_printf(rstr, " icmp6 [%u:%u] %s => %s",
3550 (flow->key.dp >> 8), (flow->key.dp & 0xFF),
3551 sabuf, dabuf);
3552 break;
3553 default:
3554 g_string_append_printf(rstr, " ip %u %s => %s",
3555 flow->key.proto, sabuf, dabuf);
3556 break;
3557 }
3558
3559
3560 /* print vlan tags */
3561 if (flow->key.vlanId) {
3562 if (flow->rval.oct) {
3563 g_string_append_printf(rstr, " vlan %03hx:%03hx",
3564 flow->val.vlan, flow->rval.vlan);
3565 } else {
3566 g_string_append_printf(rstr, " vlan %03hx",
3567 flow->val.vlan);
3568 }
3569 }
3570
3571 /* print flow counters and round-trip time */
3572 if (flow->rval.pkt) {
3573 g_string_append_printf(rstr, " (%llu/%llu <-> %llu/%llu) rtt %u ms",
3574 (long long unsigned int)flow->val.pkt,
3575 (long long unsigned int)flow->val.oct,
3576 (long long unsigned int)flow->rval.pkt,
3577 (long long unsigned int)flow->rval.oct,
3578 flow->rdtime);
3579 } else {
3580 g_string_append_printf(rstr, " (%llu/%llu ->)",
3581 (long long unsigned int)flow->val.pkt,
3582 (long long unsigned int)flow->val.oct);
3583 }
3584
3585 /* end reason flags */
3586 if ((flow->reason & YAF_END_MASK) == YAF_END_IDLE)
3587 g_string_append(rstr," idle");
3588 if ((flow->reason & YAF_END_MASK) == YAF_END_ACTIVE)
3589 g_string_append(rstr," active");
3590 if ((flow->reason & YAF_END_MASK) == YAF_END_FORCED)
3591 g_string_append(rstr," eof");
3592 if ((flow->reason & YAF_END_MASK) == YAF_END_RESOURCE)
3593 g_string_append(rstr," rsrc");
3594 if ((flow->reason & YAF_END_MASK) == YAF_END_UDPFORCE)
3595 g_string_append(rstr, " force");
3596
3597 /* if app label is enabled, print the label */
3598 # ifdef YAF_ENABLE_APPLABEL
3599 if (0 != flow->appLabel) {
3600 g_string_append_printf(rstr, " applabel: %u", flow->appLabel);
3601 }
3602 # endif
3603 # ifdef YAF_ENABLE_NDPI
3604 if (0 != flow->ndpi_master) {
3605 if (flow->ndpi_sub) {
3606 g_string_append_printf(rstr, " ndpi: %u[%u]", flow->ndpi_master, flow->ndpi_sub);
3607 } else {
3608 g_string_append_printf(rstr, " ndpi: %u", flow->ndpi_master);
3609 }
3610 }
3611 # endif
3612
3613 /* if entropy is enabled, print the entropy values */
3614 # ifdef YAF_ENABLE_ENTROPY
3615 if (0 != flow->val.entropy || 0 != flow->rval.entropy) {
3616 g_string_append_printf(rstr, " entropy: %u rev entropy: %u",
3617 flow->val.entropy, flow->rval.entropy);
3618 }
3619 # endif
3620
3621 /* finish line */
3622 g_string_append(rstr,"\n");
3623
3624 /* print payload if necessary */
3625 # if YAF_ENABLE_PAYLOAD
3626 if (flow->val.payload) {
3627 air_hexdump_g_string_append(rstr, " -> ",
3628 flow->val.payload, flow->val.paylen);
3629 g_free(flow->val.payload);
3630 flow->val.payload = NULL;
3631 flow->val.paylen = 0;
3632 }
3633 if (flow->rval.payload) {
3634 air_hexdump_g_string_append(rstr, " <- ",
3635 flow->rval.payload, flow->rval.paylen);
3636 g_free(flow->rval.payload);
3637 flow->rval.payload = NULL;
3638 flow->rval.paylen = 0;
3639
3640 }
3641 # endif
3642 }
3643
3644 /**
3645 *yfPrintDelimitedString
3646 *
3647 *
3648 *
3649 */
yfPrintDelimitedString(GString * rstr,yfFlow_t * flow,gboolean yaft_mac)3650 void yfPrintDelimitedString(
3651 GString *rstr,
3652 yfFlow_t *flow,
3653 gboolean yaft_mac)
3654 {
3655 char sabuf[AIR_IP6ADDR_BUF_MINSZ],
3656 dabuf[AIR_IP6ADDR_BUF_MINSZ];
3657 GString *fstr = NULL;
3658 int loop = 0;
3659 unsigned short rvlan = 0;
3660
3661 /* print time and duration */
3662 air_mstime_g_string_append(rstr, flow->stime, AIR_TIME_ISO8601);
3663 g_string_append_printf(rstr, "%s", YF_PRINT_DELIM);
3664 air_mstime_g_string_append(rstr, flow->etime, AIR_TIME_ISO8601);
3665 g_string_append_printf(rstr, "%s%8.3f%s",
3666 YF_PRINT_DELIM, (flow->etime - flow->stime) / 1000.0, YF_PRINT_DELIM);
3667
3668 /* print initial RTT */
3669 g_string_append_printf(rstr, "%8.3f%s",
3670 flow->rdtime / 1000.0, YF_PRINT_DELIM);
3671
3672 /* print five tuple */
3673 if (flow->key.version == 4) {
3674 air_ipaddr_buf_print(sabuf, flow->key.addr.v4.sip);
3675 air_ipaddr_buf_print(dabuf, flow->key.addr.v4.dip);
3676 } else if (flow->key.version == 6) {
3677 air_ip6addr_buf_print(sabuf, flow->key.addr.v6.sip);
3678 air_ip6addr_buf_print(dabuf, flow->key.addr.v6.dip);
3679 } else {
3680 sabuf[0] = (char)0;
3681 dabuf[0] = (char)0;
3682
3683 }
3684 g_string_append_printf(rstr, "%3u%s%40s%s%5u%s%40s%s%5u%s",
3685 flow->key.proto, YF_PRINT_DELIM,
3686 sabuf, YF_PRINT_DELIM, flow->key.sp, YF_PRINT_DELIM,
3687 dabuf, YF_PRINT_DELIM, flow->key.dp, YF_PRINT_DELIM);
3688
3689 if (yaft_mac) {
3690 for (loop = 0; loop < 6; loop++) {
3691 g_string_append_printf(rstr, "%02x", flow->sourceMacAddr[loop]);
3692 if (loop < 5) {
3693 g_string_append_printf(rstr, ":");
3694 }
3695 /* clear out mac addr for next flow */
3696 flow->sourceMacAddr[loop] = 0;
3697 }
3698 g_string_append_printf(rstr, "%s", YF_PRINT_DELIM);
3699 for(loop =0; loop< 6; loop++) {
3700 g_string_append_printf(rstr, "%02x", flow->destinationMacAddr[loop]);
3701 if (loop < 5) {
3702 g_string_append_printf(rstr, ":");
3703 }
3704 /* clear out mac addr for next flow */
3705 flow->destinationMacAddr[loop] = 0;
3706 }
3707 g_string_append_printf(rstr, "%s", YF_PRINT_DELIM);
3708 }
3709
3710 /* print tcp flags */
3711 fstr = g_string_new("");
3712 yfPrintFlags(fstr, flow->val.iflags);
3713 g_string_append_printf(rstr, "%8s%s", fstr->str, YF_PRINT_DELIM);
3714 g_string_truncate(fstr, 0);
3715 yfPrintFlags(fstr, flow->val.uflags);
3716 g_string_append_printf(rstr, "%8s%s", fstr->str, YF_PRINT_DELIM);
3717 g_string_truncate(fstr, 0);
3718 yfPrintFlags(fstr, flow->rval.iflags);
3719 g_string_append_printf(rstr, "%8s%s", fstr->str, YF_PRINT_DELIM);
3720 g_string_truncate(fstr, 0);
3721 yfPrintFlags(fstr, flow->rval.uflags);
3722 g_string_append_printf(rstr, "%8s%s", fstr->str, YF_PRINT_DELIM);
3723 g_string_free(fstr, TRUE);
3724
3725 /* print tcp sequence numbers */
3726 g_string_append_printf(rstr, "%08x%s%08x%s", flow->val.isn, YF_PRINT_DELIM,
3727 flow->rval.isn, YF_PRINT_DELIM);
3728
3729 /* print vlan tags */
3730 if (flow->rval.oct) {
3731 g_string_append_printf(rstr, "%03hx%s%03hx%s", flow->val.vlan,
3732 YF_PRINT_DELIM, flow->rval.vlan,
3733 YF_PRINT_DELIM);
3734 } else {
3735 g_string_append_printf(rstr, "%03hx%s%03hx%s", flow->key.vlanId,
3736 YF_PRINT_DELIM, rvlan, YF_PRINT_DELIM);
3737 }
3738
3739
3740 /* print flow counters */
3741 g_string_append_printf(rstr, "%8llu%s%8llu%s%8llu%s%8llu%s",
3742 (long long unsigned int)flow->val.pkt, YF_PRINT_DELIM,
3743 (long long unsigned int)flow->val.oct, YF_PRINT_DELIM,
3744 (long long unsigned int)flow->rval.pkt, YF_PRINT_DELIM,
3745 (long long unsigned int)flow->rval.oct, YF_PRINT_DELIM);
3746
3747 /* if app label is enabled, print the label */
3748 # ifdef YAF_ENABLE_APPLABEL
3749 g_string_append_printf(rstr, "%5u%s", flow->appLabel, YF_PRINT_DELIM);
3750 # endif
3751
3752 /* if entropy is enabled, print the entropy values */
3753 # ifdef YAF_ENABLE_ENTROPY
3754 g_string_append_printf(rstr, "%3u%s%3u%s",
3755 flow->val.entropy, YF_PRINT_DELIM,
3756 flow->rval.entropy, YF_PRINT_DELIM);
3757 # endif
3758
3759
3760 /* end reason flags */
3761 if ((flow->reason & YAF_END_MASK) == YAF_END_IDLE)
3762 g_string_append(rstr,"idle ");
3763 if ((flow->reason & YAF_END_MASK) == YAF_END_ACTIVE)
3764 g_string_append(rstr,"active ");
3765 if ((flow->reason & YAF_END_MASK) == YAF_END_FORCED)
3766 g_string_append(rstr,"eof ");
3767 if ((flow->reason & YAF_END_MASK) == YAF_END_RESOURCE)
3768 g_string_append(rstr,"rsrc ");
3769 if ((flow->reason & YAF_END_MASK) == YAF_END_UDPFORCE)
3770 g_string_append(rstr, "force ");
3771
3772
3773 /* finish line */
3774 g_string_append(rstr,"\n");
3775
3776 /* not printing payload - but need to free */
3777 # if YAF_ENABLE_PAYLOAD
3778 if (flow->val.payload) {
3779 g_free(flow->val.payload);
3780 flow->val.payload = NULL;
3781 flow->val.paylen = 0;
3782 }
3783 if (flow->rval.payload) {
3784 g_free(flow->rval.payload);
3785 flow->rval.payload = NULL;
3786 flow->rval.paylen = 0;
3787 }
3788 # endif
3789
3790 }
3791
3792 /**
3793 *yfPrint
3794 *
3795 *
3796 *
3797 */
yfPrint(FILE * out,yfFlow_t * flow,GError ** err)3798 gboolean yfPrint(
3799 FILE *out,
3800 yfFlow_t *flow,
3801 GError **err)
3802 {
3803 GString *rstr = NULL;
3804 int rc = 0;
3805
3806 rstr = g_string_new("");
3807
3808 yfPrintString(rstr, flow);
3809
3810 rc = fwrite(rstr->str, rstr->len, 1, out);
3811
3812 if (rc != 1) {
3813 g_set_error(err, YAF_ERROR_DOMAIN, YAF_ERROR_IO,
3814 "error printing flow: %s", strerror(errno));
3815 }
3816
3817 g_string_free(rstr, TRUE);
3818
3819 return (rc == 1);
3820
3821 }
3822
3823 /**
3824 *yfPrintDelimited
3825 *
3826 *
3827 *
3828 */
yfPrintDelimited(FILE * out,yfFlow_t * flow,gboolean yaft_mac,GError ** err)3829 gboolean yfPrintDelimited(
3830 FILE *out,
3831 yfFlow_t *flow,
3832 gboolean yaft_mac,
3833 GError **err)
3834 {
3835 GString *rstr = NULL;
3836 int rc = 0;
3837
3838 rstr = g_string_new("");
3839
3840 yfPrintDelimitedString(rstr, flow, yaft_mac);
3841
3842 rc = fwrite(rstr->str, rstr->len, 1, out);
3843
3844 if (rc != 1) {
3845 g_set_error(err, YAF_ERROR_DOMAIN, YAF_ERROR_IO,
3846 "error printing delimited flow: %s", strerror(errno));
3847 }
3848
3849 g_string_free(rstr, TRUE);
3850
3851 return (rc == 1);
3852
3853 }
3854
3855 /**
3856 * yfPrintColumnHeaders
3857 *
3858 *
3859 */
yfPrintColumnHeaders(FILE * out,gboolean yaft_mac,GError ** err)3860 void yfPrintColumnHeaders(
3861 FILE *out,
3862 gboolean yaft_mac,
3863 GError **err)
3864 {
3865
3866 GString *rstr = NULL;
3867
3868 rstr = g_string_new("");
3869
3870 g_string_append_printf(rstr, "start-time%14s", YF_PRINT_DELIM);
3871 g_string_append_printf(rstr, "end-time%16s", YF_PRINT_DELIM);
3872 g_string_append_printf(rstr, "duration%s", YF_PRINT_DELIM);
3873 g_string_append_printf(rstr, "rtt%6s", YF_PRINT_DELIM);
3874 g_string_append_printf(rstr, "proto%s", YF_PRINT_DELIM);
3875 g_string_append_printf(rstr, "sip%36s", YF_PRINT_DELIM);
3876 g_string_append_printf(rstr, "sp%4s", YF_PRINT_DELIM);
3877 g_string_append_printf(rstr, "dip%38s", YF_PRINT_DELIM);
3878 g_string_append_printf(rstr, "dp%4s", YF_PRINT_DELIM);
3879 if (yaft_mac) {
3880 g_string_append_printf(rstr, "srcMacAddress%5s", YF_PRINT_DELIM);
3881 g_string_append_printf(rstr, "destMacAddress%4s", YF_PRINT_DELIM);
3882 }
3883 g_string_append_printf(rstr, "iflags%3s", YF_PRINT_DELIM);
3884 g_string_append_printf(rstr, "uflags%3s", YF_PRINT_DELIM);
3885 g_string_append_printf(rstr, "riflags%2s", YF_PRINT_DELIM);
3886 g_string_append_printf(rstr, "ruflags%2s", YF_PRINT_DELIM);
3887 g_string_append_printf(rstr, "isn%6s", YF_PRINT_DELIM);
3888 g_string_append_printf(rstr, "risn%5s", YF_PRINT_DELIM);
3889 g_string_append_printf(rstr, "tag%s", YF_PRINT_DELIM);
3890 g_string_append_printf(rstr, "rtag%s", YF_PRINT_DELIM);
3891 g_string_append_printf(rstr, "pkt%5s", YF_PRINT_DELIM);
3892 g_string_append_printf(rstr, "oct%6s", YF_PRINT_DELIM);
3893 g_string_append_printf(rstr, "rpkt%5s", YF_PRINT_DELIM);
3894 g_string_append_printf(rstr, "roct%5s", YF_PRINT_DELIM);
3895
3896 #if YAF_ENABLE_APPLABEL
3897 g_string_append_printf(rstr, "app%3s", YF_PRINT_DELIM);
3898 #endif
3899 #if YAF_ENABLE_ENTROPY
3900 g_string_append_printf(rstr, "entropy%s", YF_PRINT_DELIM);
3901 g_string_append_printf(rstr, "rentropy%s", YF_PRINT_DELIM);
3902 #endif
3903
3904 g_string_append_printf(rstr, "end-reason");
3905 g_string_append(rstr,"\n");
3906
3907 fwrite(rstr->str, rstr->len, 1, out);
3908
3909 g_string_free(rstr, TRUE);
3910
3911 }
3912