1 /*
2 ** Copyright (C) 2001-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 ** rwipv6routingio.c
11 **
12 ** Routines to pack/unpack FT_RWIPV6ROUTING records.
13 */
14
15 #include <silk/silk.h>
16
17 RCSIDENT("$SiLK: rwipv6routingio.c ef14e54179be 2020-04-14 21:57:45Z mthomas $");
18
19 #include "skstream_priv.h"
20
21
22 /* Version to use when SK_RECORD_VERSION_ANY is specified */
23 #define DEFAULT_RECORD_VERSION 1
24
25
26 /* LOCAL FUNCTION PROTOTYPES */
27
28 static int
29 ipv6routingioRecordUnpack_V1(
30 skstream_t *stream,
31 rwGenericRec_V5 *rwrec,
32 uint8_t *ar);
33
34
35 static const uint8_t IP4in6_prefix[12] =
36 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
37
38
39 /* ********************************************************************* */
40
41 /*
42 ** RWIPV6ROUTING VERSION 3
43 **
44 ** int64_t sTime; // 0- 7 Flow start time as milliseconds
45 ** // since UNIX epoch
46 **
47 ** uint32_t elapsed; // 8-11 Duration of flow in milliseconds
48 ** // (Allows for a 49 day flow)
49 **
50 ** uint16_t sPort; // 12-13 Source port
51 ** uint16_t dPort; // 14-15 Destination port
52 **
53 ** uint8_t proto; // 16 IP protocol
54 ** uint8_t flow_type; // 17 Class & Type info
55 ** uint16_t sID; // 18-19 Sensor ID
56 **
57 ** uint8_t flags; // 20 OR of all flags (Netflow flags)
58 ** uint8_t init_flags; // 21 TCP flags in first packet
59 ** // or blank for "legacy" data
60 ** uint8_t rest_flags; // 22 TCP flags on non-initial packet
61 ** // or blank for "legacy" data
62 ** uint8_t tcp_state; // 23 TCP state machine info (below)
63 **
64 ** uint16_t application; // 24-25 Indication of type of traffic
65 ** uint16_t memo; // 26-27 Application specific field
66 **
67 ** uint32_t input; // 28-31 Router incoming SNMP interface
68 **
69 ** uint64_t pkts; // 32-39 Count of packets
70 **
71 ** uint64_t bytes; // 40-47 Count of bytes
72 **
73 ** uint8_t[16] sIP; // 48-63 (IPv4 in 60-63) Source IP
74 ** uint8_t[16] dIP; // 64-79 (IPv4 in 76-79) Destination IP
75 ** uint8_t[16] nhIP; // 80-95 (IPv4 in 92-95) Router Next Hop IP
76 **
77 ** uint32_t output; // 96-99 Router outgoing SNMP interface
78 **
79 **
80 ** 100 bytes on disk.
81 */
82
83 #define RECLEN_RWIPV6ROUTING_V3 100
84
85
86 /*
87 * Byte swap the RWIPV6ROUTING v1 record 'ar' in place.
88 */
89 #define ipv6routingioRecordSwap_V3(ar) \
90 { \
91 SWAP_DATA64((ar) + 0); /* sTime */ \
92 SWAP_DATA32((ar) + 8); /* elapsed */ \
93 SWAP_DATA16((ar) + 12); /* sPort */ \
94 SWAP_DATA16((ar) + 14); /* dPort */ \
95 /* Two single bytes: (16)proto, (17)flow_type */ \
96 SWAP_DATA16((ar) + 18); /* sID */ \
97 /* Four single bytes: (20)flags, (21)init_flags, \
98 * (22)rest_flags, (23)tcp_state */ \
99 SWAP_DATA16((ar) + 24); /* application */ \
100 SWAP_DATA16((ar) + 26); /* memo */ \
101 SWAP_DATA32((ar) + 28); /* input */ \
102 SWAP_DATA64((ar) + 32); /* pkts */ \
103 SWAP_DATA64((ar) + 40); /* bytes */ \
104 /* 48 bytes of sIP, dIP, nhIP always in network byte order */ \
105 SWAP_DATA32((ar) + 96); /* output */ \
106 }
107
108
109 /*
110 * Unpack the array of bytes 'ar' into a record 'rwrec'
111 */
112 static int
ipv6routingioRecordUnpack_V3(skstream_t * stream,rwRec * rwrec,uint8_t * ar)113 ipv6routingioRecordUnpack_V3(
114 skstream_t *stream,
115 rwRec *rwrec,
116 uint8_t *ar)
117 {
118 uint32_t u32;
119 uint64_t u64;
120
121 #if !SK_ENABLE_IPV6
122 if (ar[23] & 0x80) {
123 /* Record is IPv6 */
124 return SKSTREAM_ERR_UNSUPPORT_IPV6;
125 }
126 #endif
127
128 /* swap if required */
129 if (stream->swapFlag) {
130 ipv6routingioRecordSwap_V3(ar);
131 }
132
133 rwRecMemSetStartTime(rwrec, &ar[0]);
134 rwRecMemSetElapsed(rwrec, &ar[8]);
135 rwRecMemSetSPort(rwrec, &ar[12]);
136 rwRecMemSetDPort(rwrec, &ar[14]);
137 rwRecMemSetProto(rwrec, &ar[16]);
138 rwRecMemSetFlowType(rwrec, &ar[17]);
139 rwRecMemSetSensor(rwrec, &ar[18]);
140 rwRecMemSetFlags(rwrec, &ar[20]);
141 rwRecMemSetInitFlags(rwrec, &ar[21]);
142 rwRecMemSetRestFlags(rwrec, &ar[22]);
143 rwRecMemSetTcpState(rwrec, &ar[23]);
144 rwRecMemSetApplication(rwrec, &ar[24]);
145 rwRecMemSetMemo(rwrec, &ar[26]);
146
147 /* Input; set to UINT16_MAX if too large */
148 memcpy(&u32, &ar[28], sizeof(u32));
149 if (u32 > UINT16_MAX) {
150 rwRecSetInput(rwrec, UINT16_MAX);
151 } else {
152 rwRecSetInput(rwrec, (uint16_t)u32);
153 }
154
155 /* Packets; set to UINT32_MAX if too large */
156 memcpy(&u64, &ar[32], sizeof(u64));
157 if (u64 > UINT32_MAX) {
158 rwRecSetPkts(rwrec, UINT32_MAX);
159 } else {
160 rwRecSetPkts(rwrec, (uint32_t)u64);
161 }
162
163 /* Bytes; set to UINT32_MAX if too large */
164 memcpy(&u64, &ar[40], sizeof(u64));
165 if (u64 > UINT32_MAX) {
166 rwRecSetBytes(rwrec, UINT32_MAX);
167 } else {
168 rwRecSetBytes(rwrec, (uint32_t)u64);
169 }
170
171 /* Output; set to UINT16_MAX if too large */
172 memcpy(&u32, &ar[96], sizeof(u32));
173 if (u32 > UINT16_MAX) {
174 rwRecSetOutput(rwrec, UINT16_MAX);
175 } else {
176 rwRecSetOutput(rwrec, (uint16_t)u32);
177 }
178
179 #if SK_ENABLE_IPV6
180 if (ar[23] & 0x80) {
181 /* Record is IPv6 */
182 rwRecSetIPv6(rwrec);
183 rwRecMemSetSIPv6(rwrec, &ar[48]);
184 rwRecMemSetDIPv6(rwrec, &ar[64]);
185 rwRecMemSetNhIPv6(rwrec, &ar[80]);
186 } else
187 #endif /* SK_ENABLE_IPV6 */
188 {
189 /* Record is IPv4, but data encoded as IPv6 */
190 uint32_t ip;
191
192 /* sIP */
193 memcpy(&ip, &ar[60], sizeof(ip));
194 rwRecSetSIPv4(rwrec, ntohl(ip));
195
196 /* dIP */
197 memcpy(&ip, &ar[76], sizeof(ip));
198 rwRecSetDIPv4(rwrec, ntohl(ip));
199
200 /* nhIP */
201 memcpy(&ip, &ar[92], sizeof(ip));
202 rwRecSetNhIPv4(rwrec, ntohl(ip));
203 }
204
205 /*
206 * No need for this; file format is post SiLK-3.6.0
207 * RWREC_MAYBE_CLEAR_TCPSTATE_EXPANDED(rwrec);
208 */
209
210 return SKSTREAM_OK;
211 }
212
213
214 /*
215 * Pack the record 'rwrec' into an array of bytes 'ar'
216 */
217 static int
ipv6routingioRecordPack_V3(skstream_t * stream,const rwRec * rwrec,uint8_t * ar)218 ipv6routingioRecordPack_V3(
219 skstream_t *stream,
220 const rwRec *rwrec,
221 uint8_t *ar)
222 {
223 uint32_t u32;
224 uint64_t u64;
225
226 rwRecMemGetStartTime(rwrec, &ar[0]);
227 rwRecMemGetElapsed(rwrec, &ar[8]);
228 rwRecMemGetSPort(rwrec, &ar[12]);
229 rwRecMemGetDPort(rwrec, &ar[14]);
230 rwRecMemGetProto(rwrec, &ar[16]);
231 rwRecMemGetFlowType(rwrec, &ar[17]);
232 rwRecMemGetSensor(rwrec, &ar[18]);
233 rwRecMemGetFlags(rwrec, &ar[20]);
234 rwRecMemGetInitFlags(rwrec, &ar[21]);
235 rwRecMemGetRestFlags(rwrec, &ar[22]);
236 rwRecMemGetTcpState(rwrec, &ar[23]);
237 rwRecMemGetApplication(rwrec, &ar[24]);
238 rwRecMemGetMemo(rwrec, &ar[26]);
239
240 u32 = rwRecGetInput(rwrec);
241 memcpy(&ar[28], &u32, sizeof(u32));
242
243 u64 = rwRecGetPkts(rwrec);
244 memcpy(&ar[32], &u64, sizeof(u64));
245
246 u64 = rwRecGetBytes(rwrec);
247 memcpy(&ar[40], &u64, sizeof(u64));
248
249 u32 = rwRecGetOutput(rwrec);
250 memcpy(&ar[96], &u32, sizeof(u32));
251
252 if (rwRecIsIPv6(rwrec)) {
253 /* Record is IPv6 */
254 #if !SK_ENABLE_IPV6
255 return SKSTREAM_ERR_UNSUPPORT_IPV6;
256 #else
257 ar[23] |= 0x80;
258 rwRecMemGetSIPv6(rwrec, &ar[48]);
259 rwRecMemGetDIPv6(rwrec, &ar[64]);
260 rwRecMemGetNhIPv6(rwrec, &ar[80]);
261 #endif /* SK_ENABLE_IPV6 */
262 } else {
263 /* Record is IPv4, but encode as IPv6 */
264 uint32_t ip;
265
266 /* sIP */
267 ip = htonl(rwRecGetSIPv4(rwrec));
268 memcpy(&ar[48], IP4in6_prefix, sizeof(IP4in6_prefix));
269 memcpy(&ar[60], &ip, sizeof(ip));
270
271 /* dIP */
272 ip = htonl(rwRecGetDIPv4(rwrec));
273 memcpy(&ar[64], IP4in6_prefix, sizeof(IP4in6_prefix));
274 memcpy(&ar[76], &ip, sizeof(ip));
275
276 /* nhIP */
277 ip = htonl(rwRecGetNhIPv4(rwrec));
278 memcpy(&ar[80], IP4in6_prefix, sizeof(IP4in6_prefix));
279 memcpy(&ar[92], &ip, sizeof(ip));
280 }
281
282 /* swap if required */
283 if (stream->swapFlag) {
284 ipv6routingioRecordSwap_V3(ar);
285 }
286
287 return SKSTREAM_OK;
288 }
289
290
291 /* ********************************************************************* */
292
293 /*
294 ** RWIPV6ROUTING VERSION 2
295 **
296 ** FT_RWIPV6ROUTING version 2 is identical to V1, expect must clear
297 ** the application field when unpacking. Packing functions for V1
298 ** and V2 are identical.
299 */
300
301 static int
ipv6routingioRecordUnpack_V2(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)302 ipv6routingioRecordUnpack_V2(
303 skstream_t *stream,
304 rwGenericRec_V5 *rwrec,
305 uint8_t *ar)
306 {
307 int rv;
308
309 rv = ipv6routingioRecordUnpack_V1(stream, rwrec, ar);
310 rwRecSetApplication(rwrec, 0);
311 return rv;
312 }
313
314
315 /* ********************************************************************* */
316
317 /*
318 ** RWIPV6ROUTING VERSION 1
319 **
320 ** int64_t sTime; // 0- 7 Flow start time as milliseconds
321 ** // since UNIX epoch
322 **
323 ** uint32_t elapsed; // 8-11 Duration of flow in milliseconds
324 ** // (Allows for a 49 day flow)
325 **
326 ** uint16_t sPort; // 12-13 Source port
327 ** uint16_t dPort; // 14-15 Destination port
328 **
329 ** uint8_t proto; // 16 IP protocol
330 ** uint8_t flow_type; // 17 Class & Type info
331 ** uint16_t sID; // 18-19 Sensor ID
332 **
333 ** uint8_t flags; // 20 OR of all flags (Netflow flags)
334 ** uint8_t init_flags; // 21 TCP flags in first packet
335 ** // or blank for "legacy" data
336 ** uint8_t rest_flags; // 22 TCP flags on non-initial packet
337 ** // or blank for "legacy" data
338 ** uint8_t tcp_state; // 23 TCP state machine info (below)
339 **
340 ** uint16_t application; // 24-25 Indication of type of traffic
341 ** uint16_t memo; // 26-27 Application specific field
342 **
343 ** uint16_t input; // 28-29 Router incoming SNMP interface
344 ** uint16_t output; // 30-31 Router outgoing SNMP interface
345 **
346 ** uint32_t pkts; // 32-35 Count of packets
347 ** uint32_t bytes; // 36-39 Count of bytes
348 **
349 ** uint8_t[16] sIP; // 40-55 Source IP
350 ** uint8_t[16] dIP; // 56-71 Destination IP
351 ** uint8_t[16] nhIP; // 72-87 Router Next Hop IP
352 **
353 **
354 ** 88 bytes on disk.
355 */
356
357 #define RECLEN_RWIPV6ROUTING_V1 88
358
359
360 /*
361 * Byte swap the RWIPV6ROUTING v1 record 'ar' in place.
362 */
363 #define ipv6routingioRecordSwap_V1(ar) \
364 { \
365 SWAP_DATA64((ar) + 0); /* sTime */ \
366 SWAP_DATA32((ar) + 8); /* elapsed */ \
367 SWAP_DATA16((ar) + 12); /* sPort */ \
368 SWAP_DATA16((ar) + 14); /* dPort */ \
369 /* Two single bytes: (16)proto, (17)flow_type */ \
370 SWAP_DATA16((ar) + 18); /* sID */ \
371 /* Four single bytes: (20)flags, (21)init_flags, \
372 * (22)rest_flags, (23)tcp_state */ \
373 SWAP_DATA16((ar) + 24); /* application */ \
374 SWAP_DATA16((ar) + 26); /* memo */ \
375 SWAP_DATA16((ar) + 28); /* input */ \
376 SWAP_DATA16((ar) + 30); /* output */ \
377 SWAP_DATA32((ar) + 32); /* pkts */ \
378 SWAP_DATA32((ar) + 36); /* bytes */ \
379 /* 48 bytes of sIP, dIP, nhIP always in network byte order */ \
380 }
381
382
383 /*
384 * Unpack the array of bytes 'ar' into a record 'rwrec'
385 */
386 static int
ipv6routingioRecordUnpack_V1(skstream_t * stream,rwGenericRec_V5 * rwrec,uint8_t * ar)387 ipv6routingioRecordUnpack_V1(
388 skstream_t *stream,
389 rwGenericRec_V5 *rwrec,
390 uint8_t *ar)
391 {
392 uint32_t ip;
393
394 /* swap if required */
395 if (stream->swapFlag) {
396 ipv6routingioRecordSwap_V1(ar);
397 }
398
399 rwRecMemSetStartTime(rwrec, &ar[0]);
400 rwRecMemSetElapsed(rwrec, &ar[8]);
401 rwRecMemSetSPort(rwrec, &ar[12]);
402 rwRecMemSetDPort(rwrec, &ar[14]);
403 rwRecMemSetProto(rwrec, &ar[16]);
404 rwRecMemSetFlowType(rwrec, &ar[17]);
405 rwRecMemSetSensor(rwrec, &ar[18]);
406 rwRecMemSetFlags(rwrec, &ar[20]);
407 rwRecMemSetInitFlags(rwrec, &ar[21]);
408 rwRecMemSetRestFlags(rwrec, &ar[22]);
409 rwRecMemSetTcpState(rwrec, &ar[23]);
410 rwRecMemSetApplication(rwrec, &ar[24]);
411 rwRecMemSetMemo(rwrec, &ar[26]);
412 rwRecMemSetInput(rwrec, &ar[28]);
413 rwRecMemSetOutput(rwrec, &ar[30]);
414 rwRecMemSetPkts(rwrec, &ar[32]);
415 rwRecMemSetBytes(rwrec, &ar[36]);
416
417 if (ar[23] & 0x80) {
418 /* Record is IPv6 */
419 #if !SK_ENABLE_IPV6
420 return SKSTREAM_ERR_UNSUPPORT_IPV6;
421 #else
422 rwRecSetIPv6(rwrec);
423 rwRecMemSetSIPv6(rwrec, &ar[40]);
424 rwRecMemSetDIPv6(rwrec, &ar[56]);
425 rwRecMemSetNhIPv6(rwrec, &ar[72]);
426 #endif /* SK_ENABLE_IPV6 */
427 } else {
428 /* Record is IPv4 */
429
430 /* sIP */
431 memcpy(&ip, &ar[52], sizeof(ip));
432 rwRecSetSIPv4(rwrec, ntohl(ip));
433
434 /* dIP */
435 memcpy(&ip, &ar[68], sizeof(ip));
436 rwRecSetDIPv4(rwrec, ntohl(ip));
437
438 /* nhIP */
439 memcpy(&ip, &ar[84], sizeof(ip));
440 rwRecSetNhIPv4(rwrec, ntohl(ip));
441 }
442
443 RWREC_MAYBE_CLEAR_TCPSTATE_EXPANDED(rwrec);
444
445 return SKSTREAM_OK;
446 }
447
448
449 /*
450 * Pack the record 'rwrec' into an array of bytes 'ar'
451 */
452 static int
ipv6routingioRecordPack_V1(skstream_t * stream,const rwGenericRec_V5 * rwrec,uint8_t * ar)453 ipv6routingioRecordPack_V1(
454 skstream_t *stream,
455 const rwGenericRec_V5 *rwrec,
456 uint8_t *ar)
457 {
458 uint32_t ip;
459
460 rwRecMemGetStartTime(rwrec, &ar[0]);
461 rwRecMemGetElapsed(rwrec, &ar[8]);
462 rwRecMemGetSPort(rwrec, &ar[12]);
463 rwRecMemGetDPort(rwrec, &ar[14]);
464 rwRecMemGetProto(rwrec, &ar[16]);
465 rwRecMemGetFlowType(rwrec, &ar[17]);
466 rwRecMemGetSensor(rwrec, &ar[18]);
467 rwRecMemGetFlags(rwrec, &ar[20]);
468 rwRecMemGetInitFlags(rwrec, &ar[21]);
469 rwRecMemGetRestFlags(rwrec, &ar[22]);
470 rwRecMemGetTcpState(rwrec, &ar[23]);
471 rwRecMemGetApplication(rwrec, &ar[24]);
472 rwRecMemGetMemo(rwrec, &ar[26]);
473 rwRecMemGetInput(rwrec, &ar[28]);
474 rwRecMemGetOutput(rwrec, &ar[30]);
475 rwRecMemGetPkts(rwrec, &ar[32]);
476 rwRecMemGetBytes(rwrec, &ar[36]);
477
478 if (rwRecIsIPv6(rwrec)) {
479 /* Record is IPv6 */
480 #if !SK_ENABLE_IPV6
481 return SKSTREAM_ERR_UNSUPPORT_IPV6;
482 #else
483 ar[23] |= 0x80;
484 rwRecMemGetSIPv6(rwrec, &ar[40]);
485 rwRecMemGetDIPv6(rwrec, &ar[56]);
486 rwRecMemGetNhIPv6(rwrec, &ar[72]);
487 #endif /* SK_ENABLE_IPV6 */
488 } else {
489 /* Record is IPv4, but encode as IPv6 */
490
491 /* sIP */
492 ip = htonl(rwRecGetSIPv4(rwrec));
493 memcpy(&ar[40], IP4in6_prefix, sizeof(IP4in6_prefix));
494 memcpy(&ar[52], &ip, sizeof(ip));
495
496 /* dIP */
497 ip = htonl(rwRecGetDIPv4(rwrec));
498 memcpy(&ar[56], IP4in6_prefix, sizeof(IP4in6_prefix));
499 memcpy(&ar[68], &ip, sizeof(ip));
500
501 /* nhIP */
502 ip = htonl(rwRecGetNhIPv4(rwrec));
503 memcpy(&ar[72], IP4in6_prefix, sizeof(IP4in6_prefix));
504 memcpy(&ar[84], &ip, sizeof(ip));
505 }
506
507 /* swap if required */
508 if (stream->swapFlag) {
509 ipv6routingioRecordSwap_V1(ar);
510 }
511
512 return SKSTREAM_OK;
513 }
514
515
516 /* ********************************************************************* */
517
518 /*
519 * Return length of record of specified version, or 0 if no such
520 * version exists. See skstream_priv.h for details.
521 */
522 uint16_t
ipv6routingioGetRecLen(sk_file_version_t vers)523 ipv6routingioGetRecLen(
524 sk_file_version_t vers)
525 {
526 switch (vers) {
527 case 1:
528 case 2:
529 return RECLEN_RWIPV6ROUTING_V1;
530 case 3:
531 return RECLEN_RWIPV6ROUTING_V3;
532 default:
533 return 0;
534 }
535 }
536
537
538 /*
539 * status = ipv6routingioPrepare(stream);
540 *
541 * Sets the record version to the default if it is unspecified,
542 * checks that the record format supports the requested record
543 * version, sets the record length, and sets the pack and unpack
544 * functions for this record format and version.
545 */
546 int
ipv6routingioPrepare(skstream_t * stream)547 ipv6routingioPrepare(
548 skstream_t *stream)
549 {
550 #define FILE_FORMAT "FT_RWIPV6ROUTING"
551 sk_file_header_t *hdr = stream->silk_hdr;
552 int rv = SKSTREAM_OK; /* return value */
553
554 /* Set version if none was selected by caller */
555 if ((stream->io_mode == SK_IO_WRITE)
556 && (skHeaderGetRecordVersion(hdr) == SK_RECORD_VERSION_ANY))
557 {
558 skHeaderSetRecordVersion(hdr, DEFAULT_RECORD_VERSION);
559 }
560
561 /* version check; set values based on version */
562 switch (skHeaderGetRecordVersion(hdr)) {
563 case 3:
564 stream->rwUnpackFn = &ipv6routingioRecordUnpack_V3;
565 stream->rwPackFn = &ipv6routingioRecordPack_V3;
566 break;
567 case 2:
568 stream->rwUnpackFn = &ipv6routingioRecordUnpack_V2;
569 stream->rwPackFn = &ipv6routingioRecordPack_V1;
570 break;
571 case 1:
572 stream->rwUnpackFn = &ipv6routingioRecordUnpack_V1;
573 stream->rwPackFn = &ipv6routingioRecordPack_V1;
574 break;
575 case 0:
576 default:
577 rv = SKSTREAM_ERR_UNSUPPORT_VERSION;
578 goto END;
579 }
580
581 stream->recLen = ipv6routingioGetRecLen(skHeaderGetRecordVersion(hdr));
582
583 /* verify lengths */
584 if (stream->recLen == 0) {
585 skAppPrintErr("Record length not set for %s version %u",
586 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr));
587 skAbort();
588 }
589 if (stream->recLen != skHeaderGetRecordLength(hdr)) {
590 if (0 == skHeaderGetRecordLength(hdr)) {
591 skHeaderSetRecordLength(hdr, stream->recLen);
592 } else {
593 skAppPrintErr(("Record length mismatch for %s version %u\n"
594 "\tcode = %" PRIu16 " bytes; header = %lu bytes"),
595 FILE_FORMAT, (unsigned)skHeaderGetRecordVersion(hdr),
596 stream->recLen,
597 (unsigned long)skHeaderGetRecordLength(hdr));
598 skAbort();
599 }
600 }
601
602 END:
603 return rv;
604 }
605
606
607 /*
608 ** Local Variables:
609 ** mode:c
610 ** indent-tabs-mode:nil
611 ** c-basic-offset:4
612 ** End:
613 */
614