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