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 /*
10 ** Functions to support binary output: opening binary SiLK files for
11 ** writing or appending.
12 **
13 */
14
15
16 #include <silk/silk.h>
17
18 RCSIDENTVAR(rcsID_RWPACK_C, "$SiLK: rwpack.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
19
20 #ifndef RWPACK_BYTES_PACKETS
21 #if defined(RWPACK_FLAGS_TIMES_VOLUMES) || defined(RWPACK_SBB_PEF)
22 #define RWPACK_BYTES_PACKETS 1
23 #endif
24 #endif
25 #include "skstream_priv.h"
26
27
28 #ifdef RWPACK_BYTES_PACKETS
29 /* Convert bytes and packets fields in 'rwrec' to the values used in
30 * rwfilter output files and in the packed file formats. See
31 * skstream_priv.h. */
32 static int
rwpackPackBytesPackets(uint32_t * bpp_out,uint32_t * pkts_out,uint32_t * pflag_out,const rwGenericRec_V5 * rwrec)33 rwpackPackBytesPackets(
34 uint32_t *bpp_out,
35 uint32_t *pkts_out,
36 uint32_t *pflag_out,
37 const rwGenericRec_V5 *rwrec)
38 {
39 imaxdiv_t bpp;
40 uint32_t packets;
41 uint32_t bytes;
42
43 assert(bpp_out);
44 assert(pkts_out);
45 assert(pflag_out);
46 assert(rwrec);
47
48 packets = rwRecGetPkts(rwrec);
49 bytes = rwRecGetBytes(rwrec);
50
51 /* Check for 0 value in 'pkts' field */
52 if (packets == 0) {
53 return SKSTREAM_ERR_PKTS_ZERO;
54 }
55
56 /* Verify that there are more bytes than packets */
57 if (packets > bytes) {
58 return SKSTREAM_ERR_PKTS_GT_BYTES;
59 }
60
61 /* Set packets field; check for overflow */
62 if (packets < MAX_PKTS) {
63 *pkts_out = packets;
64 *pflag_out = 0;
65 } else {
66 *pkts_out = packets / PKTS_DIVISOR;
67 if (*pkts_out >= MAX_PKTS) {
68 /* Double overflow in pkts */
69 return SKSTREAM_ERR_PKTS_OVRFLO;
70 }
71 /* pktsFlag */
72 *pflag_out = 1;
73 }
74
75 /* calculate the bytes-per-packet ratio */
76 bpp = imaxdiv(bytes, packets);
77
78 if (bpp.quot > MASKARRAY_14) {
79 return SKSTREAM_ERR_BPP_OVRFLO;
80 }
81
82 /* compute new value */
83 *bpp_out = (((uint32_t)bpp.quot) << 6) |
84 ((uint32_t)(bpp.rem * BPP_PRECN / packets));
85
86 return SKSTREAM_OK;
87 }
88
89
90 /* Fill in the bytes and packets fields in rwrec by expanding the
91 * values that were read from disk. See skstream_priv.h for details. */
92 static void
rwpackUnpackBytesPackets(rwGenericRec_V5 * rwrec,uint32_t bpp,uint32_t pkts,uint32_t pflag)93 rwpackUnpackBytesPackets(
94 rwGenericRec_V5 *rwrec,
95 uint32_t bpp,
96 uint32_t pkts,
97 uint32_t pflag)
98 {
99 uint32_t bytes;
100 int bPPkt, bPPFrac;
101 div_t i;
102
103 if (pflag) {
104 pkts *= PKTS_DIVISOR;
105 }
106
107 /* Unpack the bpp value: bPPkt:14; bPPFrac:6; */
108 bPPkt = GET_MASKED_BITS(bpp, 6, 14);
109 bPPFrac = GET_MASKED_BITS(bpp, 0, 6);
110
111 /* convert fraction to whole number */
112 i = div((bPPFrac * pkts), BPP_PRECN);
113
114 bytes = ((bPPkt * pkts) + i.quot + ((i.rem >= BPP_PRECN_DIV_2) ? 1 : 0));
115
116 rwRecSetPkts(rwrec, pkts);
117 rwRecSetBytes(rwrec, bytes);
118 }
119 #endif /* RWPACK_BYTES_PACKETS */
120
121
122 #ifdef RWPACK_PROTO_FLAGS
123 /* Pack the protocol, flags, and TCP state fields. See skstream_priv.h */
124 static void
rwpackPackProtoFlags(uint8_t * is_tcp_out,uint8_t * prot_flags_out,uint8_t * tcp_state_out,uint8_t * rest_flags_out,const rwGenericRec_V5 * rwrec)125 rwpackPackProtoFlags(
126 uint8_t *is_tcp_out,
127 uint8_t *prot_flags_out,
128 uint8_t *tcp_state_out,
129 uint8_t *rest_flags_out,
130 const rwGenericRec_V5 *rwrec)
131 {
132 *tcp_state_out = rwRecGetTcpState(rwrec);
133 if (rwRecGetProto(rwrec) != IPPROTO_TCP) {
134 /* Flow is not TCP, so there is no additional TCP info. Set
135 * '*rest_flags_out' to value of rwrec->flags. */
136 *is_tcp_out = 0;
137 *prot_flags_out = rwRecGetProto(rwrec);
138 *rest_flags_out = rwRecGetFlags(rwrec);
139 } else {
140 /* Flow is TCP */
141 *is_tcp_out = 1;
142 if (*tcp_state_out & SK_TCPSTATE_EXPANDED) {
143 /* There is additional TCP info. Put the initial TCP
144 * flags into the '*prot_flags_out' value. */
145 *prot_flags_out = rwRecGetInitFlags(rwrec);
146 *rest_flags_out = rwRecGetRestFlags(rwrec);
147 } else {
148 /* There is no additional TCP info. */
149 *prot_flags_out = rwRecGetFlags(rwrec);
150 *rest_flags_out = 0;
151 }
152 }
153 }
154
155
156 /* Fill in the protocol, flags, and TCP state fields on the rwrec. See
157 * skstream_priv.h */
158 static void
rwpackUnpackProtoFlags(rwGenericRec_V5 * rwrec,uint8_t is_tcp,uint8_t prot_flags,uint8_t tcp_state,uint8_t rest_flags)159 rwpackUnpackProtoFlags(
160 rwGenericRec_V5 *rwrec,
161 uint8_t is_tcp,
162 uint8_t prot_flags,
163 uint8_t tcp_state,
164 uint8_t rest_flags)
165 {
166 /* For some record types (e.g., RWWWW), proto is fixed at 6(TCP)
167 * and there may be another value in the 'is_tcp' bit; ignore the
168 * 'is_tcp' bit if the protocol is already set to TCP. */
169 rwRecSetTcpState(rwrec, tcp_state);
170 if ((rwRecGetProto(rwrec) == IPPROTO_TCP) || (is_tcp == 1)) {
171 /* Flow is TCP */
172 rwRecSetProto(rwrec, IPPROTO_TCP);
173 if (tcp_state & SK_TCPSTATE_EXPANDED) {
174 /* We have additional flow information; value in
175 * prot_flags are the flags on the first packet. */
176 rwRecSetInitFlags(rwrec, prot_flags);
177 rwRecSetRestFlags(rwrec, rest_flags);
178 rwRecSetFlags(rwrec, (uint8_t)(prot_flags | rest_flags));
179 } else {
180 /* We don't have additional TCP info; 'prot_flags' holds
181 * the flags. */
182 rwRecSetFlags(rwrec, prot_flags);
183 }
184 } else {
185 /* Flow is not TCP so there can be no additional TCP info.
186 * 'prot_flags' holds the protocol. Although 'flags' has no
187 * real meaning here, the 'rest_flags' value has the value
188 * that we got from the flow collector, so set 'rwrec->flags'
189 * to that value. */
190 rwRecSetProto(rwrec, prot_flags);
191 rwRecSetFlags(rwrec, rest_flags);
192 }
193 }
194 #endif /* RWPACK_PROTO_FLAGS */
195
196
197 #ifdef RWPACK_SBB_PEF
198 /* Compute the 'sbb' and 'pef' fields used in packed file formats.
199 * See skstream_priv.h. */
200 static int
rwpackPackSbbPef(uint32_t * sbb_out,uint32_t * pef_out,const rwGenericRec_V5 * rwrec,sktime_t file_start_time)201 rwpackPackSbbPef(
202 uint32_t *sbb_out,
203 uint32_t *pef_out,
204 const rwGenericRec_V5 *rwrec,
205 sktime_t file_start_time)
206 {
207 int rv = SKSTREAM_OK; /* return value */
208 sktime_t start_time;
209 uint32_t elapsed;
210 uint32_t pkts, bpp, pflag;
211
212 elapsed = (rwRecGetElapsed(rwrec) / 1000);
213 if (elapsed >= MAX_ELAPSED_TIME_OLD) {
214 rv = SKSTREAM_ERR_ELPSD_OVRFLO;
215 goto END;
216 }
217
218 start_time = rwRecGetStartTime(rwrec);
219 if (start_time < file_start_time) {
220 rv = SKSTREAM_ERR_STIME_UNDRFLO;
221 goto END;
222 }
223 /* convert start time to seconds in the hour */
224 start_time = (start_time - file_start_time) / 1000;
225 if (start_time >= MAX_START_TIME) {
226 rv = SKSTREAM_ERR_STIME_OVRFLO;
227 goto END;
228 }
229
230 rv = rwpackPackBytesPackets(&bpp, &pkts, &pflag, rwrec);
231 if (rv) { goto END; }
232
233 /* sbb: uint32_t sTime:12; uint32_t bPPkt:14; uint32_t bPPFrac:6; */
234 *sbb_out = (((MASKARRAY_12 & (uint32_t)start_time) << 20)
235 | (bpp & MASKARRAY_20));
236
237 /* pef: uint32_t pkts:20; uint32_t elapsed :11; uint32_t pktsFlag:1; */
238 *pef_out = ((pkts << 12) | (elapsed << 1) | pflag);
239
240 END:
241 return rv;
242 }
243
244
245 /* Set values in rwrec by expanding the 'sbb' and 'pef' fields that
246 * exist in the packed file formats. See skstream_priv.h for details. */
247 static void
rwpackUnpackSbbPef(rwGenericRec_V5 * rwrec,sktime_t file_start_time,const uint32_t * sbb,const uint32_t * pef)248 rwpackUnpackSbbPef(
249 rwGenericRec_V5 *rwrec,
250 sktime_t file_start_time,
251 const uint32_t *sbb,
252 const uint32_t *pef)
253 {
254 uint32_t pkts, pktsFlag, bpp, start_time;
255
256 /* pef: uint32_t pkts:20; uint32_t elapsed :11; uint32_t pktsFlag:1; */
257 pkts = *pef >> 12;
258 rwRecSetElapsed(rwrec, (1000 * ((*pef >> 1) & MASKARRAY_11)));
259 pktsFlag = *pef & MASKARRAY_01;
260
261 /* sbb: uint32_t start_time:12; uint32_t bpp:20 */
262 bpp = *sbb & MASKARRAY_20;
263 start_time = (*sbb >> 20);
264 rwRecSetStartTime(rwrec, file_start_time + sktimeCreate(start_time, 0));
265
266 rwpackUnpackBytesPackets(rwrec, bpp, pkts, pktsFlag);
267 }
268 #endif /* RWPACK_SBB_PEF */
269
270
271 #ifdef RWPACK_TIME_BYTES_PKTS_FLAGS
272 static int
rwpackPackTimeBytesPktsFlags(uint32_t * pkts_stime_out,uint32_t * bbe_out,uint32_t * msec_flags_out,const rwGenericRec_V5 * rwrec,sktime_t file_start_time)273 rwpackPackTimeBytesPktsFlags(
274 uint32_t *pkts_stime_out,
275 uint32_t *bbe_out,
276 uint32_t *msec_flags_out,
277 const rwGenericRec_V5 *rwrec,
278 sktime_t file_start_time)
279 {
280 int rv = SKSTREAM_OK; /* return value */
281 sktime_t start_time;
282 uint32_t pkts, bpp, pflag, is_tcp;
283 uint8_t prot_flags;
284 imaxdiv_t stime_div;
285 imaxdiv_t elapsed_div;
286
287 elapsed_div = imaxdiv(rwRecGetElapsed(rwrec), 1000);
288
289 if (elapsed_div.quot >= MAX_ELAPSED_TIME) {
290 rv = SKSTREAM_ERR_ELPSD_OVRFLO;
291 goto END;
292 }
293
294 start_time = rwRecGetStartTime(rwrec);
295 if (start_time < file_start_time) {
296 rv = SKSTREAM_ERR_STIME_UNDRFLO;
297 goto END;
298 }
299 start_time -= file_start_time;
300 stime_div = imaxdiv(start_time, 1000);
301 if (stime_div.quot >= MAX_START_TIME) {
302 rv = SKSTREAM_ERR_STIME_OVRFLO;
303 goto END;
304 }
305
306 rv = rwpackPackBytesPackets(&bpp, &pkts, &pflag, rwrec);
307 if (rv) { goto END; }
308
309 /* pkts_stime: pkts:20; sTime: 12; */
310 *pkts_stime_out = ((pkts << 12)
311 | (MASKARRAY_12 & (uint32_t)stime_div.quot));
312
313 /* bbe: bpp: 20; elapsed: 12 */
314 *bbe_out = ((bpp << 12)
315 | (MASKARRAY_12 & (uint32_t)elapsed_div.quot));
316
317 /* set is_tcp bit and prot_flags */
318 if (rwRecGetProto(rwrec) == IPPROTO_TCP) {
319 is_tcp = 1;
320 prot_flags = rwRecGetFlags(rwrec);
321 } else {
322 is_tcp = 0;
323 prot_flags = rwRecGetProto(rwrec);
324 }
325
326 /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1;
327 * is_tcp:1; pad:2; prot_flags:8;*/
328 *msec_flags_out = (((MASKARRAY_10 & (uint32_t)stime_div.rem) << 22)
329 | ((MASKARRAY_10 & (uint32_t)elapsed_div.rem) << 12)
330 | (pflag ? (1 << 11) : 0)
331 | (is_tcp ? (1 << 10) : 0)
332 | prot_flags);
333
334 END:
335 return rv;
336 }
337
338
339 static void
rwpackUnpackTimeBytesPktsFlags(rwGenericRec_V5 * rwrec,sktime_t file_start_time,const uint32_t * pkts_stime,const uint32_t * bbe,const uint32_t * msec_flags)340 rwpackUnpackTimeBytesPktsFlags(
341 rwGenericRec_V5 *rwrec,
342 sktime_t file_start_time,
343 const uint32_t *pkts_stime,
344 const uint32_t *bbe,
345 const uint32_t *msec_flags)
346 {
347 uint32_t pkts, bpp, is_tcp, pflag;
348 uint8_t prot_flags;
349
350 /* pkts_stime: pkts:20; sTime: 12; */
351 /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1;
352 * is_tcp:1; pad:2, prot_flags:8; */
353 pkts = GET_MASKED_BITS(*pkts_stime, 12, 20);
354
355 rwRecSetStartTime(rwrec,
356 (file_start_time
357 + sktimeCreate(GET_MASKED_BITS(*pkts_stime, 0, 12),
358 GET_MASKED_BITS(*msec_flags, 22, 10))));
359
360 /* bbe: bpp: 20; elapsed: 12 */
361 bpp = GET_MASKED_BITS(*bbe, 12, 20);
362
363 rwRecSetElapsed(rwrec, (1000u * GET_MASKED_BITS(*bbe, 0, 12)
364 + GET_MASKED_BITS(*msec_flags, 12, 10)));
365
366 /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1;
367 * is_tcp:1; pad:2, prot_flags:8; */
368 pflag = GET_MASKED_BITS(*msec_flags, 11, 1);
369 is_tcp = GET_MASKED_BITS(*msec_flags, 10, 1);
370 prot_flags = (uint8_t)GET_MASKED_BITS(*msec_flags, 0, 8);
371
372 if (rwRecGetProto(rwrec) == IPPROTO_TCP) {
373 /* caller has forced record to be TCP */
374 rwRecSetFlags(rwrec, prot_flags);
375 } else if (is_tcp == 0) {
376 /* flow is not TCP */
377 rwRecSetProto(rwrec, prot_flags);
378 } else {
379 /* flow is TCP */
380 rwRecSetProto(rwrec, IPPROTO_TCP);
381 rwRecSetFlags(rwrec, prot_flags);
382 }
383
384 /* unpack the bpp value into bytes and packets */
385 rwpackUnpackBytesPackets(rwrec, bpp, pkts, pflag);
386 }
387 #endif /* RWPACK_TIME_BYTES_PKTS_FLAGS */
388
389
390 #ifdef RWPACK_FLAGS_TIMES_VOLUMES
391 static int
rwpackPackFlagsTimesVolumes(uint8_t * ar,const rwGenericRec_V5 * rwrec,sktime_t file_start_time,size_t len)392 rwpackPackFlagsTimesVolumes(
393 uint8_t *ar,
394 const rwGenericRec_V5 *rwrec,
395 sktime_t file_start_time,
396 size_t len)
397 {
398 uint32_t bpp, tmp, pkts, pflag;
399 uint8_t tcp_state;
400 sktime_t start_time;
401 int rv = SKSTREAM_OK;
402
403 if (rwRecGetElapsed(rwrec) >= 1000u * MAX_ELAPSED_TIME) {
404 rv = SKSTREAM_ERR_ELPSD_OVRFLO;
405 goto END;
406 }
407
408 start_time = rwRecGetStartTime(rwrec);
409 if (start_time < file_start_time) {
410 rv = SKSTREAM_ERR_STIME_UNDRFLO;
411 goto END;
412 }
413 start_time -= file_start_time;
414 if (start_time >= sktimeCreate(MAX_START_TIME, 0)) {
415 rv = SKSTREAM_ERR_STIME_OVRFLO;
416 goto END;
417 }
418
419 rv = rwpackPackBytesPackets(&bpp, &pkts, &pflag, rwrec);
420 if (rv) { goto END; }
421
422 /*
423 ** uint32_t stime_bb1; // 0- 3
424 ** // uint32_t stime :22 // Start time:msec offset from hour
425 ** // uint32_t bPPkt1 :10; // Whole bytes-per-packet (hi 10)
426 */
427 tmp = (((MASKARRAY_22 & (uint32_t)start_time) << 10)
428 | (GET_MASKED_BITS(bpp, 10, 10)));
429 memcpy(&ar[0], &tmp, sizeof(tmp));
430
431 /*
432 ** uint32_t bb2_elapsed; // 4- 7
433 ** // uint32_t bPPkt2 : 4; // Whole bytes-per-packet (low 4)
434 ** // uint32_t bPPFrac : 6; // Fractional bytes-per-packet
435 ** // uint32_t elapsed :22; // Duration of flow in msec
436 **
437 */
438 tmp = ((GET_MASKED_BITS(bpp, 0, 10) << 22)
439 | (MASKARRAY_22 & rwRecGetElapsed(rwrec)));
440 memcpy(&ar[4], &tmp, sizeof(tmp));
441
442 /*
443 ** uint8_t tcp_state; // 12 TCP state machine info
444 ** uint8_t rest_flags; // 13 is_tcp==0: Flow's reported flags
445 ** // is_tcp==1 &&
446 ** // EXPANDED==0:Empty
447 ** // EXPANDED==1:TCPflags/!1st pkt
448 ** uint16_t application; // 14-15 Type of traffic
449 */
450 if (len == 12) {
451 tcp_state = 0;
452 } else if (len == 16) {
453 tcp_state = rwRecGetTcpState(rwrec);
454 ar[12] = tcp_state;
455 if (rwRecGetProto(rwrec) != IPPROTO_TCP) {
456 /* when not TCP, holds whatever flags value we have */
457 ar[13] = rwRecGetFlags(rwrec);
458 } else if (tcp_state & SK_TCPSTATE_EXPANDED) {
459 /* when TCP and extended data, hold the rest flags */
460 ar[13] = rwRecGetRestFlags(rwrec);
461 } else {
462 /* when TCP but no extended data, is empty */
463 ar[13] = 0;
464 }
465 rwRecMemGetApplication(rwrec, &ar[14]);
466 } else {
467 skAppPrintErr(("Bad length (%lu) to rwpackPackFlagsTimesVolumes"
468 " at %s:%d"),
469 (unsigned long)len, __FILE__, __LINE__);
470 skAbort();
471 }
472
473 /*
474 ** uint32_t pro_flg_pkts; // 8-11
475 ** // uint32_t prot_flags: 8; // is_tcp==0: IP protocol
476 ** // is_tcp==1 &&
477 ** // EXPANDED==0:TCPflags/All pkts
478 ** // EXPANDED==1:TCPflags/1st pkt
479 ** // uint32_t pflag : 1; // 'pkts' requires multiplier?
480 ** // uint32_t is_tcp : 1; // 1 if flow is TCP; 0 otherwise
481 ** // uint32_t padding : 2; //
482 ** // uint32_t pkts :20; // Count of packets
483 */
484 tmp = ((pflag << 23)
485 | (MASKARRAY_20 & pkts));
486 if (rwRecGetProto(rwrec) != IPPROTO_TCP) {
487 tmp |= (rwRecGetProto(rwrec) << 24);
488 } else {
489 if (tcp_state & SK_TCPSTATE_EXPANDED) {
490 tmp |= ((rwRecGetInitFlags(rwrec) << 24)
491 | (1 << 22));
492 } else {
493 tmp |= ((rwRecGetFlags(rwrec) << 24)
494 | (1 << 22));
495 }
496 }
497 memcpy(&ar[8], &tmp, sizeof(tmp));
498
499 END:
500 return rv;
501 }
502
503
504 static void
rwpackUnpackFlagsTimesVolumes(rwGenericRec_V5 * rwrec,const uint8_t * ar,sktime_t file_start_time,size_t len,int is_tcp)505 rwpackUnpackFlagsTimesVolumes(
506 rwGenericRec_V5 *rwrec,
507 const uint8_t *ar,
508 sktime_t file_start_time,
509 size_t len,
510 int is_tcp)
511 {
512 uint32_t bpp, tmp, pkts, pflag;
513 uint8_t tcp_state, rest_flags;
514
515 /*
516 ** uint8_t tcp_state; // 12 TCP state machine info
517 ** uint8_t rest_flags; // 13 is_tcp==0: Flow's reported flags
518 ** // is_tcp==1 &&
519 ** // EXPANDED==0:Empty
520 ** // EXPANDED==1:TCPflags/!1st pkt
521 ** uint16_t application; // 14-15 Type of traffic
522 */
523 if (len == 12) {
524 tcp_state = 0;
525 rest_flags = 0;
526 } else if (len == 16) {
527 tcp_state = ar[12];
528 rest_flags = ar[13];
529 rwRecSetTcpState(rwrec, tcp_state);
530 rwRecMemSetApplication(rwrec, &ar[14]);
531 } else {
532 skAppPrintErr(("Bad length (%lu) to rwpackUnpackFlagsTimesVolumes"
533 " at %s:%d"),
534 (unsigned long)len, __FILE__, __LINE__);
535 skAbort();
536 }
537
538 /*
539 ** uint32_t pro_flg_pkts; // 8-11
540 ** // uint32_t prot_flags: 8; // is_tcp==0: IP protocol
541 ** // is_tcp==1 &&
542 ** // EXPANDED==0:TCPflags/All pkts
543 ** // EXPANDED==1:TCPflags/1st pkt
544 ** // uint32_t pflag : 1; // 'pkts' requires multiplier?
545 ** // uint32_t is_tcp : 1; // 1 if flow is TCP; 0 otherwise
546 ** // uint32_t padding : 2; //
547 ** // uint32_t pkts :20; // Count of packets
548 */
549 memcpy(&tmp, &ar[8], sizeof(tmp));
550 pkts = GET_MASKED_BITS(tmp, 0, 20);
551 pflag = GET_MASKED_BITS(tmp, 23, 1);
552 if (!is_tcp) {
553 is_tcp = GET_MASKED_BITS(tmp, 22, 1);
554 }
555 if (!is_tcp) {
556 rwRecSetProto(rwrec, GET_MASKED_BITS(tmp, 24, 8));
557 rwRecSetFlags(rwrec, rest_flags);
558 } else {
559 rwRecSetProto(rwrec, IPPROTO_TCP);
560 if (tcp_state & SK_TCPSTATE_EXPANDED) {
561 rwRecSetRestFlags(rwrec, rest_flags);
562 rwRecSetInitFlags(rwrec, GET_MASKED_BITS(tmp, 24, 8));
563 }
564 rwRecSetFlags(rwrec, (GET_MASKED_BITS(tmp, 24, 8)
565 | rest_flags));
566 }
567
568 /*
569 ** uint32_t bb2_elapsed; // 4- 7
570 ** // uint32_t bPPkt2 : 4; // Whole bytes-per-packet (low 4)
571 ** // uint32_t bPPFrac : 6; // Fractional bytes-per-packet
572 ** // uint32_t elapsed :22; // Duration of flow in msec
573 **
574 */
575 memcpy(&tmp, &ar[4], sizeof(tmp));
576 rwRecSetElapsed(rwrec, GET_MASKED_BITS(tmp, 0, 22));
577
578
579 /*
580 ** uint32_t stime_bb1; // 0- 3
581 ** // uint32_t stime :22 // Start time:msec offset from hour
582 ** // uint32_t bPPkt1 :10; // Whole bytes-per-packet (hi 10)
583 */
584 memcpy(&bpp, &ar[0], sizeof(bpp));
585 rwRecSetStartTime(rwrec, file_start_time + GET_MASKED_BITS(bpp, 10, 22));
586
587 bpp = ((GET_MASKED_BITS(bpp, 0, 10) << 10)
588 | GET_MASKED_BITS(tmp, 22, 10));
589
590 rwpackUnpackBytesPackets(rwrec, bpp, pkts, pflag);
591 }
592 #endif /* RWPACK_FLAGS_TIMES_VOLUMES */
593
594
595 #ifdef RWPACK_TIMES_FLAGS_PROTO
596 static int
rwpackPackTimesFlagsProto(const rwGenericRec_V5 * rwrec,uint8_t * ar,sktime_t file_start_time)597 rwpackPackTimesFlagsProto(
598 const rwGenericRec_V5 *rwrec,
599 uint8_t *ar,
600 sktime_t file_start_time)
601 {
602 sktime_t start_time;
603 uint32_t tmp;
604 int rv = SKSTREAM_OK; /* return value */
605
606 start_time = rwRecGetStartTime(rwrec);
607 if (start_time < file_start_time) {
608 rv = SKSTREAM_ERR_STIME_UNDRFLO;
609 goto END;
610 }
611 start_time -= file_start_time;
612 if (start_time >= sktimeCreate(MAX_START_TIME, 0)) {
613 rv = SKSTREAM_ERR_STIME_OVRFLO;
614 goto END;
615 }
616
617 /*
618 ** uint32_t rflag_stime; // 0- 3
619 ** // uint32_t rest_flags: 8; // is_tcp==0: Empty; else
620 ** // EXPANDED==0:Empty
621 ** // EXPANDED==1:TCPflags/!1st pkt
622 ** // uint32_t is_tcp : 1; // 1 if FLOW is TCP; 0 otherwise
623 ** // uint32_t unused : 1; // Reserved
624 ** // uint32_t stime :22; // Start time:msec offset from hour
625 **
626 ** uint8_t proto_iflags; // 4 is_tcp==0: Protocol; else:
627 ** // EXPANDED==0:TCPflags/ALL pkts
628 ** // EXPANDED==1:TCPflags/1st pkt
629 ** uint8_t tcp_state; // 5 TCP state machine info
630 */
631
632 /* Start time, Protocol, TCP Flags */
633 if (IPPROTO_TCP != rwRecGetProto(rwrec)) {
634 /* First 4 bytes only contains stime */
635 assert((MASKARRAY_22 & (uint32_t)start_time) == start_time);
636 tmp = (uint32_t)start_time;
637 memcpy(&ar[ 0], &tmp, sizeof(tmp));
638 rwRecMemGetProto(rwrec, &ar[ 4]);
639
640 } else if (rwRecGetTcpState(rwrec) & SK_TCPSTATE_EXPANDED) {
641 tmp = ((rwRecGetRestFlags(rwrec) << 24)
642 | (1 << 23)
643 | (MASKARRAY_22 & (uint32_t)start_time));
644 memcpy(&ar[ 0], &tmp, sizeof(tmp));
645 rwRecMemGetInitFlags(rwrec, &ar[ 4]);
646
647 } else {
648 tmp = ((1 << 23)
649 | (MASKARRAY_22 & (uint32_t)start_time));
650 memcpy(&ar[ 0], &tmp, sizeof(tmp));
651 rwRecMemGetFlags(rwrec, &ar[ 4]);
652 }
653
654 rwRecMemGetTcpState(rwrec, &ar[ 5]);
655
656 END:
657 return rv;
658 }
659
660
661 static void
rwpackUnpackTimesFlagsProto(rwGenericRec_V5 * rwrec,const uint8_t * ar,sktime_t file_start_time)662 rwpackUnpackTimesFlagsProto(
663 rwGenericRec_V5 *rwrec,
664 const uint8_t *ar,
665 sktime_t file_start_time)
666 {
667 uint32_t tmp;
668
669 /*
670 ** uint32_t rflag_stime; // 0- 3
671 ** // uint32_t rest_flags: 8; // is_tcp==0: Empty; else
672 ** // EXPANDED==0:Empty
673 ** // EXPANDED==1:TCPflags/!1st pkt
674 ** // uint32_t is_tcp : 1; // 1 if FLOW is TCP; 0 otherwise
675 ** // uint32_t unused : 1; // Reserved
676 ** // uint32_t stime :22; // Start time:msec offset from hour
677 **
678 ** uint8_t proto_iflags; // 4 is_tcp==0: Protocol; else:
679 ** // EXPANDED==0:TCPflags/ALL pkts
680 ** // EXPANDED==1:TCPflags/1st pkt
681 ** uint8_t tcp_state; // 5 TCP state machine info
682 */
683
684 memcpy(&tmp, &ar[0], sizeof(tmp));
685 rwRecSetStartTime(rwrec, (file_start_time
686 + (sktime_t)GET_MASKED_BITS(tmp, 0, 22)));
687
688 if (0 == GET_MASKED_BITS(tmp, 23, 1)) {
689 /* Not TCP; protocol is in the 'proto_iflags' field */
690 rwRecMemSetProto(rwrec, &ar[4]);
691
692 } else if (ar[5] & SK_TCPSTATE_EXPANDED) {
693 /* Is TCP and have initial-flags and session-flags */
694 rwRecSetProto(rwrec, IPPROTO_TCP);
695 rwRecSetRestFlags(rwrec, GET_MASKED_BITS(tmp, 24, 8));
696 rwRecMemSetInitFlags(rwrec, &ar[4]);
697 rwRecSetFlags(rwrec,
698 (rwRecGetInitFlags(rwrec) | rwRecGetRestFlags(rwrec)));
699 } else {
700 /* Is TCP; only have combined TCP flags */
701 rwRecSetProto(rwrec, IPPROTO_TCP);
702 rwRecMemSetFlags(rwrec, &ar[4]);
703 }
704
705 rwRecMemSetTcpState(rwrec, &ar[5]);
706 }
707 #endif /* RWPACK_TIMES_FLAGS_PROTO */
708
709
710 /*
711 ** Local Variables:
712 ** mode:c
713 ** indent-tabs-mode:nil
714 ** c-basic-offset:4
715 ** End:
716 */
717