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 ** rwaugroutingio.c
11 **
12 ** routines to do io stuff with augrouting records.
13 */
14
15 #include <silk/silk.h>
16
17 RCSIDENT("$SiLK: rwaugroutingio.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
18
19 /* #define RWPACK_BYTES_PACKETS 1 */
20 #define RWPACK_FLAGS_TIMES_VOLUMES 1
21 #define RWPACK_PROTO_FLAGS 1
22 /* #define RWPACK_SBB_PEF 1 */
23 #define RWPACK_TIME_BYTES_PKTS_FLAGS 1
24 #define RWPACK_TIMES_FLAGS_PROTO 1
25 #include "skstream_priv.h"
26 #include "rwpack.c"
27
28
29 /* Version to use when SK_RECORD_VERSION_ANY is specified */
30 #define DEFAULT_RECORD_VERSION 4
31
32
33 /* ********************************************************************* */
34
35 /*
36 ** RWAUGROUTING VERSION 5
37 **
38 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
39 **
40 ** uint32_t rflag_stime; // 0- 3
41 ** // uint32_t rest_flags: 8; // is_tcp==0: Empty; else
42 ** // EXPANDED==0:Empty
43 ** // EXPANDED==1:TCPflags/!1st pkt
44 ** // uint32_t is_tcp : 1; // 1 if FLOW is TCP; 0 otherwise
45 ** // uint32_t unused : 1; // Reserved
46 ** // uint32_t stime :22; // Start time:msec offset from hour
47 **
48 ** uint8_t proto_iflags; // 4 is_tcp==0: Protocol; else:
49 ** // EXPANDED==0:TCPflags/ALL pkts
50 ** // EXPANDED==1:TCPflags/1st pkt
51 ** uint8_t tcp_state; // 5 TCP state machine info
52 ** uint16_t application; // 6- 7 Indication of type of traffic
53 **
54 ** uint16_t sPort; // 8- 9 Source port
55 ** uint16_t dPort; // 10-11 Destination port
56 **
57 ** uint32_t elapsed; // 12-15 Duration of the flow
58 **
59 ** uint32_t pkts; // 16-19 Count of packets
60 ** uint32_t bytes; // 20-23 Count of bytes
61 **
62 ** uint32_t sIP; // 24-27 Source IP
63 ** uint32_t dIP; // 28-31 Destination IP
64 **
65 ** uint32_t nhIP; // 32-35 Router Next Hop IP
66 **
67 ** uint16_t input; // 36-37 Router incoming SNMP interface
68 ** uint16_t output; // 38-39 Router outgoing SNMP interface
69 **
70 **
71 ** 40 bytes on disk.
72 */
73
74 #define RECLEN_RWAUGROUTING_V5 40
75
76
77 /*
78 * Byte swap the RWAUGROUTING v5 record 'ar' in place.
79 */
80 #define augroutingioRecordSwap_V5(ar) \
81 { \
82 SWAP_DATA32((ar) + 0); /* rflag_stime */ \
83 /* two single bytes (4)proto_iflags, (5)tcp_state */ \
84 SWAP_DATA16((ar) + 6); /* application */ \
85 SWAP_DATA16((ar) + 8); /* sPort */ \
86 SWAP_DATA16((ar) + 10); /* dPort */ \
87 SWAP_DATA32((ar) + 12); /* elapsed */ \
88 SWAP_DATA32((ar) + 16); /* pkts */ \
89 SWAP_DATA32((ar) + 20); /* bytes */ \
90 SWAP_DATA32((ar) + 24); /* sIP */ \
91 SWAP_DATA32((ar) + 28); /* dIP */ \
92 SWAP_DATA32((ar) + 32); /* nhIP */ \
93 SWAP_DATA16((ar) + 36); /* input */ \
94 SWAP_DATA16((ar) + 38); /* output */ \
95 }
96
97
98 /*
99 * Unpack the array of bytes 'ar' into a record 'rwrec'
100 */
101 static int
augroutingioRecordUnpack_V5(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)102 augroutingioRecordUnpack_V5(
103 skstream_t *stream,
104 rwGenericRec_V5 *rwrec,
105 uint8_t *ar)
106 {
107 /* swap if required */
108 if (stream->swapFlag) {
109 augroutingioRecordSwap_V5(ar);
110 }
111
112 /* Start time, TCP flags, Protocol, TCP State */
113 rwpackUnpackTimesFlagsProto(rwrec, ar, stream->hdr_starttime);
114
115 /* application */
116 rwRecMemSetApplication(rwrec, &ar[ 6]);
117
118 /* sPort, dPort */
119 rwRecMemSetSPort(rwrec, &ar[ 8]);
120 rwRecMemSetDPort(rwrec, &ar[10]);
121
122 /* Elapsed */
123 rwRecMemSetElapsed(rwrec, &ar[12]);
124
125 /* packets, bytes */
126 rwRecMemSetPkts(rwrec, &ar[16]);
127 rwRecMemSetBytes(rwrec, &ar[20]);
128
129 /* sIP, dIP */
130 rwRecMemSetSIPv4(rwrec, &ar[24]);
131 rwRecMemSetDIPv4(rwrec, &ar[28]);
132
133 /* nhIP */
134 rwRecMemSetNhIPv4(rwrec, &ar[32]);
135
136 /* input, output */
137 rwRecMemSetInput(rwrec, &ar[36]);
138 rwRecMemSetOutput(rwrec, &ar[38]);
139
140 /* sensor, flow_type from file name/header */
141 rwRecSetSensor(rwrec, stream->hdr_sensor);
142 rwRecSetFlowType(rwrec, stream->hdr_flowtype);
143
144 return SKSTREAM_OK;
145 }
146
147
148 /*
149 * Pack the record 'rwrec' into an array of bytes 'ar'
150 */
151 static int
augroutingioRecordPack_V5(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)152 augroutingioRecordPack_V5(
153 skstream_t *stream,
154 const rwGenericRec_V5 *rwrec,
155 uint8_t *ar)
156 {
157 int rv;
158
159 /* Start time, TCP Flags, Protocol, TCP State */
160 rv = rwpackPackTimesFlagsProto(rwrec, ar, stream->hdr_starttime);
161 if (rv) {
162 return rv;
163 }
164
165 /* application */
166 rwRecMemGetApplication(rwrec, &ar[6]);
167
168 /* sPort, dPort */
169 rwRecMemGetSPort(rwrec, &ar[ 8]);
170 rwRecMemGetDPort(rwrec, &ar[10]);
171
172 /* Elapsed */
173 rwRecMemGetElapsed(rwrec, &ar[12]);
174
175 /* packets, bytes */
176 rwRecMemGetPkts(rwrec, &ar[16]);
177 rwRecMemGetBytes(rwrec, &ar[20]);
178
179 /* sIP, dIP */
180 rwRecMemGetSIPv4(rwrec, &ar[24]);
181 rwRecMemGetDIPv4(rwrec, &ar[28]);
182
183 /* nhIP */
184 rwRecMemGetNhIPv4(rwrec, &ar[32]);
185
186 /* input, output */
187 rwRecMemGetInput(rwrec, &ar[36]);
188 rwRecMemGetOutput(rwrec, &ar[38]);
189
190 /* swap if required */
191 if (stream->swapFlag) {
192 augroutingioRecordSwap_V5(ar);
193 }
194
195 return SKSTREAM_OK;
196 }
197
198
199 /* ********************************************************************* */
200
201 /*
202 ** RWAUGROUTING VERSION 4
203 **
204 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
205 **
206 ** uint32_t stime_bb1; // 0- 3
207 ** // uint32_t stime :22 // Start time:msec offset from hour
208 ** // uint32_t bPPkt1 :10; // Whole bytes-per-packet (hi 10)
209 **
210 ** uint32_t bb2_elapsed; // 4- 7
211 ** // uint32_t bPPkt2 : 4; // Whole bytes-per-packet (low 4)
212 ** // uint32_t bPPFrac : 6; // Fractional bytes-per-packet
213 ** // uint32_t elapsed :22; // Duration of flow in msec
214 **
215 ** uint32_t pro_flg_pkts; // 8-11
216 ** // uint32_t prot_flags: 8; // is_tcp==0: IP protocol
217 ** // is_tcp==1 &&
218 ** // EXPANDED==0:TCPflags/All pkts
219 ** // EXPANDED==1:TCPflags/1st pkt
220 ** // uint32_t pflag : 1; // 'pkts' requires multiplier?
221 ** // uint32_t is_tcp : 1; // 1 if flow is TCP; 0 otherwise
222 ** // uint32_t padding : 2; //
223 ** // uint32_t pkts :20; // Count of packets
224 **
225 ** uint8_t tcp_state; // 12 TCP state machine info
226 ** uint8_t rest_flags; // 13 is_tcp==0: Flow's reported flags
227 ** // is_tcp==1 &&
228 ** // EXPANDED==0:Empty
229 ** // EXPANDED==1:TCPflags/!1st pkt
230 ** uint16_t application; // 14-15 Type of traffic
231 **
232 ** uint16_t sPort; // 16-17 Source port
233 ** uint16_t dPort; // 18-19 Destination port
234 **
235 ** uint16_t input; // 20-21 Router incoming SNMP interface
236 ** uint16_t output; // 22-23 Router outgoing SNMP interface
237 **
238 ** uint32_t sIP; // 24-27 Source IP
239 ** uint32_t dIP; // 28-31 Destination IP
240 **
241 ** uint32_t nhIP; // 32-35 Router Next Hop IP
242 **
243 **
244 ** 36 bytes on disk.
245 */
246
247 #define RECLEN_RWAUGROUTING_V4 36
248
249
250 /*
251 * Byte swap the RWAUGROUTING v4 record 'ar' in place.
252 */
253 #define augroutingioRecordSwap_V4(ar) \
254 { \
255 SWAP_DATA32((ar) + 0); /* stime_bb1 */ \
256 SWAP_DATA32((ar) + 4); /* bb2_elapsed */ \
257 SWAP_DATA32((ar) + 8); /* pro_flg_pkts */ \
258 /* two single bytes (12)tcp_state, (13)rest_flags */ \
259 SWAP_DATA16((ar) + 14); /* application */ \
260 SWAP_DATA16((ar) + 16); /* sPort */ \
261 SWAP_DATA16((ar) + 18); /* dPort */ \
262 SWAP_DATA16((ar) + 20); /* input */ \
263 SWAP_DATA16((ar) + 22); /* output */ \
264 SWAP_DATA32((ar) + 24); /* sIP */ \
265 SWAP_DATA32((ar) + 28); /* dIP */ \
266 SWAP_DATA32((ar) + 32); /* nhIP */ \
267 }
268
269
270 /*
271 * Unpack the array of bytes 'ar' into a record 'rwrec'
272 */
273 static int
augroutingioRecordUnpack_V4(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)274 augroutingioRecordUnpack_V4(
275 skstream_t *stream,
276 rwGenericRec_V5 *rwrec,
277 uint8_t *ar)
278 {
279 /* swap if required */
280 if (stream->swapFlag) {
281 augroutingioRecordSwap_V4(ar);
282 }
283
284 /* sTime, elapsed, pkts, bytes, proto, tcp-flags, state, application */
285 rwpackUnpackFlagsTimesVolumes(rwrec, ar, stream->hdr_starttime, 16, 0);
286
287 /* sPort, dPort */
288 rwRecMemSetSPort(rwrec, &ar[16]);
289 rwRecMemSetDPort(rwrec, &ar[18]);
290
291 /* input, output */
292 rwRecMemSetInput(rwrec, &ar[20]);
293 rwRecMemSetOutput(rwrec, &ar[22]);
294
295 /* sIP, dIP, nhIP */
296 rwRecMemSetSIPv4(rwrec, &ar[24]);
297 rwRecMemSetDIPv4(rwrec, &ar[28]);
298 rwRecMemSetNhIPv4(rwrec, &ar[32]);
299
300 /* sensor, flow_type from file name/header */
301 rwRecSetSensor(rwrec, stream->hdr_sensor);
302 rwRecSetFlowType(rwrec, stream->hdr_flowtype);
303
304 return SKSTREAM_OK;
305 }
306
307
308 /*
309 * Pack the record 'rwrec' into an array of bytes 'ar'
310 */
311 static int
augroutingioRecordPack_V4(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)312 augroutingioRecordPack_V4(
313 skstream_t *stream,
314 const rwGenericRec_V5 *rwrec,
315 uint8_t *ar)
316 {
317 int rv = SKSTREAM_OK; /* return value */
318
319 /* sTime, elapsed, pkts, bytes, proto, tcp-flags, state, application */
320 rv = rwpackPackFlagsTimesVolumes(ar, rwrec, stream->hdr_starttime, 16);
321 if (rv) {
322 return rv;
323 }
324
325 /* sPort, dPort */
326 rwRecMemGetSPort(rwrec, &ar[16]);
327 rwRecMemGetDPort(rwrec, &ar[18]);
328
329 /* input, output */
330 rwRecMemGetInput(rwrec, &ar[20]);
331 rwRecMemGetOutput(rwrec, &ar[22]);
332
333 /* sIP, dIP, nhIP */
334 rwRecMemGetSIPv4(rwrec, &ar[24]);
335 rwRecMemGetDIPv4(rwrec, &ar[28]);
336 rwRecMemGetNhIPv4(rwrec, &ar[32]);
337
338 /* swap if required */
339 if (stream->swapFlag) {
340 augroutingioRecordSwap_V4(ar);
341 }
342
343 return SKSTREAM_OK;
344 }
345
346
347 /* ********************************************************************* */
348
349 /*
350 ** RWAUGROUTING VERSION 1
351 ** RWAUGROUTING VERSION 2
352 ** RWAUGROUTING VERSION 3
353 **
354 ** in the following: EXPANDED == ((tcp_state & SK_TCPSTATE_EXPANDED) ? 1 : 0)
355 **
356 ** uint32_t sIP; // 0- 3 Source IP
357 ** uint32_t dIP; // 4- 7 Destination IP
358 **
359 ** uint16_t sPort; // 8- 9 Source port
360 ** uint16_t dPort; // 10-11 Destination port
361 **
362 ** uint32_t pkts_stime; // 12-15
363 ** // uint32_t pkts :20; // Count of packets
364 ** // uint32_t sTime :12; // Start time--offset from hour
365 **
366 ** uint32_t bbe; // 16-19
367 ** // uint32_t bPPkt :14; // Whole bytes-per-packet
368 ** // uint32_t bPPFrac : 6; // Fractional bytes-per-packet
369 ** // uint32_t elapsed :12; // Duration of flow
370 **
371 ** uint32_t msec_flags // 20-23
372 ** // uint32_t sTime_msec:10; // Fractional sTime (millisec)
373 ** // uint32_t elaps_msec:10; // Fractional elapsed (millisec)
374 ** // uint32_t pflag : 1; // 'pkts' requires multiplier?
375 ** // uint32_t is_tcp : 1; // 1 if flow is TCP; 0 otherwise
376 ** // uint32_t padding : 2; // padding/reserved
377 ** // uint32_t prot_flags: 8; // is_tcp==0: IP protocol
378 ** // is_tcp==1 &&
379 ** // EXPANDED==0:TCPflags/All pkts
380 ** // EXPANDED==1:TCPflags/1st pkt
381 **
382 ** uint16_t application; // 24-25 Type of traffic
383 **
384 ** uint8_t tcp_state; // 26 TCP state machine info
385 ** uint8_t rest_flags; // 27 is_tcp==0: Flow's reported flags
386 ** // is_tcp==1 &&
387 ** // EXPANDED==0:Empty
388 ** // EXPANDED==1:TCPflags/!1st pkt
389 **
390 ** uint32_t nhIP; // 28-31 Router Next Hop IP
391 **
392 ** uint16_t input; // 32-33 Router incoming SNMP interface
393 ** uint16_t output; // 34-35 Router outgoing SNMP interface
394 **
395 **
396 ** 36 bytes on disk.
397 */
398
399 #define RECLEN_RWAUGROUTING_V1 36
400 #define RECLEN_RWAUGROUTING_V2 36
401 #define RECLEN_RWAUGROUTING_V3 36
402
403
404 /*
405 * Byte swap the RWAUGROUTING v1 record 'ar' in place.
406 */
407 #define augroutingioRecordSwap_V1(ar) \
408 { \
409 SWAP_DATA32((ar) + 0); /* sIP */ \
410 SWAP_DATA32((ar) + 4); /* dIP */ \
411 SWAP_DATA16((ar) + 8); /* sPort */ \
412 SWAP_DATA16((ar) + 10); /* dPort */ \
413 SWAP_DATA32((ar) + 12); /* pkts_stime */ \
414 SWAP_DATA32((ar) + 16); /* bbe */ \
415 SWAP_DATA32((ar) + 20); /* msec_flags */ \
416 SWAP_DATA16((ar) + 24); /* application */ \
417 /* Two single bytes: (26)tcp_state, (27)rest_flags */ \
418 SWAP_DATA32((ar) + 28); /* nhIP */ \
419 SWAP_DATA16((ar) + 32); /* input */ \
420 SWAP_DATA16((ar) + 34); /* output */ \
421 }
422
423
424 /*
425 * Unpack the array of bytes 'ar' into a record 'rwrec'
426 */
427 static int
augroutingioRecordUnpack_V1(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)428 augroutingioRecordUnpack_V1(
429 skstream_t *stream,
430 rwGenericRec_V5 *rwrec,
431 uint8_t *ar)
432 {
433 uint32_t msec_flags;
434 uint8_t is_tcp, prot_flags;
435
436 /* swap if required */
437 if (stream->swapFlag) {
438 augroutingioRecordSwap_V1(ar);
439 }
440
441 /* sIP, dIP, sPort, dPort */
442 rwRecMemSetSIPv4(rwrec, &ar[0]);
443 rwRecMemSetDIPv4(rwrec, &ar[4]);
444 rwRecMemSetSPort(rwrec, &ar[8]);
445 rwRecMemSetDPort(rwrec, &ar[10]);
446
447 /* msec times, proto or flags */
448 memcpy(&msec_flags, &ar[20], 4);
449
450 /* application */
451 rwRecMemSetApplication(rwrec, &ar[24]);
452
453 /* sTime, pkts, bytes, elapsed, proto, tcp-flags, bpp */
454 rwpackUnpackTimeBytesPktsFlags(rwrec, stream->hdr_starttime,
455 (uint32_t*)&ar[12], (uint32_t*)&ar[16],
456 &msec_flags);
457
458 /* extra TCP information */
459 is_tcp = (uint8_t)GET_MASKED_BITS(msec_flags, 10, 1);
460 prot_flags = (uint8_t)GET_MASKED_BITS(msec_flags, 0, 8);
461 rwpackUnpackProtoFlags(rwrec, is_tcp, prot_flags, ar[26], ar[27]);
462
463 /* next hop, input & output interfaces */
464 rwRecMemSetNhIPv4(rwrec, &ar[28]);
465 rwRecMemSetInput(rwrec, &ar[32]);
466 rwRecMemSetOutput(rwrec, &ar[34]);
467
468 /* sensor, flow_type from file name/header */
469 rwRecSetSensor(rwrec, stream->hdr_sensor);
470 rwRecSetFlowType(rwrec, stream->hdr_flowtype);
471
472 return SKSTREAM_OK;
473 }
474
475
476 /*
477 * Pack the record 'rwrec' into an array of bytes 'ar'
478 */
479 static int
augroutingioRecordPack_V1(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)480 augroutingioRecordPack_V1(
481 skstream_t *stream,
482 const rwGenericRec_V5 *rwrec,
483 uint8_t *ar)
484 {
485 int rv = SKSTREAM_OK; /* return value */
486 uint32_t msec_flags;
487 uint8_t is_tcp, prot_flags;
488
489 /* sTime, pkts, bytes, elapsed, proto, tcp-flags, bpp */
490 rv = rwpackPackTimeBytesPktsFlags((uint32_t*)&ar[12], (uint32_t*)&ar[16],
491 &msec_flags,
492 rwrec, stream->hdr_starttime);
493 if (rv) {
494 return rv;
495 }
496
497 rwpackPackProtoFlags(&is_tcp, &prot_flags, &ar[26], &ar[27], rwrec);
498
499 /* msec_flags: sTime_msec:10; elaps_msec:10; pflag:1;
500 * is_tcp:1; pad:2; prot_flags:8; */
501 /* overwrite the least significant 11 bits */
502 msec_flags = ((msec_flags & (MASKARRAY_21 << 11))
503 | (is_tcp ? (1 << 10) : 0)
504 | prot_flags);
505
506 /* sIP, dIP, sPort, dPort */
507 rwRecMemGetSIPv4(rwrec, &ar[0]);
508 rwRecMemGetDIPv4(rwrec, &ar[4]);
509 rwRecMemGetSPort(rwrec, &ar[8]);
510 rwRecMemGetDPort(rwrec, &ar[10]);
511
512 /* msec_flags */
513 memcpy(&ar[20], &msec_flags, 4);
514
515 /* application */
516 rwRecMemGetApplication(rwrec, &ar[24]);
517
518 /* next hop, input & output interfaces */
519 rwRecMemGetNhIPv4(rwrec, &ar[28]);
520 rwRecMemGetInput(rwrec, &ar[32]);
521 rwRecMemGetOutput(rwrec, &ar[34]);
522
523 /* swap if required */
524 if (stream->swapFlag) {
525 augroutingioRecordSwap_V1(ar);
526 }
527
528 return SKSTREAM_OK;
529 }
530
531
532 /* ********************************************************************* */
533
534 /*
535 * Return length of record of specified version, or 0 if no such
536 * version exists. See skstream_priv.h for details.
537 */
538 uint16_t
augroutingioGetRecLen(sk_file_version_t vers)539 augroutingioGetRecLen(
540 sk_file_version_t vers)
541 {
542 switch (vers) {
543 case 1:
544 return RECLEN_RWAUGROUTING_V1;
545 case 2:
546 return RECLEN_RWAUGROUTING_V2;
547 case 3:
548 return RECLEN_RWAUGROUTING_V3;
549 case 4:
550 return RECLEN_RWAUGROUTING_V4;
551 case 5:
552 return RECLEN_RWAUGROUTING_V5;
553 default:
554 return 0;
555 }
556 }
557
558
559 /*
560 * status = augroutingioPrepare(&stream);
561 *
562 * Sets the record version to the default if it is unspecified,
563 * checks that the record format supports the requested record
564 * version, sets the record length, and sets the pack and unpack
565 * functions for this record format and version.
566 */
567 int
augroutingioPrepare(skstream_t * stream)568 augroutingioPrepare(
569 skstream_t *stream)
570 {
571 #define FILE_FORMAT "FT_RWAUGROUTING"
572 sk_file_header_t *hdr = stream->silk_hdr;
573 int rv = SKSTREAM_OK; /* return value */
574
575 assert(skHeaderGetFileFormat(hdr) == FT_RWAUGROUTING);
576
577 /* Set version if none was selected by caller */
578 if ((stream->io_mode == SK_IO_WRITE)
579 && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
580 {
581 skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
582 }
583
584 /* version check; set values based on version */
585 switch (skHeaderGetRecordVersion(hdr)) {
586 case 5:
587 stream->rwUnpackFn = &augroutingioRecordUnpack_V5;
588 stream->rwPackFn = &augroutingioRecordPack_V5;
589 break;
590 case 4:
591 stream->rwUnpackFn = &augroutingioRecordUnpack_V4;
592 stream->rwPackFn = &augroutingioRecordPack_V4;
593 break;
594 case 3:
595 case 2:
596 case 1:
597 /* V1 and V2 differ only in the padding of the header */
598 /* V2 and V3 differ only in that V3 supports compression on
599 * read and write; V2 supports compression only on read */
600 stream->rwUnpackFn = &augroutingioRecordUnpack_V1;
601 stream->rwPackFn = &augroutingioRecordPack_V1;
602 break;
603 case 0:
604 default:
605 rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
606 goto END;
607 }
608
609 stream->recLen = augroutingioGetRecLen(skHeaderGetRecordVersion(hdr));
610
611 /* verify lengths */
612 if (stream->recLen == 0) {
613 skAppPrintErr("Record length not set for %s version %u",
614 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
615 skAbort();
616 }
617 if (stream->recLen != skHeaderGetRecordLength(hdr)) {
618 if (0 == skHeaderGetRecordLength(hdr)) {
619 skHeaderSetRecordLength(hdr, stream->recLen);
620 } else {
621 skAppPrintErr(("Record length mismatch for %s version %u\n"
622 "\tcode = %" PRIu16 " bytes; header = %lu bytes"),
623 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
624 stream->recLen,
625 (unsigned long)skHeaderGetRecordLength(hdr));
626 skAbort();
627 }
628 }
629
630 END:
631 return rv;
632 }
633
634
635 /*
636 ** Local Variables:
637 ** mode:c
638 ** indent-tabs-mode:nil
639 ** c-basic-offset:4
640 ** End:
641 */
642