1 /*
2 ** Copyright (C) 2004-2020 by Carnegie Mellon University.
3 **
4 ** @OPENSOURCE_LICENSE_START@
5 ** See license information in ../../LICENSE.txt
6 ** @OPENSOURCE_LICENSE_END@
7 */
8
9 #include <silk/silk.h>
10
11 RCSIDENT("$SiLK: flowcapio.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
12
13 #include "skstream_priv.h"
14
15 /*
16 ** Converts FLOWCAP records to RWGENERIC records
17 **
18 */
19
20
21 /* Version to use when SK_RECORD_VERSION_ANY is specified */
22 #define DEFAULT_RECORD_VERSION 5
23
24
25 /* LOCAL FUNCTION PROTOTYPES */
26
27 static int
28 flowcapioRecordUnpack_V5(
29 skstream_t *stream,
30 rwGenericRec_V5 *rwrec,
31 uint8_t *ar);
32 static int
33 flowcapioRecordUnpack_V3(
34 skstream_t *stream,
35 rwGenericRec_V5 *rwrec,
36 uint8_t *ar);
37 static int
38 flowcapioRecordPack_V3(
39 skstream_t *stream,
40 const rwGenericRec_V5 *rwrec,
41 uint8_t *ar);
42
43
44
45 /* ********************************************************************* */
46
47 /*
48 ** FLOWCAP VERSION 6
49 **
50 ** Flowcap version 6 is identical to V5, expect must clear the
51 ** application field when unpacking. Packing functions for V5 and
52 ** V6 are identical.
53 */
54
55 static int
flowcapioRecordUnpack_V6(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)56 flowcapioRecordUnpack_V6(
57 skstream_t *stream,
58 rwGenericRec_V5 *rwrec,
59 uint8_t *ar)
60 {
61 int rv;
62
63 rv = flowcapioRecordUnpack_V5(stream, rwrec, ar);
64 rwRecSetApplication(rwrec, 0);
65 return rv;
66 }
67
68
69 /* ********************************************************************* */
70
71 /*
72 ** FLOWCAP VERSION 5
73 **
74 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
75 **
76 ** uint32_t sIP; // 0- 3 Source IP
77 ** uint32_t dIP; // 4- 7 Destination IP
78 **
79 ** uint32_t bytes; // 8-11 Byte count
80 **
81 ** uint32_t sTime; // 12-15 Start time as UNIX epoch secs
82 **
83 ** uint16_t elapsed; // 16-17 Duration of flow in seconds
84 ** uint16_t sPort; // 18-19 Source port
85 **
86 ** uint16_t dPort; // 20-21 Destination port
87 ** uint16_t service_port; // 22-23 Port reported by flow collector
88 **
89 ** uint16_t input; // 24-25 SNMP Input
90 ** uint16_t output; // 26-27 SNMP Output
91 **
92 ** uint8_t pkts[3] // 28-30 Count of packets
93 ** uint8_t proto // 31 Protocol
94 **
95 ** uint8_t flags // 32 EXPANDED==0: All TCP Flags
96 ** // EXPANDED==1: Flags !1st pkt
97 ** uint8_t first_flags; // 33 EXPANDED==0: 0
98 ** // EXPANDED==1: TCP Flags 1st pkt
99 ** uint8_t tcp_state; // 34 TCP state machine info
100 ** uint8_t time_frac[3]; // 35-37 sTime msec & elapsed msec
101 **
102 **
103 ** 38 bytes on disk.
104 */
105
106 #define RECLEN_FLOWCAP_V5 38
107
108
109 /*
110 * Byte swap the FLOWCAP v5 record 'ar' in place.
111 */
112 #define flowcapioRecordSwap_V5(ar) \
113 { \
114 uint8_t swap_tmp; \
115 \
116 SWAP_DATA32((ar) + 0); /* sIP */ \
117 SWAP_DATA32((ar) + 4); /* dIP */ \
118 SWAP_DATA32((ar) + 8); /* bytes */ \
119 SWAP_DATA32((ar) + 12); /* sTime */ \
120 SWAP_DATA16((ar) + 16); /* dur */ \
121 SWAP_DATA16((ar) + 18); /* sPort */ \
122 SWAP_DATA16((ar) + 20); /* dPort */ \
123 SWAP_DATA16((ar) + 22); /* service_port */ \
124 SWAP_DATA16((ar) + 24); /* input */ \
125 SWAP_DATA16((ar) + 26); /* output */ \
126 \
127 swap_tmp = ar[28]; /* packets */ \
128 ar[28] = ar[30]; \
129 ar[30] = swap_tmp; \
130 \
131 /* four bytes: proto(31), flags(32), first_flags(33) tcp_state(34) */ \
132 /* three bytes in hand-encoded time_frac[3] */ \
133 }
134
135
136 /*
137 * Unpack the array of bytes 'ar' into a record 'rwrec'
138 */
139 static int
flowcapioRecordUnpack_V5(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)140 flowcapioRecordUnpack_V5(
141 skstream_t *stream,
142 rwGenericRec_V5 *rwrec,
143 uint8_t *ar)
144 {
145 uint32_t tmp32 = 0;
146 uint16_t elapsed = 0;
147
148 /* swap if required */
149 if (stream->swapFlag) {
150 flowcapioRecordSwap_V5(ar);
151 }
152
153 /* sIP, dIP, bytes */
154 rwRecMemSetSIPv4(rwrec, &ar[0]);
155 rwRecMemSetDIPv4(rwrec, &ar[4]);
156 rwRecMemSetBytes(rwrec, &ar[8]);
157
158 /* sTime seconds, plus fractional seconds in bytes 35,36 */
159 memcpy(&tmp32, &ar[12], sizeof(tmp32));
160 rwRecSetStartTime(rwrec, sktimeCreate(tmp32,
161 ((ar[35] << 2)
162 |GET_MASKED_BITS(ar[36], 6, 2))));
163
164 /* elapsed seconds, plus fractional seconds in bytes 36,37 */
165 memcpy(&elapsed, &ar[16], sizeof(elapsed));
166 rwRecSetElapsed(rwrec, (((uint32_t)1000 * elapsed)
167 + ((GET_MASKED_BITS(ar[36], 0, 6) << 4)
168 | GET_MASKED_BITS(ar[37], 4, 4))));
169
170 /* sPort, dPort, application, input, output */
171 rwRecMemSetSPort(rwrec, &ar[18]);
172 rwRecMemSetDPort(rwrec, &ar[20]);
173 rwRecMemSetApplication(rwrec, &ar[22]);
174 rwRecMemSetInput(rwrec, &ar[24]);
175 rwRecMemSetOutput(rwrec, &ar[26]);
176
177 /* packets, protocol */
178 tmp32 = 0;
179 #if SK_LITTLE_ENDIAN
180 memcpy(&tmp32, &ar[28], 3);
181 #else
182 memcpy((((uint8_t*)&tmp32) + 1), &ar[28], 3);
183 #endif
184 rwRecSetPkts(rwrec, tmp32);
185 rwRecSetProto(rwrec, ar[31]);
186
187 /* Flags, Initial flags, TCP State */
188 rwRecSetTcpState(rwrec, ar[34]);
189 if (ar[34] & SK_TCPSTATE_EXPANDED) {
190 /* have separate initial and session flags */
191 rwRecSetFlags(rwrec, (ar[32] | ar[33]));
192 rwRecSetRestFlags(rwrec, ar[32]);
193 rwRecSetInitFlags(rwrec, ar[33]);
194 } else {
195 /* have a single flags field */
196 rwRecSetFlags(rwrec, ar[32]);
197 }
198
199 /* Fractional times in bytes 35-37 handled above */
200
201 /* Get sensor from header */
202 rwRecSetSensor(rwrec, stream->hdr_sensor);
203
204 return SKSTREAM_OK;
205 }
206
207
208 /*
209 * Pack the record 'rwrec' into an array of bytes 'ar'
210 */
211 static int
flowcapioRecordPack_V5(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)212 flowcapioRecordPack_V5(
213 skstream_t *stream,
214 const rwGenericRec_V5 *rwrec,
215 uint8_t *ar)
216 {
217 uint32_t tmp32;
218 uint16_t elapsed;
219
220 /* sIP, dIP, bytes, sTime */
221 rwRecMemGetSIPv4(rwrec, &ar[0]);
222 rwRecMemGetDIPv4(rwrec, &ar[4]);
223 rwRecMemGetBytes(rwrec, &ar[8]);
224 rwRecMemGetStartSeconds(rwrec, &ar[12]);
225
226 /* elapsed */
227 if (rwRecGetElapsedSeconds(rwrec) > UINT16_MAX) {
228 memset(&ar[16], 0xFF, sizeof(elapsed));
229 } else {
230 elapsed = (uint16_t)rwRecGetElapsedSeconds(rwrec);
231 memcpy(&ar[16], &elapsed, sizeof(elapsed));
232 }
233
234 /* sPort, dPort, application, input, output */
235 rwRecMemGetSPort(rwrec, &ar[18]);
236 rwRecMemGetDPort(rwrec, &ar[20]);
237 rwRecMemGetApplication(rwrec, &ar[22]);
238 rwRecMemGetInput(rwrec, &ar[24]);
239 rwRecMemGetOutput(rwrec, &ar[26]);
240
241 /* packets, protocol */
242 tmp32 = rwRecGetPkts(rwrec);
243 if (tmp32 > 0xFFFFFF) {
244 memset(&ar[28], 0xFF, 3);
245 } else {
246 #if SK_LITTLE_ENDIAN
247 memcpy(&ar[28], &tmp32, 3);
248 #else
249 memcpy(&ar[28], (((uint8_t*)&tmp32) + 1), 3);
250 #endif
251 }
252 ar[31] = rwRecGetProto(rwrec);
253
254 /* Flags, Initial flags, TCP State */
255 ar[34] = rwRecGetTcpState(rwrec);
256 if (ar[34] & SK_TCPSTATE_EXPANDED) {
257 /* have separate initial and rest flags */
258 ar[32] = rwRecGetRestFlags(rwrec);
259 ar[33] = rwRecGetInitFlags(rwrec);
260 } else {
261 /* have a single flags field */
262 ar[32] = rwRecGetFlags(rwrec);
263 ar[33] = 0;
264 }
265
266 /* Fractional time encoding: by hand, always big endian */
267 ar[35] = 0xFF & (rwRecGetStartMSec(rwrec) >> 2);
268 SET_MASKED_BITS(ar[36], rwRecGetStartMSec(rwrec), 6, 2);
269 SET_MASKED_BITS(ar[36], rwRecGetElapsedMSec(rwrec) >> 4, 0, 6);
270 ar[37] = 0xFF & (rwRecGetElapsedMSec(rwrec) << 4);
271
272 /* swap if required */
273 if (stream->swapFlag) {
274 flowcapioRecordSwap_V5(ar);
275 }
276
277 return SKSTREAM_OK;
278 }
279
280
281 /* ********************************************************************* */
282
283 /*
284 ** FLOWCAP VERSION 4
285 **
286 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
287 **
288 ** uint32_t sIP; // 0- 3 Source IP
289 ** uint32_t dIP; // 4- 7 Destination IP
290 **
291 ** uint32_t bytes; // 8-11 Byte count
292 **
293 ** uint32_t sTime; // 12-15 Start time as UNIX epoch secs
294 **
295 ** uint16_t elapsed; // 16-17 Duration of flow in seconds
296 ** uint16_t sPort; // 18-19 Source port
297 **
298 ** uint16_t dPort; // 20-21 Destination port
299 ** uint16_t service_port; // 22-23 Port reported by flow collector
300 **
301 ** uint8_t input; // 24 SNMP Input
302 ** uint8_t output; // 25 SNMP Output
303 **
304 ** uint8_t pkts[3] // 26-28 Count of packets
305 ** uint8_t proto // 29 Protocol
306 **
307 ** uint8_t flags // 30 EXPANDED==0: All TCP Flags
308 ** // EXPANDED==1: Flags !1st pkt
309 ** uint8_t first_flags; // 31 EXPANDED==0: 0
310 ** // EXPANDED==1: TCP Flags 1st pkt
311 ** uint8_t tcp_state; // 32 TCP state machine info
312 ** uint8_t time_frac[3]; // 33-35 sTime msec & elapsed msec
313 **
314 ** uint32_t payload_hash; // 36-39 Hash of packet's payload
315 **
316 **
317 ** 40 bytes on disk.
318 */
319
320 #define RECLEN_FLOWCAP_V4 40
321
322
323 /*
324 * Unpack the array of bytes 'ar' into a record 'rwrec'
325 */
326 static int
flowcapioRecordUnpack_V4(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)327 flowcapioRecordUnpack_V4(
328 skstream_t *stream,
329 rwGenericRec_V5 *rwrec,
330 uint8_t *ar)
331 {
332 int rv;
333
334 /* The first 36 bytes of a V4 are identical to V3 */
335 rv = flowcapioRecordUnpack_V3(stream, rwrec, ar);
336
337 /* swap if required */
338 if (stream->swapFlag) {
339 /* only need to swap the payload hash */
340 SWAP_DATA32((ar) + 36);
341 }
342
343 /* Put the payload hash into the nhIP */
344 if (rv == SKSTREAM_OK) {
345 rwRecMemSetNhIPv4(rwrec, &ar[36]);
346 }
347
348 return rv;
349 }
350
351
352 /*
353 * Pack the record 'rwrec' into an array of bytes 'ar'
354 */
355 static int
flowcapioRecordPack_V4(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)356 flowcapioRecordPack_V4(
357 skstream_t *stream,
358 const rwGenericRec_V5 *rwrec,
359 uint8_t *ar)
360 {
361 int rv;
362
363 /* The first 36 bytes of a V4 are identical to V3 */
364 rv = flowcapioRecordPack_V3(stream, rwrec, ar);
365
366 if (rv == SKSTREAM_OK) {
367 rwRecMemGetNhIPv4(rwrec, &ar[36]);
368 }
369
370 /* swap if required */
371 if (stream->swapFlag) {
372 /* only need to swap the payload hash */
373 SWAP_DATA32((ar) + 36);
374 }
375
376 return rv;
377 }
378
379
380 /* ********************************************************************* */
381
382 /*
383 ** FLOWCAP VERSION 3
384 **
385 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
386 **
387 ** uint32_t sIP; // 0- 3 Source IP
388 ** uint32_t dIP; // 4- 7 Destination IP
389 **
390 ** uint32_t bytes; // 8-11 Byte count
391 **
392 ** uint32_t sTime; // 12-15 Start time as UNIX epoch secs
393 **
394 ** uint16_t elapsed; // 16-17 Duration of flow in seconds
395 ** uint16_t sPort; // 18-19 Source port
396 **
397 ** uint16_t dPort; // 20-21 Destination port
398 ** uint16_t service_port; // 22-23 Port reported by flow collector
399 **
400 ** uint8_t input; // 24 SNMP Input
401 ** uint8_t output; // 25 SNMP Output
402 **
403 ** uint8_t pkts[3] // 26-28 Count of packets
404 ** uint8_t proto // 29 Protocol
405 **
406 ** uint8_t flags // 30 EXPANDED==0: All TCP Flags
407 ** // EXPANDED==1: Flags !1st pkt
408 ** uint8_t first_flags; // 31 EXPANDED==0: 0
409 ** // EXPANDED==1: TCP Flags 1st pkt
410 ** uint8_t tcp_state; // 32 TCP state machine info
411 ** uint8_t time_frac[3]; // 33-35 sTime msec & elapsed msec
412 **
413 **
414 ** 36 bytes on disk.
415 */
416
417 #define RECLEN_FLOWCAP_V3 36
418
419
420 /*
421 * Byte swap the FLOWCAP v3 record 'ar' in place.
422 */
423 #define flowcapioRecordSwap_V3(ar) \
424 { \
425 uint8_t swap_tmp; \
426 \
427 SWAP_DATA32((ar) + 0); /* sIP */ \
428 SWAP_DATA32((ar) + 4); /* dIP */ \
429 SWAP_DATA32((ar) + 8); /* bytes */ \
430 SWAP_DATA32((ar) + 12); /* sTime */ \
431 SWAP_DATA16((ar) + 16); /* dur */ \
432 SWAP_DATA16((ar) + 18); /* sPort */ \
433 SWAP_DATA16((ar) + 20); /* dPort */ \
434 SWAP_DATA16((ar) + 22); /* service_port */ \
435 /* Two single byte values: input(24), output(25) */ \
436 \
437 swap_tmp = ar[26]; /* packets */ \
438 ar[26] = ar[28]; \
439 ar[28] = swap_tmp; \
440 \
441 /* four bytes: proto(29), flags(30), first_flags(31) tcp_state(32) */ \
442 /* three bytes in hand-encoded time_frac[3] */ \
443 }
444
445
446 /*
447 * Unpack the array of bytes 'ar' into a record 'rwrec'
448 */
449 static int
flowcapioRecordUnpack_V3(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)450 flowcapioRecordUnpack_V3(
451 skstream_t *stream,
452 rwGenericRec_V5 *rwrec,
453 uint8_t *ar)
454 {
455 uint32_t tmp32 = 0;
456 uint16_t elapsed = 0;
457
458 /* swap if required */
459 if (stream->swapFlag) {
460 flowcapioRecordSwap_V3(ar);
461 }
462
463 /* sIP, dIP, bytes */
464 rwRecMemSetSIPv4(rwrec, &ar[0]);
465 rwRecMemSetDIPv4(rwrec, &ar[4]);
466 rwRecMemSetBytes(rwrec, &ar[8]);
467
468 /* sTime seconds, plus fractional seconds in bytes 33,34 */
469 memcpy(&tmp32, &ar[12], sizeof(tmp32));
470 rwRecSetStartTime(rwrec, sktimeCreate(tmp32,
471 ((ar[33] << 2)
472 |GET_MASKED_BITS(ar[34], 6, 2))));
473
474 /* elapsed seconds, plus fractional seconds in bytes 34,35 */
475 memcpy(&elapsed, &ar[16], sizeof(elapsed));
476 rwRecSetElapsed(rwrec, (((uint32_t)1000 * elapsed)
477 + ((GET_MASKED_BITS(ar[34], 0, 6) << 4)
478 | GET_MASKED_BITS(ar[35], 4, 4))));
479
480 /* sPort, dPort, application */
481 rwRecMemSetSPort(rwrec, &ar[18]);
482 rwRecMemSetDPort(rwrec, &ar[20]);
483 rwRecMemSetApplication(rwrec, &ar[22]);
484
485 /* input, output are single byte values */
486 rwRecSetInput(rwrec, ar[24]);
487 rwRecSetOutput(rwrec, ar[25]);
488
489 /* packets, protocol */
490 tmp32 = 0;
491 #if SK_LITTLE_ENDIAN
492 memcpy(&tmp32, &ar[26], 3);
493 #else
494 memcpy((((uint8_t*)&tmp32) + 1), &ar[26], 3);
495 #endif
496 rwRecSetPkts(rwrec, tmp32);
497 rwRecSetProto(rwrec, ar[29]);
498
499 /* Flags, Initial flags, TCP State */
500 rwRecSetTcpState(rwrec, ar[32]);
501 if (ar[32] & SK_TCPSTATE_EXPANDED) {
502 /* have separate initial and session flags */
503 rwRecSetFlags(rwrec, (ar[30] | ar[31]));
504 rwRecSetRestFlags(rwrec, ar[30]);
505 rwRecSetInitFlags(rwrec, ar[31]);
506 } else {
507 /* have a single flags field */
508 rwRecSetFlags(rwrec, ar[30]);
509 }
510
511 /* Fractional times in bytes 33-35 handled above */
512
513 /* Get sensor from header */
514 rwRecSetSensor(rwrec, stream->hdr_sensor);
515
516 return SKSTREAM_OK;
517 }
518
519
520 /*
521 * Pack the record 'rwrec' into an array of bytes 'ar'
522 */
523 static int
flowcapioRecordPack_V3(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)524 flowcapioRecordPack_V3(
525 skstream_t *stream,
526 const rwGenericRec_V5 *rwrec,
527 uint8_t *ar)
528 {
529 uint32_t tmp32;
530 uint16_t elapsed;
531
532 /* sIP, dIP, bytes, sTime */
533 rwRecMemGetSIPv4(rwrec, &ar[0]);
534 rwRecMemGetDIPv4(rwrec, &ar[4]);
535 rwRecMemGetBytes(rwrec, &ar[8]);
536 rwRecMemGetStartSeconds(rwrec, &ar[12]);
537
538 /* elapsed */
539 if (rwRecGetElapsedSeconds(rwrec) > UINT16_MAX) {
540 memset(&ar[16], 0xFF, sizeof(elapsed));
541 } else {
542 elapsed = (uint16_t)rwRecGetElapsedSeconds(rwrec);
543 memcpy(&ar[16], &elapsed, sizeof(elapsed));
544 }
545
546 /* sPort, dPort, application */
547 rwRecMemGetSPort(rwrec, &ar[18]);
548 rwRecMemGetDPort(rwrec, &ar[20]);
549 rwRecMemGetApplication(rwrec, &ar[22]);
550
551 /* input, output are single byte values */
552 ar[24] = 0xFF & rwRecGetInput(rwrec);
553 ar[25] = 0xFF & rwRecGetOutput(rwrec);
554
555 /* packets, protocol */
556 tmp32 = rwRecGetPkts(rwrec);
557 if (tmp32 > 0xFFFFFF) {
558 memset(&ar[26], 0xFF, 3);
559 } else {
560 #if SK_LITTLE_ENDIAN
561 memcpy(&ar[26], &tmp32, 3);
562 #else
563 memcpy(&ar[26], (((uint8_t*)&tmp32) + 1), 3);
564 #endif
565 }
566 ar[29] = rwRecGetProto(rwrec);
567
568 /* Flags, Initial flags, TCP State */
569 ar[32] = rwRecGetTcpState(rwrec);
570 if (ar[32] & SK_TCPSTATE_EXPANDED) {
571 /* have separate initial and rest flags */
572 ar[30] = rwRecGetRestFlags(rwrec);
573 ar[31] = rwRecGetInitFlags(rwrec);
574 } else {
575 /* have a single flags field */
576 ar[30] = rwRecGetFlags(rwrec);
577 ar[31] = 0;
578 }
579
580 /* Fractional time encoding: by hand, always big endian */
581 ar[33] = 0xFF & (rwRecGetStartMSec(rwrec) >> 2);
582 SET_MASKED_BITS(ar[34], rwRecGetStartMSec(rwrec), 6, 2);
583 SET_MASKED_BITS(ar[34], rwRecGetElapsedMSec(rwrec) >> 4, 0, 6);
584 ar[35] = 0xFF & (rwRecGetElapsedMSec(rwrec) << 4);
585
586 /* swap if required */
587 if (stream->swapFlag) {
588 flowcapioRecordSwap_V3(ar);
589 }
590
591 return SKSTREAM_OK;
592 }
593
594
595
596 /* ********************************************************************* */
597
598 /*
599 ** FLOWCAP VERSION 2
600 **
601 ** uint32_t sIP; // 0- 3 Source IP
602 ** uint32_t dIP; // 4- 7 Destination IP
603 **
604 ** uint32_t bytes; // 8-11 Byte count
605 **
606 ** uint32_t sTime; // 12-15 Start time as UNIX epoch secs
607 **
608 ** uint16_t elapsed; // 16-17 Duration of flow in seconds
609 ** uint16_t sPort; // 18-19 Source port
610 **
611 ** uint16_t dPort; // 20-21 Destination port
612 ** uint8_t input; // 22 SNMP Input
613 ** uint8_t output; // 23 SNMP Output
614 **
615 ** uint8_t pkts[3] // 24-26 Count of packets
616 ** uint8_t proto // 27 Protocol
617 **
618 ** uint8_t flags // 28 OR of TCP Flags on all pkts
619 ** uint8_t first_flags; // 29 TOS (ignored)
620 **
621 **
622 ** 30 bytes on disk.
623 */
624
625 #define RECLEN_FLOWCAP_V2 30
626
627
628 /*
629 * Byte swap the FLOWCAP v2 record 'ar' in place.
630 */
631 #define flowcapioRecordSwap_V2(ar) \
632 { \
633 uint8_t swap_tmp; \
634 \
635 SWAP_DATA32((ar) + 0); /* sIP */ \
636 SWAP_DATA32((ar) + 4); /* dIP */ \
637 SWAP_DATA32((ar) + 8); /* bytes */ \
638 SWAP_DATA32((ar) + 12); /* sTime */ \
639 SWAP_DATA16((ar) + 16); /* dur */ \
640 SWAP_DATA16((ar) + 18); /* sPort */ \
641 SWAP_DATA16((ar) + 20); /* dPort */ \
642 /* Two single byte values: input(22), output(23) */ \
643 \
644 swap_tmp = ar[24]; /* packets */ \
645 ar[24] = ar[26]; \
646 ar[26] = swap_tmp; \
647 \
648 /* three bytes: proto(27), flags(28), TOS(29) */ \
649 }
650
651
652 /*
653 * Unpack the array of bytes 'ar' into a record 'rwrec'
654 */
655 static int
flowcapioRecordUnpack_V2(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)656 flowcapioRecordUnpack_V2(
657 skstream_t *stream,
658 rwGenericRec_V5 *rwrec,
659 uint8_t *ar)
660 {
661 uint32_t tmp32 = 0;
662 uint16_t elapsed = 0;
663
664 /* swap if required */
665 if (stream->swapFlag) {
666 flowcapioRecordSwap_V2(ar);
667 }
668
669 /* sIP, dIP, bytes */
670 rwRecMemSetSIPv4(rwrec, &ar[0]);
671 rwRecMemSetDIPv4(rwrec, &ar[4]);
672 rwRecMemSetBytes(rwrec, &ar[8]);
673
674 /* sTime */
675 memcpy(&tmp32, &ar[12], sizeof(tmp32));
676 rwRecSetStartTime(rwrec, sktimeCreate(tmp32, 0));
677
678 /* elapsed */
679 memcpy(&elapsed, &ar[16], sizeof(elapsed));
680 rwRecSetElapsed(rwrec, ((uint32_t)1000 * elapsed));
681
682 /* sPort, dPort */
683 rwRecMemSetSPort(rwrec, &ar[18]);
684 rwRecMemSetDPort(rwrec, &ar[20]);
685
686 /* input, output are single byte values */
687 rwRecSetInput(rwrec, ar[22]);
688 rwRecSetOutput(rwrec, ar[23]);
689
690 /* packets, protocol */
691 tmp32 = 0;
692 #if SK_LITTLE_ENDIAN
693 memcpy(&tmp32, &ar[24], 3);
694 #else
695 memcpy((((uint8_t*)&tmp32) + 1), &ar[24], 3);
696 #endif
697 rwRecSetPkts(rwrec, tmp32);
698 rwRecSetProto(rwrec, ar[27]);
699
700 /* Flags */
701 rwRecSetFlags(rwrec, ar[28]);
702
703 /* Get sensor from header */
704 rwRecSetSensor(rwrec, stream->hdr_sensor);
705
706 return SKSTREAM_OK;
707 }
708
709
710 /*
711 * Pack the record 'rwrec' into an array of bytes 'ar'
712 */
713 static int
flowcapioRecordPack_V2(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)714 flowcapioRecordPack_V2(
715 skstream_t *stream,
716 const rwGenericRec_V5 *rwrec,
717 uint8_t *ar)
718 {
719 uint32_t tmp32;
720 uint16_t elapsed;
721
722 /* sIP, dIP, bytes, sTime */
723 rwRecMemGetSIPv4(rwrec, &ar[0]);
724 rwRecMemGetDIPv4(rwrec, &ar[4]);
725 rwRecMemGetBytes(rwrec, &ar[8]);
726 rwRecMemGetStartSeconds(rwrec, &ar[12]);
727
728 /* elapsed */
729 if (rwRecGetElapsedSeconds(rwrec) > UINT16_MAX) {
730 memset(&ar[16], 0xFF, sizeof(elapsed));
731 } else {
732 elapsed = (uint16_t)rwRecGetElapsedSeconds(rwrec);
733 memcpy(&ar[16], &elapsed, sizeof(elapsed));
734 }
735
736 /* sPort, dPort */
737 rwRecMemGetSPort(rwrec, &ar[18]);
738 rwRecMemGetDPort(rwrec, &ar[20]);
739
740 /* input, output are single byte values */
741 ar[22] = 0xFF & rwRecGetInput(rwrec);
742 ar[23] = 0xFF & rwRecGetOutput(rwrec);
743
744 /* packets, protocol */
745 tmp32 = rwRecGetPkts(rwrec);
746 if (tmp32 > 0xFFFFFF) {
747 memset(&ar[24], 0xFF, 3);
748 } else {
749 #if SK_LITTLE_ENDIAN
750 memcpy(&ar[24], &tmp32, 3);
751 #else
752 memcpy(&ar[24], (((uint8_t*)&tmp32) + 1), 3);
753 #endif
754 }
755 ar[27] = rwRecGetProto(rwrec);
756
757 /* Flags, TOS */
758 ar[28] = rwRecGetFlags(rwrec);
759 ar[29] = 0;
760
761 /* swap if required */
762 if (stream->swapFlag) {
763 flowcapioRecordSwap_V2(ar);
764 }
765
766 return SKSTREAM_OK;
767 }
768
769
770 /* ********************************************************************* */
771
772 /*
773 * Return length of record of specified version, or 0 if no such
774 * version exists. See skstream_priv.h for details.
775 */
776 uint16_t
flowcapioGetRecLen(sk_file_version_t vers)777 flowcapioGetRecLen(
778 sk_file_version_t vers)
779 {
780 switch (vers) {
781 case 2:
782 return RECLEN_FLOWCAP_V2;
783 case 3:
784 return RECLEN_FLOWCAP_V3;
785 case 4:
786 return RECLEN_FLOWCAP_V4;
787 case 5:
788 case 6:
789 return RECLEN_FLOWCAP_V5;
790 default:
791 return 0;
792 }
793 }
794
795
796 /*
797 * status = flowcapioPrepare(&stream);
798 *
799 * Sets the record version to the default if it is unspecified,
800 * checks that the record format supports the requested record
801 * version, sets the record length, and sets the pack and unpack
802 * functions for this record format and version.
803 */
804 int
flowcapioPrepare(skstream_t * stream)805 flowcapioPrepare(
806 skstream_t *stream)
807 {
808 #define FILE_FORMAT "FT_FLOWCAP"
809 sk_file_header_t *hdr = stream->silk_hdr;
810 int rv = SKSTREAM_OK; /* return value */
811
812 assert(skHeaderGetFileFormat(hdr) == FT_FLOWCAP);
813
814 /* Set version if none was selected by caller */
815 if ((stream->io_mode == SK_IO_WRITE)
816 && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
817 {
818 skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
819 }
820
821 /* version check; set values based on version */
822 switch (skHeaderGetRecordVersion(hdr)) {
823 case 6:
824 stream->rwUnpackFn = &flowcapioRecordUnpack_V6;
825 stream->rwPackFn = &flowcapioRecordPack_V5;
826 break;
827 case 5:
828 stream->rwUnpackFn = &flowcapioRecordUnpack_V5;
829 stream->rwPackFn = &flowcapioRecordPack_V5;
830 break;
831 case 4:
832 stream->rwUnpackFn = &flowcapioRecordUnpack_V4;
833 stream->rwPackFn = &flowcapioRecordPack_V4;
834 break;
835 case 3:
836 stream->rwUnpackFn = &flowcapioRecordUnpack_V3;
837 stream->rwPackFn = &flowcapioRecordPack_V3;
838 break;
839 case 2:
840 stream->rwUnpackFn = &flowcapioRecordUnpack_V2;
841 stream->rwPackFn = &flowcapioRecordPack_V2;
842 break;
843 case 1:
844 /* no longer supported */
845 case 0:
846 default:
847 rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
848 goto END;
849 }
850
851 stream->recLen = flowcapioGetRecLen(skHeaderGetRecordVersion(hdr));
852
853 /* verify lengths */
854 if (stream->recLen == 0) {
855 skAppPrintErr("Record length not set for %s version %u",
856 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
857 skAbort();
858 }
859 if (stream->recLen != skHeaderGetRecordLength(hdr)) {
860 if (0 == skHeaderGetRecordLength(hdr)) {
861 skHeaderSetRecordLength(hdr, stream->recLen);
862 } else {
863 skAppPrintErr(("Record length mismatch for %s version %u\n"
864 "\tcode = %" PRIu16 " bytes; header = %lu bytes"),
865 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
866 stream->recLen,
867 (unsigned long)skHeaderGetRecordLength(hdr));
868 skAbort();
869 }
870 }
871
872 END:
873 return rv;
874 }
875
876
877 /*
878 ** Local Variables:
879 ** mode:c
880 ** indent-tabs-mode:nil
881 ** c-basic-offset:4
882 ** End:
883 */
884