1 /*
2  * k12.c
3  *
4  *  routines for importing tektronix k12xx *.rf5 files
5  *
6  *  Copyright (c) 2005, Luis E. Garia Ontanon <luis@ontanon.org>
7  *
8  * Wiretap Library
9  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
10  *
11  * SPDX-License-Identifier: GPL-2.0-or-later
12  */
13 
14 #include "config.h"
15 #include <stdlib.h>
16 #include <string.h>
17 #include <errno.h>
18 
19 #include "wtap-int.h"
20 #include "file_wrappers.h"
21 #include "k12.h"
22 
23 #include <wsutil/str_util.h>
24 #include <wsutil/glib-compat.h>
25 
26 /*
27  * See
28  *
29  *  https://www.tek.com/manual/record-file-api-programmer-manual
30  *
31  * for some information about the file format.  You may have to fill in
32  * a form to download the document ("Record File API Programmer Manual").
33  *
34  * Unfortunately, it describes an API that delivers records from an rf5
35  * file, not the raw format of an rf5 file, so, while it gives the formats
36  * of the records with various types, it does not indicate how those records
37  * are stored in the file.
38  */
39 
40 static int k12_file_type_subtype = -1;
41 
42 void register_k12(void);
43 
44 /* #define DEBUG_K12 */
45 #ifdef DEBUG_K12
46 #include <stdio.h>
47 #include <stdarg.h>
48 #include <wsutil/file_util.h>
49 
50 FILE* dbg_out = NULL;
51 char* env_file = NULL;
52 
53 static unsigned int debug_level = 0;
54 
k12_fprintf(const char * fmt,...)55 void k12_fprintf(const char* fmt, ...) {
56     va_list ap;
57 
58     va_start(ap,fmt);
59     vfprintf(dbg_out, fmt, ap);
60     va_end(ap);
61 }
62 
63 #define CAT(a,b) a##b
64 #define K12_DBG(level,args) do { if (level <= debug_level) { \
65             fprintf(dbg_out,"%s:%d: ",CAT(__FI,LE__),CAT(__LI,NE__));   \
66             k12_fprintf args ;                                          \
67             fprintf(dbg_out,"\n");                                      \
68 } } while(0)
69 
k12_hex_ascii_dump(guint level,gint64 offset,const char * label,const unsigned char * b,unsigned int len)70 void k12_hex_ascii_dump(guint level, gint64 offset, const char* label, const unsigned char* b, unsigned int len) {
71     static const char* c2t[] = {
72         "00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
73         "10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
74         "20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
75         "30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
76         "40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
77         "50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
78         "60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
79         "70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
80         "80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
81         "90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
82         "a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
83         "b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
84         "c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
85         "d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
86         "e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
87         "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff"
88     };
89     unsigned int i, j;
90 
91     if (debug_level < level) return;
92 
93     fprintf(dbg_out,"%s(%.8" G_GINT64_MODIFIER "x,%.4x):\n",label,offset,len);
94 
95     for (i=0 ; i<len ; i += 16) {
96         for (j=0; j<16; j++) {
97             if ((j%4)==0)
98                 fprintf(dbg_out," ");
99             if ((i+j)<len)
100                 fprintf(dbg_out, "%s", c2t[b[i+j]]);
101             else
102                 fprintf(dbg_out, "  ");
103         }
104         fprintf(dbg_out, "    ");
105         for (j=0; j<16; j++) {
106             if ((i+j)<len)
107                 fprintf(dbg_out, "%c", g_ascii_isprint(b[i+j]) ? b[i+j] : '.');
108         }
109         fprintf(dbg_out,"\n");
110     }
111 }
112 
113 #define K12_HEX_ASCII_DUMP(x,a,b,c,d) k12_hex_ascii_dump(x,a,b,c,d)
114 
k12_ascii_dump(guint level,guint8 * buf,guint32 len,guint32 buf_offset)115 void k12_ascii_dump(guint level, guint8 *buf, guint32 len, guint32 buf_offset) {
116     guint32 i;
117 
118     if (debug_level < level) return;
119 
120     for (i = buf_offset; i < len; i++) {
121         if (g_ascii_isprint(buf[i]) || buf[i] == '\n' || buf[i] == '\t')
122             putc(buf[i], dbg_out);
123         else if (buf[i] == '\0')
124             fprintf(dbg_out, "(NUL)\n");
125     }
126 }
127 
128 #define K12_ASCII_DUMP(x,a,b,c) k12_ascii_dump(x,a,b,c)
129 
130 #else
131 #define K12_DBG(level,args) (void)0
132 #define K12_HEX_ASCII_DUMP(x,a,b,c,d)
133 #define K12_ASCII_DUMP(x,a,b,c)
134 #endif
135 
136 
137 
138 /*
139  * A 32-bit .rf5 file begins with a 512-byte file header, containing:
140  *
141  *  a 32-bit big-endian file header length, in bytes - always 512 in
142  *  the files we've seen;
143  *
144  *  4 unknown bytes, always 0x12 0x05 0x00 0x10;
145  *
146  *  a 32-bit big-endian file length, giving the total length of the file,
147  *  in bytes;
148  *
149  *  a 32-bit big-endian number giving the "page size" of the file, in
150  *  bytes, which is normally 8192;
151  *
152  *  20 unknown bytes;
153  *
154  *  a 32-bit count of the number of records in the file;
155  *
156  *  4 unknown bytes;
157  *
158  *  a 32-bit count of the number of records in the file;
159  *
160  *  464 unknown bytes;
161  *
162  * followed by a sequence of records containing:
163  *
164  *  a 32-bit big-endian record length;
165  *
166  *  a 32-bit big-endian record type;
167  *
168  *  a 32-bit big-endian frame length;
169  *
170  *  a 32-bit big-endian source ID.
171  *
172  * Every 8192 bytes, starting immediately after the 512-byte header,
173  * there's a 16-byte blob; it's not part of the record data.
174  * There's no obvious pattern to the data; it might be junk left
175  * in memory as the file was being written.
176  *
177  * There's a 16-bit terminator FFFF at the end.
178  *
179  * Older versions of the Wireshark .rf5 writing code incorrectly wrote
180  * the header - they put 512 in the file length field (counting only the
181  * header), put a count of records into the "page size" field, and wrote
182  * out zeroes in the rest of the header.  We detect those files by
183  * checking whether the rest of the header is zero.
184  */
185 
186 /*
187  * We use the first 8 bytes of the file header as a magic number.
188  */
189 static const guint8 k12_file_magic[] = { 0x00, 0x00, 0x02, 0x00 ,0x12, 0x05, 0x00, 0x10 };
190 
191 #define K12_FILE_HDR_LEN      512
192 
193 /*
194  * Offsets in the file header.
195  */
196 #define K12_FILE_HDR_MAGIC_NUMBER   0x00
197 #define K12_FILE_HDR_FILE_SIZE      0x08
198 #define K12_FILE_HDR_PAGE_SIZE      0x0C
199 #define K12_FILE_HDR_RECORD_COUNT_1 0x24
200 #define K12_FILE_HDR_RECORD_COUNT_2 0x2C
201 
202 #define K12_FILE_BLOB_LEN     16
203 
204 typedef struct {
205     guint32 file_len;
206     guint32 num_of_records;   /* XXX: not sure about this */
207 
208     GHashTable* src_by_id;    /* k12_srcdsc_recs by input */
209     GHashTable* src_by_name;  /* k12_srcdsc_recs by stack_name */
210 
211     guint8 *seq_read_buff;    /* read buffer for sequential reading */
212     guint seq_read_buff_len;  /* length of that buffer */
213     guint8 *rand_read_buff;   /* read buffer for random reading */
214     guint rand_read_buff_len; /* length of that buffer */
215 
216     Buffer extra_info;        /* Buffer to hold per packet extra information */
217 } k12_t;
218 
219 typedef struct _k12_src_desc_t {
220     guint32 input;
221     guint32 input_type;
222     gchar* input_name;
223     gchar* stack_file;
224     k12_input_info_t input_info;
225 } k12_src_desc_t;
226 
227 
228 /*
229  * According to the Tektronix documentation, this value is a combination of
230  * a "group" code and a "type" code, with both being 2-byte values and
231  * with the "group" code followe by the "type" code.  The "group" values
232  * are:
233  *
234  *      0x0001 - "data event"
235  *      0x0002 - "text or L1 event"
236  *      0x0007 - "configuration event"
237  *
238  * and the "type" values are:
239  *
240  *  data events:
241  *      0x0020 - "frame" (i.e., "an actual packet")
242  *      0x0021 - "transparent frame"
243  *      0x0022 - "bit data (TRAU frame)"
244  *      0x0024 - "used to mark the frame which is a fragment"
245  *      0x0026 - "used to mark the frame which is a fragment"
246  *      0x0028 - "used to mark the frame which is generated by the LSA"
247  *      0x002A - "used to mark the frame which is generated by the LSA"
248  *
249  *  text or L1 events:
250  *      0x0030 - "text event"
251  *      0x0031 - "L1 event"
252  *      0x0032 - "L1 event (BAI)"
253  *      0x0033 - "L1 event (VX)"
254  *
255  *  configuration events:
256  *      0x0040 - Logical Data Source configuration event
257  *      0x0041 - Logical Link configuration event
258  */
259 /* so far we've seen these types of records */
260 #define K12_REC_PACKET        0x00010020 /* an actual packet */
261 #define K12_REC_D0020         0x000d0020 /* an actual packet, seen in a k18 file */
262 #define K12_REC_SCENARIO      0x00070040 /* what appears as the window's title */
263 #define K12_REC_SRCDSC        0x00070041 /* port-stack mapping + more, the key of the whole thing */
264 #define K12_REC_STK_FILE      0x00070042 /* a dump of an stk file */
265 #define K12_REC_SRCDSC2       0x00070043 /* another port-stack mapping */
266 #define K12_REC_TEXT          0x00070044 /* a string containing something with a grammar (conditions/responses?) */
267 #define K12_REC_START         0x00020030 /* a string containing human readable start time  */
268 #define K12_REC_STOP          0x00020031 /* a string containing human readable stop time */
269 
270 /*
271  * According to the Tektronix documentation, packets, i.e. "data events",
272  * have several different group/type values, which differ in the last
273  * nibble of the type code.  For now, we just mask that nibble off; the
274  * format of the items are different, so we might have to treat different
275  * data event types differently.
276  */
277 #define K12_MASK_PACKET       0xfffffff0
278 
279 /* offsets of elements in the records */
280 #define K12_RECORD_LEN         0x0 /* uint32, in bytes */
281 #define K12_RECORD_TYPE        0x4 /* uint32, see above */
282 #define K12_RECORD_FRAME_LEN   0x8 /* uint32, in bytes */
283 #define K12_RECORD_SRC_ID      0xc /* uint32 */
284 
285 /*
286  * Some records from K15 files have a port ID of an undeclared
287  * interface which happens to be the only one with the first byte changed.
288  * It is still unknown how to recognize when this happens.
289  * If the lookup of the interface record fails we'll mask it
290  * and retry.
291  */
292 #define K12_RECORD_SRC_ID_MASK 0x00ffffff
293 
294 /* elements of packet records */
295 #define K12_PACKET_TIMESTAMP  0x18 /* int64 (8b) representing 1/2us since 01-01-1990 Z00:00:00 */
296 
297 #define K12_PACKET_FRAME      0x20 /* start of the actual frame in the record */
298 #define K12_PACKET_FRAME_D0020 0x34 /* start of the actual frame in the record */
299 
300 #define K12_PACKET_OFFSET_VP  0x08 /* 2 bytes, big endian */
301 #define K12_PACKET_OFFSET_VC  0x0a /* 2 bytes, big endian */
302 #define K12_PACKET_OFFSET_CID 0x0c /* 1 byte */
303 
304 /* elements of the source description records */
305 #define K12_SRCDESC_COLOR_FOREGROUND 0x12 /* 1 byte */
306 #define K12_SRCDESC_COLOR_BACKGROUND 0x13 /* 1 byte */
307 
308 #define K12_SRCDESC_PORT_TYPE  0x1a /* 1 byte */
309 #define K12_SRCDESC_HWPARTLEN  0x1e /* uint16, big endian */
310 #define K12_SRCDESC_NAMELEN    0x20 /* uint16, big endian */
311 #define K12_SRCDESC_STACKLEN   0x22 /* uint16, big endian */
312 
313 /* Hardware part of the record */
314 #define K12_SRCDESC_HWPART     0x24 /* offset of the hardware part */
315 
316 /* Offsets relative to the beginning of the hardware part */
317 #define K12_SRCDESC_HWPARTTYPE 0    /* uint32, big endian */
318 
319 #define K12_SRCDESC_DS0_MASK   24   /* variable-length */
320 
321 #define K12_SRCDESC_ATM_VPI    20   /* uint16, big endian */
322 #define K12_SRCDESC_ATM_VCI    22   /* uint16, big endian */
323 #define K12_SRCDESC_ATM_AAL    24   /* 1 byte */
324 
325 /*
326  * A "stack file", as appears in a K12_REC_STK_FILE record, is a text
327  * file (with CR-LF line endings) with a sequence of lines, each of
328  * which begins with a keyword, and has white-space-separated tokens
329  * after that.
330  *
331  * They appear to be:
332  *
333  *   STKVER, which is followed by a number (presumably a version number
334  *   for the stack file format)
335  *
336  *   STACK, which is followed by a quoted string ("ProtocolStack" in one
337  *   file) and two numbers
338  *
339  *   PATH, which is followed by a non-quoted string giving the pathname
340  *   of the directory containing the stack file
341  *
342  *   HLAYER, which is followed by a quoted string, a path for something
343  *   (protocol module?), a keyword ("LOADED", in one file), and a
344  *   quoted string giving a description - this is probably a protocol
345  *   layer of some sort
346  *
347  *   LAYER, which has a similar syntax to HLAYER - the first quoted
348  *   string is a protocol name
349  *
350  *   RELATION, which has a quoted string giving a protocol name,
351  *   another quoted string giving a protocol name, and a condition
352  *   specifier of some sort, which probably says the second protocol
353  *   is layered atop the first protocol if the condition is true.
354  *   The first protocol can also be "BASE", which means that the
355  *   second protocol is the lowest-level protocol.
356  *   The conditions are:
357  *
358  *     CPLX, which may mean "complex" - it has parenthesized expressions
359  *     including "&", presumably a boolean AND, with the individual
360  *     tests being L:expr, where L is a letter such as "L", "D", or "P",
361  *     and expr is:
362  *
363  *        0x........ for L, where each . is a hex digit or a ?, presumably
364  *        meaning "don't care"
365  *
366  *        0;0{=,!=}0b........ for D, where . is presumably a bit or a ?
367  *
368  *        param=value for P, where param is something such as "src_port"
369  *        and value is a value, presumably to test, for example, TCP or
370  *        UDP ports
371  *
372  *     UNCOND, presumably meaning "always"
373  *
374  *     PARAM, followed by a parameter name (as with P:) and a value,
375  *     possibly followed by LAYPARAM and a hex value
376  *
377  *   DECKRNL, followed by a quoted string protocol name, un-quoted
378  *   "LSBF" or "MSBF" (Least/Most Significant Byte First?), and
379  *   an un-quoted string ending with _DK
380  *
381  *   LAYPARAM, followed by a quoted protocol name and a number (-2147221504
382  *   in one file, which is 0x80040000)
383  *
384  *   SPC_CONF, folloed by a number, a quoted string with numbers separated
385  *   by hyphens, and another number
386  *
387  *   CIC_CONF, with a similar syntax to SPC_CONF
388  *
389  *   LAYPOS, followed by a protocol name or "BASE" and 3 numbers.
390  *
391  * Most of this is probably not useful, but the RELATION lines with
392  * "BASE" could be used to figure out how to start the dissection
393  * (if we knew what "L" and "D" did), and *some* of the others might
394  * be useful if they don't match what's already in various dissector
395  * tables (the ones for IP and a higher-level protocol, for example,
396  * aren't very useful, as those are standardized, but the ones for
397  * TCP, UDP, and SCTP ports, and SCTP PPIs, might be useful).
398  */
399 
400 /*
401  * get_record: Get the next record into a buffer
402  *   Every 8192 bytes 16 bytes are inserted in the file,
403  *   even in the middle of a record.
404  *   This reads the next record without the eventual 16 bytes.
405  *   returns the length of the record + the stuffing (if any)
406  *
407  *   Returns number of bytes read on success, 0 on EOF, -1 on error;
408  *   if -1 is returned, *err is set to the error indication and, for
409  *   errors where that's appropriate, *err_info is set to an additional
410  *   error string.
411  *
412  * XXX: works at most with 8191 bytes per record
413  */
get_record(k12_t * file_data,FILE_T fh,gint64 file_offset,gboolean is_random,int * err,gchar ** err_info)414 static gint get_record(k12_t *file_data, FILE_T fh, gint64 file_offset,
415                        gboolean is_random, int *err, gchar **err_info) {
416     guint8 *buffer = is_random ? file_data->rand_read_buff : file_data->seq_read_buff;
417     guint buffer_len = is_random ? file_data->rand_read_buff_len : file_data->seq_read_buff_len;
418     guint total_read = 0;
419     guint left;
420     guint8* writep;
421 #ifdef DEBUG_K12
422     guint actual_len;
423 #endif
424 
425     /*
426      * Where the next unknown 16 bytes are stuffed to the file.
427      * Following the file header, they appear every 8192 bytes,
428      * starting right after the file header, so if the file offset
429      * relative to the file header is a multiple of 8192, the
430      * 16-byte blob is there.
431      */
432     guint junky_offset = 8192 - (gint) ( (file_offset - K12_FILE_HDR_LEN) % 8192 );
433 
434     K12_DBG(6,("get_record: ENTER: junky_offset=%" G_GINT64_MODIFIER "d, file_offset=%" G_GINT64_MODIFIER "d",junky_offset,file_offset));
435 
436     /* no buffer is given, lets create it */
437     if (buffer == NULL) {
438         buffer = (guint8*)g_malloc(8192);
439         buffer_len = 8192;
440         if (is_random) {
441             file_data->rand_read_buff = buffer;
442             file_data->rand_read_buff_len = buffer_len;
443         } else {
444             file_data->seq_read_buff = buffer;
445             file_data->seq_read_buff_len = buffer_len;
446         }
447     }
448 
449     if ( junky_offset == 8192 ) {
450         /*
451          * We're at the beginning of one of the 16-byte blobs,
452          * so we first need to skip the blob.
453          *
454          * XXX - what if the blob is in the middle of the record
455          * length?  If the record length is always a multiple of
456          * 4 bytes, that won't happen.
457          */
458         if ( ! wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) )
459             return -1;
460         total_read += K12_FILE_BLOB_LEN;
461     }
462 
463     /*
464      * Read the record length.
465      */
466     if ( !wtap_read_bytes( fh, buffer, 4, err, err_info ) )
467         return -1;
468     total_read += 4;
469 
470     left = pntoh32(buffer + K12_RECORD_LEN);
471 #ifdef DEBUG_K12
472     actual_len = left;
473 #endif
474     junky_offset -= 4;
475 
476     K12_DBG(5,("get_record: GET length=%u",left));
477 
478     /*
479      * Record length must be at least large enough for the length
480      * and type, hence 8 bytes.
481      *
482      * XXX - is WTAP_MAX_PACKET_SIZE_STANDARD the right check for a maximum
483      * record size?  Should we report this error differently?
484      */
485     if (left < 8) {
486         *err = WTAP_ERR_BAD_FILE;
487         *err_info = g_strdup_printf("k12: Record length %u is less than 8 bytes long",left);
488         return -1;
489     }
490     if (left > WTAP_MAX_PACKET_SIZE_STANDARD) {
491         *err = WTAP_ERR_BAD_FILE;
492         *err_info = g_strdup_printf("k12: Record length %u is greater than the maximum %u",left,WTAP_MAX_PACKET_SIZE_STANDARD);
493         return -1;
494     }
495 
496     /*
497      * XXX - calculate the lowest power of 2 >= left, rather than just
498      * looping.
499      */
500     while (left > buffer_len) {
501         buffer = (guint8*)g_realloc(buffer,buffer_len*=2);
502         if (is_random) {
503             file_data->rand_read_buff = buffer;
504             file_data->rand_read_buff_len = buffer_len;
505         } else {
506             file_data->seq_read_buff = buffer;
507             file_data->seq_read_buff_len = buffer_len;
508         }
509     }
510 
511     writep = buffer + 4;
512     left -= 4;
513 
514     /* Read the rest of the record. */
515     do {
516         K12_DBG(6,("get_record: looping left=%d junky_offset=%" G_GINT64_MODIFIER "d",left,junky_offset));
517 
518         if (junky_offset > left) {
519             /*
520              * The next 16-byte blob is past the end of this record.
521              * Just read the rest of the record.
522              */
523             if ( !wtap_read_bytes( fh, writep, left, err, err_info ) )
524                 return -1;
525             total_read += left;
526             break;
527         } else {
528             /*
529              * The next 16-byte blob is part of this record.
530              * Read up to the blob.
531              */
532             if ( !wtap_read_bytes( fh, writep, junky_offset, err, err_info ) )
533                 return -1;
534 
535             total_read += junky_offset;
536             writep += junky_offset;
537 
538             /*
539              * Skip the blob.
540              */
541             if ( !wtap_read_bytes( fh, NULL, K12_FILE_BLOB_LEN, err, err_info ) )
542                 return -1;
543             total_read += K12_FILE_BLOB_LEN;
544 
545             left -= junky_offset;
546             junky_offset = 8192;
547         }
548 
549     } while(left);
550 
551     K12_HEX_ASCII_DUMP(5,file_offset, "GOT record", buffer, actual_len);
552     return total_read;
553 }
554 
555 static gboolean
memiszero(const void * ptr,size_t count)556 memiszero(const void *ptr, size_t count)
557 {
558     const guint8 *p = (const guint8 *)ptr;
559 
560     while (count != 0) {
561         if (*p != 0)
562             return FALSE;
563         p++;
564         count--;
565     }
566     return TRUE;
567 }
568 
569 static gboolean
process_packet_data(wtap_rec * rec,Buffer * target,guint8 * buffer,guint record_len,k12_t * k12,int * err,gchar ** err_info)570 process_packet_data(wtap_rec *rec, Buffer *target, guint8 *buffer,
571                     guint record_len, k12_t *k12, int *err, gchar **err_info)
572 {
573     guint32 type;
574     guint   buffer_offset;
575     guint64 ts;
576     guint32 length;
577     guint32 extra_len;
578     guint32 src_id;
579     k12_src_desc_t* src_desc;
580 
581     type = pntoh32(buffer + K12_RECORD_TYPE);
582     buffer_offset = (type == K12_REC_D0020) ? K12_PACKET_FRAME_D0020 : K12_PACKET_FRAME;
583     if (buffer_offset > record_len) {
584         *err = WTAP_ERR_BAD_FILE;
585         *err_info = g_strdup_printf("k12: Frame data offset %u > record length %u",
586                                     buffer_offset, record_len);
587         return FALSE;
588     }
589 
590     length = pntoh32(buffer + K12_RECORD_FRAME_LEN) & 0x00001FFF;
591     if (length > record_len - buffer_offset) {
592         *err = WTAP_ERR_BAD_FILE;
593         *err_info = g_strdup_printf("k12: Frame length %u > record frame data %u",
594                                     length, record_len - buffer_offset);
595         return FALSE;
596     }
597 
598     rec->rec_type = REC_TYPE_PACKET;
599     rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
600     rec->presence_flags = WTAP_HAS_TS;
601 
602     ts = pntoh64(buffer + K12_PACKET_TIMESTAMP);
603 
604     rec->ts.secs = (time_t) ((ts / 2000000) + 631152000);
605     rec->ts.nsecs = (guint32) ( (ts % 2000000) * 500 );
606 
607     rec->rec_header.packet_header.len = rec->rec_header.packet_header.caplen = length;
608 
609     ws_buffer_assure_space(target, length);
610     memcpy(ws_buffer_start_ptr(target), buffer + buffer_offset, length);
611 
612     /* extra information need by some protocols */
613     extra_len = record_len - buffer_offset - length;
614     ws_buffer_assure_space(&(k12->extra_info), extra_len);
615     memcpy(ws_buffer_start_ptr(&(k12->extra_info)),
616            buffer + buffer_offset + length, extra_len);
617     rec->rec_header.packet_header.pseudo_header.k12.extra_info = (guint8*)ws_buffer_start_ptr(&(k12->extra_info));
618     rec->rec_header.packet_header.pseudo_header.k12.extra_length = extra_len;
619 
620     src_id = pntoh32(buffer + K12_RECORD_SRC_ID);
621     K12_DBG(5,("process_packet_data: src_id=%.8x",src_id));
622     rec->rec_header.packet_header.pseudo_header.k12.input = src_id;
623 
624     if ( ! (src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) {
625         /*
626          * Some records from K15 files have a port ID of an undeclared
627          * interface which happens to be the only one with the first byte changed.
628          * It is still unknown how to recognize when this happens.
629          * If the lookup of the interface record fails we'll mask it
630          * and retry.
631          */
632         src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK));
633     }
634 
635     if (src_desc) {
636         K12_DBG(5,("process_packet_data: input_name='%s' stack_file='%s' type=%x",src_desc->input_name,src_desc->stack_file,src_desc->input_type));
637         rec->rec_header.packet_header.pseudo_header.k12.input_name = src_desc->input_name;
638         rec->rec_header.packet_header.pseudo_header.k12.stack_file = src_desc->stack_file;
639         rec->rec_header.packet_header.pseudo_header.k12.input_type = src_desc->input_type;
640 
641         switch(src_desc->input_type) {
642             case K12_PORT_ATMPVC:
643                 if (buffer_offset + length + K12_PACKET_OFFSET_CID < record_len) {
644                     rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.vp =  pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VP);
645                     rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.vc =  pntoh16(buffer + buffer_offset + length + K12_PACKET_OFFSET_VC);
646                     rec->rec_header.packet_header.pseudo_header.k12.input_info.atm.cid =  *((unsigned char*)(buffer + buffer_offset + length + K12_PACKET_OFFSET_CID));
647                     break;
648                 }
649                 /* Fall through */
650             default:
651                 memcpy(&(rec->rec_header.packet_header.pseudo_header.k12.input_info),&(src_desc->input_info),sizeof(src_desc->input_info));
652                 break;
653         }
654     } else {
655         K12_DBG(5,("process_packet_data: NO SRC_RECORD FOUND"));
656 
657         memset(&(rec->rec_header.packet_header.pseudo_header.k12),0,sizeof(rec->rec_header.packet_header.pseudo_header.k12));
658         rec->rec_header.packet_header.pseudo_header.k12.input_name = "unknown port";
659         rec->rec_header.packet_header.pseudo_header.k12.stack_file = "unknown stack file";
660     }
661 
662     rec->rec_header.packet_header.pseudo_header.k12.input = src_id;
663     rec->rec_header.packet_header.pseudo_header.k12.stuff = k12;
664     return TRUE;
665 }
666 
k12_read(wtap * wth,wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info,gint64 * data_offset)667 static gboolean k12_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, gint64 *data_offset) {
668     k12_t *k12 = (k12_t *)wth->priv;
669     k12_src_desc_t* src_desc;
670     guint8* buffer;
671     gint64 offset;
672     gint len;
673     guint32 type;
674     guint32 src_id;
675 
676     offset = file_tell(wth->fh);
677 
678     /* ignore the record if it isn't a packet */
679     do {
680         if ( k12->num_of_records == 0 ) {
681             /* No more records */
682             *err = 0;
683             return FALSE;
684         }
685 
686         K12_DBG(5,("k12_read: offset=%i",offset));
687 
688         *data_offset = offset;
689 
690         len = get_record(k12, wth->fh, offset, FALSE, err, err_info);
691 
692         if (len < 0) {
693             /* read error */
694             return FALSE;
695         } else if (len == 0) {
696             /* EOF */
697             *err = WTAP_ERR_SHORT_READ;
698             return FALSE;
699         } else if (len < K12_RECORD_SRC_ID + 4) {
700             /* Record not large enough to contain a src ID */
701             *err = WTAP_ERR_BAD_FILE;
702             *err_info = g_strdup_printf("k12: Data record length %d too short", len);
703             return FALSE;
704         }
705         k12->num_of_records--;
706 
707         buffer = k12->seq_read_buff;
708 
709         type = pntoh32(buffer + K12_RECORD_TYPE);
710         src_id = pntoh32(buffer + K12_RECORD_SRC_ID);
711 
712 
713         if ( ! (src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id))) ) {
714             /*
715              * Some records from K15 files have a port ID of an undeclared
716              * interface which happens to be the only one with the first byte changed.
717              * It is still unknown how to recognize when this happens.
718              * If the lookup of the interface record fails we'll mask it
719              * and retry.
720              */
721             src_desc = (k12_src_desc_t*)g_hash_table_lookup(k12->src_by_id,GUINT_TO_POINTER(src_id&K12_RECORD_SRC_ID_MASK));
722         }
723 
724         K12_DBG(5,("k12_read: record type=%x src_id=%x",type,src_id));
725 
726         offset += len;
727 
728     } while ( ((type & K12_MASK_PACKET) != K12_REC_PACKET && (type & K12_MASK_PACKET) != K12_REC_D0020) || !src_id || !src_desc );
729 
730     return process_packet_data(rec, buf, buffer, (guint)len, k12, err, err_info);
731 }
732 
733 
k12_seek_read(wtap * wth,gint64 seek_off,wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info)734 static gboolean k12_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) {
735     k12_t *k12 = (k12_t *)wth->priv;
736     guint8* buffer;
737     gint len;
738     gboolean status;
739 
740     K12_DBG(5,("k12_seek_read: ENTER"));
741 
742     if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) {
743         K12_DBG(5,("k12_seek_read: SEEK ERROR"));
744         return FALSE;
745     }
746 
747     len = get_record(k12, wth->random_fh, seek_off, TRUE, err, err_info);
748     if (len < 0) {
749         K12_DBG(5,("k12_seek_read: READ ERROR"));
750         return FALSE;
751     } else if (len < K12_RECORD_SRC_ID + 4) {
752         /* Record not large enough to contain a src ID */
753         K12_DBG(5,("k12_seek_read: SHORT READ"));
754         *err = WTAP_ERR_SHORT_READ;
755         return FALSE;
756     }
757 
758     buffer = k12->rand_read_buff;
759 
760     status = process_packet_data(rec, buf, buffer, (guint)len, k12, err, err_info);
761 
762     K12_DBG(5,("k12_seek_read: DONE OK"));
763 
764     return status;
765 }
766 
767 
new_k12_file_data(void)768 static k12_t* new_k12_file_data(void) {
769     k12_t* fd = g_new(k12_t,1);
770 
771     fd->file_len = 0;
772     fd->num_of_records = 0;
773     fd->src_by_name = g_hash_table_new(g_str_hash,g_str_equal);
774     fd->src_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
775     fd->seq_read_buff = NULL;
776     fd->seq_read_buff_len = 0;
777     fd->rand_read_buff = NULL;
778     fd->rand_read_buff_len = 0;
779 
780     ws_buffer_init(&(fd->extra_info), 100);
781 
782     return fd;
783 }
784 
destroy_srcdsc(gpointer k _U_,gpointer v,gpointer p _U_)785 static gboolean destroy_srcdsc(gpointer k _U_, gpointer v, gpointer p _U_) {
786     k12_src_desc_t* rec = (k12_src_desc_t*)v;
787 
788     g_free(rec->input_name);
789     g_free(rec->stack_file);
790     g_free(rec);
791 
792     return TRUE;
793 }
794 
destroy_k12_file_data(k12_t * fd)795 static void destroy_k12_file_data(k12_t* fd) {
796     g_hash_table_destroy(fd->src_by_id);
797     g_hash_table_foreach_remove(fd->src_by_name,destroy_srcdsc,NULL);
798     g_hash_table_destroy(fd->src_by_name);
799     ws_buffer_free(&(fd->extra_info));
800     g_free(fd->seq_read_buff);
801     g_free(fd->rand_read_buff);
802     g_free(fd);
803 }
804 
k12_close(wtap * wth)805 static void k12_close(wtap *wth) {
806     k12_t *k12 = (k12_t *)wth->priv;
807 
808     destroy_k12_file_data(k12);
809     wth->priv = NULL;   /* destroy_k12_file_data freed it */
810 #ifdef DEBUG_K12
811     K12_DBG(5,("k12_close: CLOSED"));
812     if (env_file) fclose(dbg_out);
813 #endif
814 }
815 
816 
k12_open(wtap * wth,int * err,gchar ** err_info)817 wtap_open_return_val k12_open(wtap *wth, int *err, gchar **err_info) {
818     k12_src_desc_t* rec;
819     guint8 header_buffer[K12_FILE_HDR_LEN];
820     guint8* read_buffer;
821     guint32 type;
822     long offset;
823     long len;
824     guint port_type;
825     guint32 rec_len;
826     guint32 hwpart_len;
827     guint32 name_len;
828     guint32 stack_len;
829     guint i;
830     k12_t* file_data;
831 
832 #ifdef DEBUG_K12
833     gchar* env_level = getenv("K12_DEBUG_LEVEL");
834     env_file = getenv("K12_DEBUG_FILENAME");
835     if ( env_file ) {
836         dbg_out = ws_fopen(env_file,"w");
837         if (dbg_out == NULL) {
838                 dbg_out = stderr;
839                 K12_DBG(1,("unable to open K12 DEBUG FILENAME for writing!  Logging to standard error"));
840         }
841     }
842     else
843         dbg_out = stderr;
844     if ( env_level ) debug_level = (unsigned int)strtoul(env_level,NULL,10);
845     K12_DBG(1,("k12_open: ENTER debug_level=%u",debug_level));
846 #endif
847 
848     if ( !wtap_read_bytes(wth->fh,header_buffer,K12_FILE_HDR_LEN,err,err_info) ) {
849         K12_DBG(1,("k12_open: FILE HEADER TOO SHORT OR READ ERROR"));
850         if (*err != WTAP_ERR_SHORT_READ) {
851             return WTAP_OPEN_ERROR;
852         }
853         return WTAP_OPEN_NOT_MINE;
854     }
855 
856     if ( memcmp(header_buffer,k12_file_magic,8) != 0 ) {
857         K12_DBG(1,("k12_open: BAD MAGIC"));
858         return WTAP_OPEN_NOT_MINE;
859     }
860 
861     offset = K12_FILE_HDR_LEN;
862 
863     file_data = new_k12_file_data();
864 
865     file_data->file_len = pntoh32( header_buffer + 0x8);
866     if (memiszero(header_buffer + 0x10, K12_FILE_HDR_LEN - 0x10)) {
867         /*
868          * The rest of the file header is all zeroes.  That means
869          * this is a file written by the old Wireshark code, and
870          * a count of records in the file is at an offset of 0x0C.
871          */
872         file_data->num_of_records = pntoh32( header_buffer + 0x0C );
873     } else {
874         /*
875          * There's at least one non-zero byte in the rest of the
876          * header.  The value 8192 is at 0xC (page size?), and
877          * what appears to be the number of records in the file
878          * is at an offset of 0x24 and at an offset of 0x2c.
879          *
880          * If the two values are not the same, we fail; if that's
881          * the case, we need to see the file to figure out which
882          * of those two values, if any, is the count.
883          */
884         file_data->num_of_records = pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_1 );
885         if ( file_data->num_of_records != pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_2 ) ) {
886             *err = WTAP_ERR_BAD_FILE;
887             *err_info = g_strdup_printf("k12: two different record counts, %u at 0x%02x and %u at 0x%02x",
888                                         file_data->num_of_records,
889                                         K12_FILE_HDR_RECORD_COUNT_1,
890                                         pntoh32( header_buffer + K12_FILE_HDR_RECORD_COUNT_2 ),
891                                         K12_FILE_HDR_RECORD_COUNT_2 );
892             destroy_k12_file_data(file_data);
893             return WTAP_OPEN_ERROR;
894         }
895     }
896 
897     K12_DBG(5,("k12_open: FILE_HEADER OK: offset=%x file_len=%i records=%i",
898             offset,
899             file_data->file_len,
900             file_data->num_of_records ));
901 
902     do {
903         if ( file_data->num_of_records == 0 ) {
904             *err = WTAP_ERR_SHORT_READ;
905             destroy_k12_file_data(file_data);
906             return WTAP_OPEN_ERROR;
907         }
908 
909         len = get_record(file_data, wth->fh, offset, FALSE, err, err_info);
910 
911         if ( len < 0 ) {
912             K12_DBG(1,("k12_open: BAD HEADER RECORD",len));
913             destroy_k12_file_data(file_data);
914             return WTAP_OPEN_ERROR;
915         }
916         if ( len == 0 ) {
917             K12_DBG(1,("k12_open: BAD HEADER RECORD",len));
918             *err = WTAP_ERR_SHORT_READ;
919             destroy_k12_file_data(file_data);
920             return WTAP_OPEN_ERROR;
921         }
922 
923         read_buffer = file_data->seq_read_buff;
924 
925         rec_len = pntoh32( read_buffer + K12_RECORD_LEN );
926         if (rec_len < K12_RECORD_TYPE + 4) {
927             /* Record isn't long enough to have a type field */
928             *err = WTAP_ERR_BAD_FILE;
929             *err_info = g_strdup_printf("k12: record length %u < %u",
930                                         rec_len, K12_RECORD_TYPE + 4);
931             destroy_k12_file_data(file_data);
932             return WTAP_OPEN_ERROR;
933         }
934         type = pntoh32( read_buffer + K12_RECORD_TYPE );
935 
936         if ( (type & K12_MASK_PACKET) == K12_REC_PACKET ||
937              (type & K12_MASK_PACKET) == K12_REC_D0020) {
938             /*
939              * we are at the first packet record, rewind and leave.
940              */
941             if (file_seek(wth->fh, offset, SEEK_SET, err) == -1) {
942                 destroy_k12_file_data(file_data);
943                 return WTAP_OPEN_ERROR;
944             }
945             K12_DBG(5,("k12_open: FIRST PACKET offset=%x",offset));
946             break;
947         }
948 
949         switch (type) {
950 
951         case K12_REC_SRCDSC:
952         case K12_REC_SRCDSC2:
953             rec = g_new0(k12_src_desc_t,1);
954 
955             if (rec_len < K12_SRCDESC_HWPART) {
956                 /*
957                  * Record isn't long enough to have the fixed-length portion
958                  * of the source descriptor field.
959                  */
960                 *err = WTAP_ERR_BAD_FILE;
961                 *err_info = g_strdup_printf("k12: source descriptor record length %u < %u",
962                                             rec_len, K12_SRCDESC_HWPART);
963                 destroy_k12_file_data(file_data);
964                 g_free(rec);
965                 return WTAP_OPEN_ERROR;
966             }
967             port_type = read_buffer[K12_SRCDESC_PORT_TYPE];
968             hwpart_len = pntoh16( read_buffer + K12_SRCDESC_HWPARTLEN );
969             name_len = pntoh16( read_buffer + K12_SRCDESC_NAMELEN );
970             stack_len = pntoh16( read_buffer + K12_SRCDESC_STACKLEN );
971 
972             rec->input = pntoh32( read_buffer + K12_RECORD_SRC_ID );
973 
974             K12_DBG(5,("k12_open: INTERFACE RECORD offset=%x interface=%x",offset,rec->input));
975 
976             if (name_len == 0) {
977                 K12_DBG(5,("k12_open: failed (name_len == 0 in source description"));
978                 destroy_k12_file_data(file_data);
979                 g_free(rec);
980                 return WTAP_OPEN_NOT_MINE;
981             }
982             if (stack_len == 0) {
983                 K12_DBG(5,("k12_open: failed (stack_len == 0 in source description"));
984                 destroy_k12_file_data(file_data);
985                 g_free(rec);
986                 return WTAP_OPEN_NOT_MINE;
987             }
988             if (rec_len < K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len) {
989                 /*
990                  * Record isn't long enough to have the full source descriptor
991                  * field, including the variable-length parts.
992                  */
993                 *err = WTAP_ERR_BAD_FILE;
994                 *err_info = g_strdup_printf("k12: source descriptor record length %u < %u (%u + %u + %u + %u)",
995                                             rec_len,
996                                             K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len,
997                                             K12_SRCDESC_HWPART, hwpart_len, name_len, stack_len);
998                 destroy_k12_file_data(file_data);
999                 g_free(rec);
1000                 return WTAP_OPEN_ERROR;
1001             }
1002 
1003             if (hwpart_len) {
1004                 if (hwpart_len < 4) {
1005                     /* Hardware part isn't long enough to have a type field */
1006                     *err = WTAP_ERR_BAD_FILE;
1007                     *err_info = g_strdup_printf("k12: source descriptor hardware part length %u < 4",
1008                                                 hwpart_len);
1009                     destroy_k12_file_data(file_data);
1010                     g_free(rec);
1011                     return WTAP_OPEN_ERROR;
1012                 }
1013                 switch(( rec->input_type = pntoh32( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_HWPARTTYPE ) )) {
1014                     case K12_PORT_DS0S:
1015                         /* This appears to be variable-length */
1016                         rec->input_info.ds0mask = 0x00000000;
1017                         if (hwpart_len > K12_SRCDESC_DS0_MASK) {
1018                             for (i = 0; i < hwpart_len - K12_SRCDESC_DS0_MASK; i++) {
1019                                 rec->input_info.ds0mask |= ( *(read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_DS0_MASK + i) == 0xff ) ? 1U<<(31-i) : 0x0;
1020                             }
1021                         }
1022                         break;
1023                     case K12_PORT_ATMPVC:
1024                         if (hwpart_len < K12_SRCDESC_ATM_VCI + 2) {
1025                             /* Hardware part isn't long enough to have ATM information */
1026                             *err = WTAP_ERR_BAD_FILE;
1027                             *err_info = g_strdup_printf("k12: source descriptor hardware part length %u < %u",
1028                                                         hwpart_len,
1029                                                         K12_SRCDESC_ATM_VCI + 2);
1030                             destroy_k12_file_data(file_data);
1031                             g_free(rec);
1032                             return WTAP_OPEN_ERROR;
1033                         }
1034 
1035                         rec->input_info.atm.vp = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VPI );
1036                         rec->input_info.atm.vc = pntoh16( read_buffer + K12_SRCDESC_HWPART + K12_SRCDESC_ATM_VCI );
1037                         break;
1038                     default:
1039                         break;
1040                 }
1041             } else {
1042                 /* Record viewer generated files don't have this information */
1043                 if (port_type >= 0x14
1044                     && port_type <= 0x17) {
1045                     /* For ATM2_E1DS1, ATM2_E3DS3,
1046                        ATM2_STM1EL and ATM2_STM1OP */
1047                     rec->input_type = K12_PORT_ATMPVC;
1048                     rec->input_info.atm.vp = 0;
1049                     rec->input_info.atm.vc = 0;
1050                 }
1051             }
1052 
1053             if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len - 1] != '\0') {
1054                 *err = WTAP_ERR_BAD_FILE;
1055                 *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated link-layer name");
1056                 destroy_k12_file_data(file_data);
1057                 g_free(rec);
1058                 return WTAP_OPEN_ERROR;
1059             }
1060             if (read_buffer[K12_SRCDESC_HWPART + hwpart_len + name_len + stack_len - 1] != '\0') {
1061                 *err = WTAP_ERR_BAD_FILE;
1062                 *err_info = g_strdup("k12_open: source descriptor record contains non-null-terminated stack path");
1063                 destroy_k12_file_data(file_data);
1064                 g_free(rec);
1065                 return WTAP_OPEN_ERROR;
1066             }
1067             rec->input_name = (gchar *)g_memdup2(read_buffer + K12_SRCDESC_HWPART + hwpart_len, name_len);
1068             rec->stack_file = (gchar *)g_memdup2(read_buffer + K12_SRCDESC_HWPART + hwpart_len + name_len, stack_len);
1069 
1070             ascii_strdown_inplace (rec->stack_file);
1071 
1072             g_hash_table_insert(file_data->src_by_id,GUINT_TO_POINTER(rec->input),rec);
1073             g_hash_table_insert(file_data->src_by_name,rec->stack_file,rec);
1074             break;
1075 
1076         case K12_REC_STK_FILE:
1077             K12_DBG(1,("k12_open: K12_REC_STK_FILE"));
1078             K12_DBG(1,("Field 1: 0x%08x",pntoh32( read_buffer + 0x08 )));
1079             K12_DBG(1,("Field 2: 0x%08x",pntoh32( read_buffer + 0x0c )));
1080             K12_ASCII_DUMP(1, read_buffer, rec_len, 16);
1081             break;
1082 
1083         default:
1084             K12_DBG(1,("k12_open: RECORD TYPE 0x%08x",type));
1085             break;
1086         }
1087         offset += len;
1088         file_data->num_of_records--;
1089     } while(1);
1090 
1091     wth->file_type_subtype = k12_file_type_subtype;
1092     wth->file_encap = WTAP_ENCAP_K12;
1093     wth->snapshot_length = 0;
1094     wth->subtype_read = k12_read;
1095     wth->subtype_seek_read = k12_seek_read;
1096     wth->subtype_close = k12_close;
1097     wth->priv = (void *)file_data;
1098     wth->file_tsprec = WTAP_TSPREC_NSEC;
1099 
1100     /*
1101      * Add an IDB; we don't know how many interfaces were
1102      * involved, so we just say one interface, about which
1103      * we only know the link-layer type, snapshot length,
1104      * and time stamp resolution.
1105      */
1106     wtap_add_generated_idb(wth);
1107 
1108     return WTAP_OPEN_MINE;
1109 }
1110 
1111 typedef struct {
1112     guint32 file_len;
1113     guint32 num_of_records;
1114     guint32 file_offset;
1115 } k12_dump_t;
1116 
k12_dump_can_write_encap(int encap)1117 static int k12_dump_can_write_encap(int encap) {
1118 
1119     if (encap == WTAP_ENCAP_PER_PACKET)
1120         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1121 
1122     if (encap != WTAP_ENCAP_K12)
1123         return WTAP_ERR_UNWRITABLE_ENCAP;
1124 
1125     return 0;
1126 }
1127 
1128 static const gchar dumpy_junk[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
1129 
k12_dump_record(wtap_dumper * wdh,guint32 len,guint8 * buffer,int * err_p)1130 static gboolean k12_dump_record(wtap_dumper *wdh, guint32 len,  guint8* buffer, int *err_p) {
1131     k12_dump_t *k12 = (k12_dump_t *)wdh->priv;
1132     guint32 junky_offset = (8192 - ( (k12->file_offset - K12_FILE_HDR_LEN) % 8192 )) % 8192;
1133 
1134     if (len > junky_offset) {
1135         if (junky_offset) {
1136             if (! wtap_dump_file_write(wdh, buffer, junky_offset, err_p))
1137                 return FALSE;
1138         }
1139         if (! wtap_dump_file_write(wdh, dumpy_junk, K12_FILE_BLOB_LEN, err_p))
1140             return FALSE;
1141 
1142         if (! wtap_dump_file_write(wdh, buffer+junky_offset, len - junky_offset, err_p))
1143             return FALSE;
1144 
1145         k12->file_offset += len + K12_FILE_BLOB_LEN;
1146         k12->file_len += len + K12_FILE_BLOB_LEN;
1147     } else {
1148         if (! wtap_dump_file_write(wdh, buffer, len, err_p))
1149             return FALSE;
1150         k12->file_offset += len;
1151         k12->file_len += len;
1152     }
1153 
1154     k12->num_of_records++;
1155     return TRUE;
1156 }
1157 
k12_dump_src_setting(gpointer k _U_,gpointer v,gpointer p)1158 static void k12_dump_src_setting(gpointer k _U_, gpointer v, gpointer p) {
1159     k12_src_desc_t* src_desc = (k12_src_desc_t*)v;
1160     wtap_dumper *wdh = (wtap_dumper *)p;
1161     guint32 len;
1162     guint offset;
1163     guint i;
1164     int   errxxx; /* dummy */
1165 
1166     union {
1167         guint8 buffer[8192];
1168 
1169         struct {
1170             guint32 len;
1171             guint32 type;
1172             guint32 unk32_1;
1173             guint32 input;
1174 
1175             guint16 unk32_2;
1176             guint16 color;
1177             guint32 unk32_3;
1178             guint32 unk32_4;
1179             guint16 unk16_1;
1180             guint16 hwpart_len;
1181 
1182             guint16 name_len;
1183             guint16 stack_len;
1184 
1185             struct {
1186                 guint32 type;
1187 
1188                 union {
1189                     struct {
1190                         guint32 unk32;
1191                         guint8 mask[32];
1192                     } ds0mask;
1193 
1194                     struct {
1195                         guint8 unk_data[16];
1196                         guint16 vp;
1197                         guint16 vc;
1198                     } atm;
1199 
1200                     guint32 unk;
1201                 } desc;
1202             } extra;
1203         } record;
1204     } obj;
1205 
1206     obj.record.type = g_htonl(K12_REC_SRCDSC);
1207     obj.record.unk32_1 = g_htonl(0x00000001);
1208     obj.record.input = g_htonl(src_desc->input);
1209 
1210     obj.record.unk32_2 = g_htons(0x0000);
1211     obj.record.color = g_htons(0x060f);
1212     obj.record.unk32_3 = g_htonl(0x00000003);
1213     switch (src_desc->input_type) {
1214         case K12_PORT_ATMPVC:
1215             obj.record.unk32_4 = g_htonl(0x01001400);
1216             break;
1217         default:
1218             obj.record.unk32_4 = g_htonl(0x01000100);
1219     }
1220 
1221     obj.record.unk16_1 = g_htons(0x0000);
1222     obj.record.name_len = (guint16) strlen(src_desc->input_name) + 1;
1223     obj.record.stack_len = (guint16) strlen(src_desc->stack_file) + 1;
1224 
1225     obj.record.extra.type = g_htonl(src_desc->input_type);
1226 
1227     switch (src_desc->input_type) {
1228         case K12_PORT_ATMPVC:
1229             obj.record.hwpart_len = g_htons(0x18);
1230             obj.record.extra.desc.atm.vp = g_htons(src_desc->input_info.atm.vp);
1231             obj.record.extra.desc.atm.vc = g_htons(src_desc->input_info.atm.vc);
1232             offset = 0x3c;
1233             break;
1234         case K12_PORT_DS0S:
1235             obj.record.hwpart_len = g_htons(0x18);
1236             for( i=0; i<32; i++ ) {
1237                 obj.record.extra.desc.ds0mask.mask[i] =
1238                 (src_desc->input_info.ds0mask & (1UL << i)) ? 0xff : 0x00;
1239             }
1240             offset = 0x3c;
1241             break;
1242         default:
1243             obj.record.hwpart_len = g_htons(0x08);
1244             offset = 0x2c;
1245             break;
1246     }
1247 
1248     memcpy(obj.buffer + offset,
1249            src_desc->input_name,
1250            obj.record.name_len);
1251 
1252     memcpy(obj.buffer + offset + obj.record.name_len,
1253            src_desc->stack_file,
1254            obj.record.stack_len);
1255 
1256     len = offset + obj.record.name_len + obj.record.stack_len;
1257     len += (len % 4) ? 4 - (len % 4) : 0;
1258 
1259     obj.record.len = g_htonl(len);
1260     obj.record.name_len =  g_htons(obj.record.name_len);
1261     obj.record.stack_len = g_htons(obj.record.stack_len);
1262 
1263     k12_dump_record(wdh,len,obj.buffer, &errxxx); /* fwrite errs ignored: see k12_dump below */
1264 }
1265 
k12_dump(wtap_dumper * wdh,const wtap_rec * rec,const guint8 * pd,int * err,gchar ** err_info _U_)1266 static gboolean k12_dump(wtap_dumper *wdh, const wtap_rec *rec,
1267                          const guint8 *pd, int *err, gchar **err_info _U_) {
1268     const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
1269     k12_dump_t *k12 = (k12_dump_t *)wdh->priv;
1270     guint32 len;
1271     union {
1272         guint8 buffer[8192];
1273         struct {
1274             guint32 len;
1275             guint32 type;
1276             guint32 frame_len;
1277             guint32 input;
1278 
1279             guint32 datum_1;
1280             guint32 datum_2;
1281             guint64 ts;
1282 
1283             guint8 frame[0x1fc0];
1284         } record;
1285     } obj;
1286 
1287     /* We can only write packet records. */
1288     if (rec->rec_type != REC_TYPE_PACKET) {
1289         *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
1290         return FALSE;
1291     }
1292 
1293     /*
1294      * Make sure this packet doesn't have a link-layer type that
1295      * differs from the one for the file.
1296      */
1297     if (wdh->encap != rec->rec_header.packet_header.pkt_encap) {
1298         *err = WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1299         return FALSE;
1300     }
1301 
1302     if (k12->num_of_records == 0) {
1303         k12_t* file_data = (k12_t*)pseudo_header->k12.stuff;
1304         /* XXX: We'll assume that any fwrite errors in k12_dump_src_setting will    */
1305         /*      repeat during the final k12_dump_record at the end of k12_dump      */
1306         /*      (and thus cause an error return from k12_dump).                     */
1307         /*      (I don't see a reasonably clean way to handle any fwrite errors     */
1308         /*       encountered in k12_dump_src_setting).                              */
1309         g_hash_table_foreach(file_data->src_by_id,k12_dump_src_setting,wdh);
1310     }
1311     obj.record.len = 0x20 + rec->rec_header.packet_header.caplen;
1312     obj.record.len += (obj.record.len % 4) ? 4 - obj.record.len % 4 : 0;
1313 
1314     len = obj.record.len;
1315 
1316     obj.record.len = g_htonl(obj.record.len);
1317 
1318     obj.record.type = g_htonl(K12_REC_PACKET);
1319     obj.record.frame_len = g_htonl(rec->rec_header.packet_header.caplen);
1320     obj.record.input = g_htonl(pseudo_header->k12.input);
1321 
1322     obj.record.ts = GUINT64_TO_BE((((guint64)rec->ts.secs - 631152000) * 2000000) + (rec->ts.nsecs / 1000 * 2));
1323 
1324     memcpy(obj.record.frame,pd,rec->rec_header.packet_header.caplen);
1325 
1326     return k12_dump_record(wdh,len,obj.buffer, err);
1327 }
1328 
1329 static const guint8 k12_eof[] = {0xff,0xff};
1330 
k12_dump_finish(wtap_dumper * wdh,int * err,gchar ** err_info _U_)1331 static gboolean k12_dump_finish(wtap_dumper *wdh, int *err, gchar **err_info _U_) {
1332     k12_dump_t *k12 = (k12_dump_t *)wdh->priv;
1333     union {
1334         guint8 b[sizeof(guint32)];
1335         guint32 u;
1336     } d;
1337 
1338     if (! wtap_dump_file_write(wdh, k12_eof, 2, err))
1339         return FALSE;
1340     k12->file_len += 2;
1341 
1342     if (wtap_dump_file_seek(wdh, K12_FILE_HDR_FILE_SIZE, SEEK_SET, err) == -1)
1343         return FALSE;
1344 
1345     d.u = g_htonl(k12->file_len);
1346 
1347     if (! wtap_dump_file_write(wdh, d.b, 4, err))
1348         return FALSE;
1349 
1350     if (wtap_dump_file_seek(wdh, K12_FILE_HDR_PAGE_SIZE, SEEK_SET, err) == -1)
1351         return FALSE;
1352 
1353     d.u = g_htonl(8192);
1354 
1355     if (! wtap_dump_file_write(wdh, d.b, 4, err))
1356         return FALSE;
1357 
1358     if (wtap_dump_file_seek(wdh, K12_FILE_HDR_RECORD_COUNT_1, SEEK_SET, err) == -1)
1359         return FALSE;
1360 
1361     d.u = g_htonl(k12->num_of_records);
1362 
1363     if (! wtap_dump_file_write(wdh, d.b, 4, err))
1364         return FALSE;
1365 
1366     if (wtap_dump_file_seek(wdh, K12_FILE_HDR_RECORD_COUNT_2, SEEK_SET, err) == -1)
1367         return FALSE;
1368 
1369     d.u = g_htonl(k12->num_of_records);
1370 
1371     if (! wtap_dump_file_write(wdh, d.b, 4, err))
1372         return FALSE;
1373 
1374     return TRUE;
1375 }
1376 
1377 
k12_dump_open(wtap_dumper * wdh,int * err,gchar ** err_info _U_)1378 static gboolean k12_dump_open(wtap_dumper *wdh, int *err, gchar **err_info _U_) {
1379     k12_dump_t *k12;
1380 
1381     if ( ! wtap_dump_file_write(wdh, k12_file_magic, 8, err)) {
1382         return FALSE;
1383     }
1384 
1385     if (wtap_dump_file_seek(wdh, K12_FILE_HDR_LEN, SEEK_SET, err) == -1)
1386         return FALSE;
1387 
1388     wdh->subtype_write = k12_dump;
1389     wdh->subtype_finish = k12_dump_finish;
1390 
1391     k12 = g_new(k12_dump_t, 1);
1392     wdh->priv = (void *)k12;
1393     k12->file_len = K12_FILE_HDR_LEN;
1394     k12->num_of_records = 0;
1395     k12->file_offset  = K12_FILE_HDR_LEN;
1396 
1397     return TRUE;
1398 }
1399 
1400 static const struct supported_block_type k12_blocks_supported[] = {
1401     /*
1402      * We support packet blocks, with no comments or other options.
1403      */
1404     { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
1405 };
1406 
1407 static const struct file_type_subtype_info k12_info = {
1408     "Tektronix K12xx 32-bit .rf5 format", "rf5", "rf5", NULL,
1409     TRUE, BLOCKS_SUPPORTED(k12_blocks_supported),
1410     k12_dump_can_write_encap, k12_dump_open, NULL
1411 };
1412 
register_k12(void)1413 void register_k12(void)
1414 {
1415     k12_file_type_subtype = wtap_register_file_type_subtype(&k12_info);
1416 
1417     /*
1418      * Register name for backwards compatibility with the
1419      * wtap_filetypes table in Lua.
1420      */
1421     wtap_register_backwards_compatibility_lua_name("K12",
1422                                                    k12_file_type_subtype);
1423 }
1424 
1425 /*
1426  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1427  *
1428  * Local variables:
1429  * c-basic-offset: 4
1430  * tab-width: 8
1431  * indent-tabs-mode: nil
1432  * End:
1433  *
1434  * vi: set shiftwidth=4 tabstop=8 expandtab:
1435  * :indentSize=4:tabSize=8:noTabs=true:
1436  */
1437