1 /*
2 ** Copyright (C) 2005-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8
9 /*
10 ** Support file for probeconf.c
11 **
12 */
13
14 #include <silk/silk.h>
15
16 RCSIDENT("$SiLK: packlogic-generic.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
17
18 #include <silk/rwflowpack.h>
19 #include <silk/rwrec.h>
20 #include <silk/silk_files.h>
21 #include <silk/sksite.h>
22 #include <silk/skvector.h>
23 #include <silk/utils.h>
24
25
26 /* TYPEDEFS AND MACROS */
27
28 /*
29 * Define integers to stand-in for each of the possible flowtypes
30 * that are defined in the silk.conf file. These must match.
31 */
32 #define RW_IN 0
33 #define RW_OUT 1
34 #define RW_IN_WEB 2
35 #define RW_OUT_WEB 3
36 #define RW_IN_NULL 4
37 #define RW_OUT_NULL 5
38
39
40 /*
41 * These are the IDs of the networks that should be defined in the
42 * sensor.conf file. We are in trouble if someone redefines these
43 * values.
44 */
45 #define NUM_NETWORKS 3
46
47 #define NETWORK_NULL ((skpc_network_id_t)0)
48 /* The SNMP interface on the probe to which non-routed traffic is
49 * sent. This is 0 on Cisco routers. */
50
51 #define NETWORK_EXTERNAL ((skpc_network_id_t)1)
52 /* A bitmap where an ON bit represents an SNMP interface on the
53 * probe that faces the external world. Traffic entering the
54 * router on this interface will be considered incoming. */
55
56 #define NETWORK_INTERNAL ((skpc_network_id_t)2)
57 /* A bitmap where an ON bit represents an SNMP interface on the
58 * probe that faces the internal world. Traffic entering the
59 * router on this interface will be considered outgoing. */
60
61
62 /* LOCAL VARIABLES */
63
64 /* the names that correspond to each network */
65 static const char *net_names[NUM_NETWORKS] = {
66 "null",
67 "external",
68 "internal"
69 };
70
71 /*
72 * Define the file formats used to pack each flowtype. If these do
73 * not line up with the type IDs defined in the config file, there
74 * will be problems. Use the more compact formats for flows from
75 * NetFlow v5 based sources, and the expanded formats for flows
76 * from other sources.
77 */
78 static struct filetypeFormats_st {
79 sk_file_format_t netflow_v5;
80 sk_file_format_t other;
81 } filetypeFormats[] = {
82 /* in */ {FT_RWSPLIT, FT_RWAUGMENTED},
83 /* out */ {FT_RWSPLIT, FT_RWAUGMENTED},
84 /* inweb */ {FT_RWWWW, FT_RWAUGWEB},
85 /* outweb */ {FT_RWWWW, FT_RWAUGWEB},
86 /* innull */ {FT_RWSPLIT, FT_RWAUGMENTED},
87 /* outnull */ {FT_RWSPLIT, FT_RWAUGMENTED}
88 };
89
90
91 static const char plugin_source[] = __FILE__;
92 static const char *plugin_path = plugin_source;
93
94
95 /* LOCAL FUNCTION PROTOTYPES */
96
97 static int packLogicSetup(void);
98 static void packLogicTeardown(void);
99 static int packLogicVerifySensor(skpc_sensor_t *sensor);
100 static int
101 packLogicDetermineFlowtype(
102 const skpc_probe_t *probe,
103 const rwRec *rwrec,
104 sk_flowtype_id_t *ftypes,
105 sk_sensor_id_t *sensorids);
106 static sk_file_format_t
107 packLogicDetermineFileFormat(
108 const skpc_probe_t *probe,
109 sk_flowtype_id_t ftype);
110
111
112 /* FUNCTION DEFINITIONS */
113
114 /*
115 * Fill in 'packlogic' with pointers to the functions defined in
116 * this file.
117 */
118 int
packLogicInitialize(packlogic_plugin_t * packlogic)119 packLogicInitialize(
120 packlogic_plugin_t *packlogic)
121 {
122 assert(packlogic);
123
124 if (packlogic->path) {
125 plugin_path = packlogic->path;
126 }
127
128 packlogic->setup_fn = &packLogicSetup;
129 packlogic->teardown_fn = &packLogicTeardown;
130 packlogic->verify_sensor_fn = &packLogicVerifySensor;
131 packlogic->determine_flowtype_fn = &packLogicDetermineFlowtype;
132 packlogic->determine_fileformat_fn = &packLogicDetermineFileFormat;
133 return 0;
134 }
135
136
137 /*
138 * Verify contents of silk.conf file matches the values we set here
139 * and set any globals we require.
140 *
141 * Invoked from rwflowpack by packlogic->setup_fn
142 */
143 static int
packLogicSetup(void)144 packLogicSetup(
145 void)
146 {
147 const size_t count = (sizeof(filetypeFormats)/sizeof(filetypeFormats[0]));
148 uint32_t i;
149
150 #define FT_ASSERT(flowtype_id, flowtype_name) \
151 sksiteFlowtypeAssert(plugin_path, (flowtype_id), "all", (flowtype_name))
152
153 /* Make sure flowtype definitions match config file */
154 FT_ASSERT(RW_IN, "in");
155 FT_ASSERT(RW_OUT, "out");
156 FT_ASSERT(RW_IN_WEB, "inweb");
157 FT_ASSERT(RW_OUT_WEB, "outweb");
158 FT_ASSERT(RW_IN_NULL, "innull");
159 FT_ASSERT(RW_OUT_NULL, "outnull");
160
161 /* Confirm that number of flowtypes is not greater than the size
162 * of the filetypeFormats[] array; abort if it is. Complain if
163 * the array is too large, but continue processing. */
164 if (count <= sksiteFlowtypeGetMaxID()) {
165 skAppPrintErr(("File formats not specified for some flowtypes.\n"
166 "\tModify filetypeFormats[] in %s,\n"
167 "\trecompile and try running again."),
168 plugin_path);
169 skAbort();
170 } else if (count != (1u + sksiteFlowtypeGetMaxID())) {
171 skAppPrintErr(("Warning: Number of flowtypes does not equal number\n"
172 "\tof file formats in filetypeFormats[] in %s"),
173 plugin_path);
174 }
175
176 /* Define all of our networks */
177 for (i = 0; i < NUM_NETWORKS; ++i) {
178 if (skpcNetworkAdd(i, net_names[i])) {
179 skAppPrintErr("Unable to add network %" PRIu32 "->%s",
180 i, net_names[i]);
181 return -1;
182 }
183 }
184
185 return 0;
186 }
187
188
189 /*
190 * Clean up any memory we allocated.
191 *
192 * Invoked from rwflowpack by packlogic->teardown_fn
193 */
194 static void
packLogicTeardown(void)195 packLogicTeardown(
196 void)
197 {
198 return;
199 }
200
201
202 /*
203 * Verify sensor by its class. Verify that the sensor supports the
204 * type(s) of its probe(s). Verify that enough information is
205 * present on the sensor to categorize a flow record.
206 *
207 * Invoked from rwflowpack by packlogic->verify_sensor_fn
208 */
209 static int
packLogicVerifySensor(skpc_sensor_t * sensor)210 packLogicVerifySensor(
211 skpc_sensor_t *sensor)
212 {
213 skpc_probe_t *probe;
214 sk_vector_t *probe_vec;
215 uint32_t count;
216
217 /* There is a single class, so no per-class verification is
218 * necessary. Make certain we have either snmp interface values
219 * or ip-blocks depending on the type of probe(s) associated with
220 * this sensor. */
221
222 /* get the probes for the sensor */
223 probe_vec = skVectorNew(sizeof(skpc_probe_t*));
224 if (probe_vec == NULL) {
225 return -1;
226 }
227 count = skpcSensorGetProbes(sensor, probe_vec);
228
229 /* this packing logic only supports a single probe per sensor */
230 if (count != 1) {
231 skAppPrintErr(("Cannot verify sensor '%s':\n"
232 "\tOnly one probe per sensor is supported"
233 " by the packing-logic\n\tfile '%s'"),
234 sensor->sensor_name,
235 plugin_path);
236 skVectorDestroy(probe_vec);
237 return -1;
238 }
239 skVectorGetValue(&probe, probe_vec, 0);
240 skVectorDestroy(probe_vec);
241
242 /* make certain the probe's type is valid */
243 switch (probe->probe_type) {
244 case PROBE_ENUM_NETFLOW_V5:
245 case PROBE_ENUM_NETFLOW_V9:
246 case PROBE_ENUM_IPFIX:
247 /* expected probe types */
248 break;
249
250 default:
251 assert(skpcProbetypeEnumtoName(probe->probe_type));
252 skAppPrintErr(("Cannot verify sensor '%s':\n"
253 "\tThe probe type '%s' is not supported in the"
254 " packing-logic\n\tfile '%s'"),
255 sensor->sensor_name,
256 skpcProbetypeEnumtoName(probe->probe_type),
257 plugin_path);
258 return -1;
259 }
260
261
262 /* Verify that we have enough information to determine the
263 * flowtype for every flow. These are the rules:
264 *
265 * 1. One of external-interface, external-ipblock, or
266 * external-ipset must be specified.
267 *
268 * 2. You cannot mix interfaces, ipblocks, and ipsets, with the
269 * excption that a null-interface which is always allowed.
270 *
271 * 3. Only one network may claim the remainder.
272 *
273 * 4. Using remainder for an ipblock or ipset requires that
274 * another interface has set an IPblock or an IPset.
275 */
276 switch (sensor->decider[NETWORK_EXTERNAL].nd_type) {
277 case SKPC_UNSET:
278 /* It is an error when neither SNMP interfaces nor IP-blocks
279 * were specified for the external network. */
280 skAppPrintErr(("Cannot verify sensor '%s':\n"
281 "\tMust specify %s-interface, %s-ipblock, or %s-ipset"),
282 sensor->sensor_name,
283 net_names[NETWORK_EXTERNAL],
284 net_names[NETWORK_EXTERNAL],
285 net_names[NETWORK_EXTERNAL]);
286 return -1;
287
288 case SKPC_NEG_IPBLOCK:
289 skAppPrintErr("Negated IPblock logic not implemented");
290 exit(EXIT_FAILURE);
291 case SKPC_NEG_IPSET:
292 skAppPrintErr("Negated IPset logic not implemented");
293 exit(EXIT_FAILURE);
294
295 case SKPC_IPBLOCK:
296 /* Fine as long as INTERNAL is either empty or also contains
297 * IPblocks */
298 switch (sensor->decider[NETWORK_INTERNAL].nd_type) {
299 case SKPC_UNSET:
300 case SKPC_IPBLOCK:
301 case SKPC_REMAIN_IPBLOCK:
302 /* These are fine */
303 break;
304
305 case SKPC_NEG_IPBLOCK:
306 skAppPrintErr("Negated IPblock logic not implemented");
307 exit(EXIT_FAILURE);
308 case SKPC_NEG_IPSET:
309 skAppPrintErr("Negated IPset logic not implemented");
310 exit(EXIT_FAILURE);
311
312 case SKPC_INTERFACE:
313 case SKPC_REMAIN_INTERFACE:
314 /* Bad mix */
315 skAppPrintErr(("Cannot verify sensor '%s':\n"
316 "\tCannot mix %s-ipblock and %s-interface"),
317 sensor->sensor_name,
318 net_names[NETWORK_EXTERNAL],
319 net_names[NETWORK_INTERNAL]);
320 return -1;
321
322 case SKPC_IPSET:
323 case SKPC_REMAIN_IPSET:
324 /* Bad mix */
325 skAppPrintErr(("Cannot verify sensor '%s':\n"
326 "\tCannot mix %s-ipblock and %s-ipset"),
327 sensor->sensor_name,
328 net_names[NETWORK_EXTERNAL],
329 net_names[NETWORK_INTERNAL]);
330 return -1;
331 }
332 break;
333
334 case SKPC_REMAIN_IPBLOCK:
335 switch (sensor->decider[NETWORK_INTERNAL].nd_type) {
336 case SKPC_UNSET:
337 /* Accept for now, though this will be an error if
338 * NETWORK_NULL does not define an IPblock */
339 break;
340
341 case SKPC_NEG_IPBLOCK:
342 skAppPrintErr("Negated IPblock logic not implemented");
343 exit(EXIT_FAILURE);
344 case SKPC_NEG_IPSET:
345 skAppPrintErr("Negated IPset logic not implemented");
346 exit(EXIT_FAILURE);
347
348 case SKPC_REMAIN_IPBLOCK:
349 /* Cannot have multiple things requesting "remainder" */
350 skAppPrintErr(("Cannot verify sensor '%s':\n"
351 "\tOnly one network value may use 'remainder'"),
352 sensor->sensor_name);
353 return -1;
354
355 case SKPC_IPBLOCK:
356 /* This is fine */
357 break;
358
359 case SKPC_INTERFACE:
360 case SKPC_REMAIN_INTERFACE:
361 /* Bad mix */
362 skAppPrintErr(("Cannot verify sensor '%s':\n"
363 "\tCannot mix %s-ipblock and %s-interface"),
364 sensor->sensor_name,
365 net_names[NETWORK_EXTERNAL],
366 net_names[NETWORK_INTERNAL]);
367 return -1;
368
369 case SKPC_IPSET:
370 case SKPC_REMAIN_IPSET:
371 /* Bad mix */
372 skAppPrintErr(("Cannot verify sensor '%s':\n"
373 "\tCannot mix %s-ipblock and %s-ipset"),
374 sensor->sensor_name,
375 net_names[NETWORK_EXTERNAL],
376 net_names[NETWORK_INTERNAL]);
377 return -1;
378 }
379 break;
380
381 case SKPC_INTERFACE:
382 case SKPC_REMAIN_INTERFACE:
383 /* Fine as long as INTERNAL and NULL are either empty or also
384 * contain interfaces */
385 switch (sensor->decider[NETWORK_INTERNAL].nd_type) {
386 case SKPC_UNSET:
387 case SKPC_INTERFACE:
388 case SKPC_REMAIN_INTERFACE:
389 switch (sensor->decider[NETWORK_NULL].nd_type) {
390 case SKPC_IPBLOCK:
391 case SKPC_NEG_IPBLOCK:
392 case SKPC_REMAIN_IPBLOCK:
393 /* Bad mix */
394 skAppPrintErr(("Cannot verify sensor '%s':\n"
395 "\tCannot mix %s-interface and %s-ipblock"),
396 sensor->sensor_name,
397 net_names[NETWORK_EXTERNAL],
398 net_names[NETWORK_NULL]);
399 return -1;
400 case SKPC_IPSET:
401 case SKPC_NEG_IPSET:
402 case SKPC_REMAIN_IPSET:
403 /* Bad mix */
404 skAppPrintErr(("Cannot verify sensor '%s':\n"
405 "\tCannot mix %s-interface and %s-ipset"),
406 sensor->sensor_name,
407 net_names[NETWORK_EXTERNAL],
408 net_names[NETWORK_NULL]);
409 return -1;
410 default:
411 break;
412 }
413 break;
414
415 case SKPC_IPBLOCK:
416 case SKPC_NEG_IPBLOCK:
417 case SKPC_REMAIN_IPBLOCK:
418 /* Bad mix */
419 skAppPrintErr(("Cannot verify sensor '%s':\n"
420 "\tCannot mix %s-interface and %s-ipblock"),
421 sensor->sensor_name,
422 net_names[NETWORK_EXTERNAL],
423 net_names[NETWORK_INTERNAL]);
424 return -1;
425
426 case SKPC_IPSET:
427 case SKPC_NEG_IPSET:
428 case SKPC_REMAIN_IPSET:
429 /* Bad mix */
430 skAppPrintErr(("Cannot verify sensor '%s':\n"
431 "\tCannot mix %s-interface and %s-ipset"),
432 sensor->sensor_name,
433 net_names[NETWORK_EXTERNAL],
434 net_names[NETWORK_INTERNAL]);
435 return -1;
436 }
437 break;
438
439 case SKPC_IPSET:
440 /* Fine as long as INTERNAL is either empty or also contains
441 * IPsets */
442 switch (sensor->decider[NETWORK_INTERNAL].nd_type) {
443 case SKPC_UNSET:
444 case SKPC_IPSET:
445 case SKPC_REMAIN_IPSET:
446 /* These are fine */
447 break;
448
449 case SKPC_NEG_IPSET:
450 skAppPrintErr("Negated IPset logic not implemented");
451 exit(EXIT_FAILURE);
452 case SKPC_NEG_IPBLOCK:
453 skAppPrintErr("Negated IPblock logic not implemented");
454 exit(EXIT_FAILURE);
455
456 case SKPC_INTERFACE:
457 case SKPC_REMAIN_INTERFACE:
458 /* Bad mix */
459 skAppPrintErr(("Cannot verify sensor '%s':\n"
460 "\tCannot mix %s-ipset and %s-interface"),
461 sensor->sensor_name,
462 net_names[NETWORK_EXTERNAL],
463 net_names[NETWORK_INTERNAL]);
464 return -1;
465
466 case SKPC_IPBLOCK:
467 case SKPC_REMAIN_IPBLOCK:
468 /* Bad mix */
469 skAppPrintErr(("Cannot verify sensor '%s':\n"
470 "\tCannot mix %s-ipset and %s-ipblock"),
471 sensor->sensor_name,
472 net_names[NETWORK_EXTERNAL],
473 net_names[NETWORK_INTERNAL]);
474 return -1;
475 }
476 break;
477
478 case SKPC_REMAIN_IPSET:
479 switch (sensor->decider[NETWORK_INTERNAL].nd_type) {
480 case SKPC_UNSET:
481 /* Accept for now, though this will be an error if
482 * NETWORK_NULL does not define an IPset */
483 break;
484
485 case SKPC_NEG_IPSET:
486 skAppPrintErr("Negated IPset logic not implemented");
487 exit(EXIT_FAILURE);
488 case SKPC_NEG_IPBLOCK:
489 skAppPrintErr("Negated IPblock logic not implemented");
490 exit(EXIT_FAILURE);
491
492 case SKPC_REMAIN_IPSET:
493 /* Cannot have multiple things requesting "remainder" */
494 skAppPrintErr(("Cannot verify sensor '%s':\n"
495 "\tOnly one network value may use 'remainder'"),
496 sensor->sensor_name);
497 return -1;
498
499 case SKPC_IPSET:
500 /* This is fine */
501 break;
502
503 case SKPC_INTERFACE:
504 case SKPC_REMAIN_INTERFACE:
505 /* Bad mix */
506 skAppPrintErr(("Cannot verify sensor '%s':\n"
507 "\tCannot mix %s-ipset and %s-interface"),
508 sensor->sensor_name,
509 net_names[NETWORK_EXTERNAL],
510 net_names[NETWORK_INTERNAL]);
511 return -1;
512
513 case SKPC_IPBLOCK:
514 case SKPC_REMAIN_IPBLOCK:
515 /* Bad mix */
516 skAppPrintErr(("Cannot verify sensor '%s':\n"
517 "\tCannot mix %s-ipset and %s-ipblock"),
518 sensor->sensor_name,
519 net_names[NETWORK_EXTERNAL],
520 net_names[NETWORK_INTERNAL]);
521 return -1;
522 }
523 break;
524 }
525
526 return 0;
527 }
528
529
530 /*
531 * count = packLogicDetermineFlowtype(probe, &rwrec, ftypes[], sensorids[]);
532 *
533 * Fill the 'ftypes' and 'sensorids' arrays with the list of
534 * flow_types and sensors to which the 'rwrec' probe, collected
535 * from the 'probe' sensor, should be packed. Return the number of
536 * elements added to each array or -1 on error.
537 *
538 * Invoked from rwflowpack by packlogic->determine_flowtype_fn
539 */
540 static int
packLogicDetermineFlowtype(const skpc_probe_t * probe,const rwRec * rwrec,sk_flowtype_id_t * ftypes,sk_sensor_id_t * sensorids)541 packLogicDetermineFlowtype(
542 const skpc_probe_t *probe,
543 const rwRec *rwrec,
544 sk_flowtype_id_t *ftypes,
545 sk_sensor_id_t *sensorids)
546 {
547 skpc_sensor_t *sensor;
548 uint16_t memo;
549
550 /* index into output arrays and count to be returned */
551 size_t sensor_count;
552
553 assert(ftypes);
554 assert(sensorids);
555
556 memo = rwRecGetMemo(rwrec);
557
558 /* loop over all sensors that use the 'probe' */
559 for (sensor_count = 0; sensor_count < probe->sensor_count; ++sensor_count) {
560 sensor = probe->sensor_list[sensor_count];
561 sensorids[sensor_count] = sensor->sensor_id;
562
563 if (1 == skpcSensorTestFlowInterfaces(sensor, rwrec,
564 NETWORK_EXTERNAL, SKPC_DIR_SRC))
565 {
566 /* Flow came from the outside */
567
568 if (1 == skpcSensorTestFlowInterfaces(sensor, rwrec,
569 NETWORK_NULL, SKPC_DIR_DST))
570 {
571 /* Flow went to the null destination */
572 ftypes[sensor_count] = RW_IN_NULL;
573 } else {
574 /* Assume flow went to the inside: incoming */
575 if (rwRecIsWeb(rwrec)) {
576 ftypes[sensor_count] = RW_IN_WEB;
577 } else {
578 ftypes[sensor_count] = RW_IN;
579 }
580 }
581 } else {
582 /* Flow came from the inside */
583
584 if (1 == skpcSensorTestFlowInterfaces(sensor, rwrec,
585 NETWORK_NULL, SKPC_DIR_DST))
586 {
587 /* Flow went to the null destination */
588 ftypes[sensor_count] = RW_OUT_NULL;
589 } else {
590
591 /* Assume flow went to the outside: outgoing */
592 if (rwRecIsWeb(rwrec)) {
593 ftypes[sensor_count] = RW_OUT_WEB;
594 } else {
595 ftypes[sensor_count] = RW_OUT;
596 }
597 }
598 }
599
600 if (skpcProbeGetQuirks(probe) & SKPC_QUIRK_FW_EVENT) {
601 /* Check whether libskipfix stored a "flow denied"
602 * firewallEvent, NF_F_FW_EVENT, or NF_F_FW_EXT_EVENT. If so,
603 * make certain flowtype is NULL */
604 switch (memo) {
605 case 0:
606 break;
607 case SKIPFIX_FW_EVENT_DENIED_INGRESS:
608 ftypes[sensor_count] = RW_IN_NULL;
609 break;
610 case SKIPFIX_FW_EVENT_DENIED_EGRESS:
611 ftypes[sensor_count] = RW_OUT_NULL;
612 break;
613 case SKIPFIX_FW_EVENT_DENIED:
614 case SKIPFIX_FW_EVENT_DENIED_SERV_PORT:
615 case SKIPFIX_FW_EVENT_DENIED_NOT_SYN:
616 switch (ftypes[sensor_count]) {
617 case RW_IN_NULL:
618 case RW_OUT_NULL:
619 /* type is already null */
620 break;
621 case RW_IN:
622 case RW_IN_WEB:
623 /* arrived from the outside */
624 ftypes[sensor_count] = RW_IN_NULL;
625 break;
626 case RW_OUT:
627 case RW_OUT_WEB:
628 /* arrived from the inside */
629 ftypes[sensor_count] = RW_OUT_NULL;
630 break;
631 default:
632 skAbortBadCase(ftypes[sensor_count]);
633 }
634 break;
635 }
636 }
637 }
638
639 return probe->sensor_count;
640 }
641
642
643 /*
644 * Determine the file output format to use.
645 *
646 * Invoked from rwflowpack by packlogic->determine_fileformat_fn
647 */
648 #if SK_ENABLE_IPV6
649
650 static sk_file_format_t
packLogicDetermineFileFormat(const skpc_probe_t UNUSED (* probe),sk_flowtype_id_t UNUSED (ftype))651 packLogicDetermineFileFormat(
652 const skpc_probe_t UNUSED(*probe),
653 sk_flowtype_id_t UNUSED(ftype))
654 {
655 return FT_RWIPV6;
656 }
657
658 #else
659
660 static sk_file_format_t
packLogicDetermineFileFormat(const skpc_probe_t * probe,sk_flowtype_id_t ftype)661 packLogicDetermineFileFormat(
662 const skpc_probe_t *probe,
663 sk_flowtype_id_t ftype)
664 {
665 assert(ftype < (sizeof(filetypeFormats)/sizeof(filetypeFormats[0])));
666
667 if (skpcProbeGetQuirks(probe) & SKPC_QUIRK_ZERO_PACKETS) {
668 /* Use a format that does not use bytes/packet ratio */
669 return FT_RWGENERIC;
670 }
671
672 switch (probe->probe_type) {
673 case PROBE_ENUM_NETFLOW_V5:
674 return filetypeFormats[ftype].netflow_v5;
675
676 default:
677 return filetypeFormats[ftype].other;
678 }
679 }
680
681 #endif /* #else of #if SK_ENABLE_IPV6 */
682
683
684 /*
685 ** Local Variables:
686 ** mode:c
687 ** indent-tabs-mode:nil
688 ** c-basic-offset:4
689 ** End:
690 */
691