use a helper dissector to show k12 files.
authorlego <lego@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 13 Jun 2005 19:45:21 +0000 (19:45 +0000)
committerlego <lego@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 13 Jun 2005 19:45:21 +0000 (19:45 +0000)
git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@14621 f5534014-38df-0310-8fa8-9805f1628bb7

epan/dissectors/Makefile.common
epan/dissectors/packet-k12.c [new file with mode: 0644]
wiretap/k12.c
wiretap/wtap.h

index 1a07751cc15250187dd8387ef3f57db0712ca7c6..2b145d42b2df2979dfdc5527ce6dccd974cf8a66 100644 (file)
@@ -349,6 +349,7 @@ DISSECTOR_SRC =     \
        packet-jabber.c \
        packet-juniper.c \
        packet-jxta.c   \
+       packet-k12.c \
        packet-kadm5.c  \
        packet-kerberos.c       \
        packet-kerberos4.c      \
diff --git a/epan/dissectors/packet-k12.c b/epan/dissectors/packet-k12.c
new file mode 100644 (file)
index 0000000..e684435
--- /dev/null
@@ -0,0 +1,199 @@
+/* packet-k12.c
+* Routines for displaying frames from k12 rf5 files
+*
+* Luis E. Garcia Ontanon <luis.ontanon@gmail.com>
+*
+* $Id$
+*
+* Ethereal - Network traffic analyzer
+* By Gerald Combs <gerald@ethereal.com>
+* Copyright 1998
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+#include <epan/packet.h>
+#include <prefs.h>
+
+static int proto_k12 = -1;
+
+static int hf_k12_port_id = -1;
+static int hf_k12_port_name = -1;
+static int hf_k12_stack_file = -1;
+
+static gint ett_k12 = -1;
+
+static dissector_handle_t k12_handle;
+static dissector_handle_t data_handle;
+
+static module_t *k12_module;
+
+static char* k12_config_filename = "";
+
+static GHashTable* k12_cfg = NULL;
+
+static void dissect_k12(tvbuff_t* tvb,packet_info* pinfo,proto_tree* tree) {
+       proto_item* k12_item;
+       proto_tree* k12_tree;
+       dissector_handle_t sub_handle;
+
+       k12_item = proto_tree_add_protocol_format(tree, proto_k12, tvb, 0, 0, "Packet from: '%s' (0x%.8x)",
+                                                                                         pinfo->pseudo_header->k12.src_name,
+                                                                                         pinfo->pseudo_header->k12.src_id);
+       
+    k12_tree = proto_item_add_subtree(k12_item, ett_k12);
+
+       proto_tree_add_uint(k12_tree, hf_k12_port_id, tvb, 0,0,pinfo->pseudo_header->k12.src_id);
+       proto_tree_add_string(k12_tree, hf_k12_port_name, tvb, 0,0,pinfo->pseudo_header->k12.src_name);
+       proto_tree_add_string(k12_tree, hf_k12_stack_file, tvb, 0,0,pinfo->pseudo_header->k12.stack_file);
+
+       
+       if (! k12_cfg ) {
+               sub_handle = data_handle;
+       } else {
+               sub_handle = g_hash_table_lookup(k12_cfg,pinfo->pseudo_header->k12.stack_file);
+               
+               if (! sub_handle )
+                       sub_handle = data_handle;
+       }
+       
+       call_dissector(sub_handle, tvb, pinfo, tree);
+       
+} 
+
+static gboolean free_just_key (gpointer k, gpointer v _U_, gpointer p _U_) {
+       g_free(k);
+       return TRUE;
+}
+
+
+static GHashTable* k12_load_config(FILE* fp) {
+       gchar buffer[0x10000];
+       size_t len;
+       GHashTable* hash = g_hash_table_new(g_str_hash,g_str_equal);
+       gchar** curr;
+       gchar** lines = NULL;
+       guint i;
+       dissector_handle_t handle;
+
+       len = fread(buffer,1,0xFFFF,fp);
+
+       if (len > 0) {
+               lines = g_strsplit(buffer,"\n",0);
+               
+               for (i = 0 ; lines[i]; i++) {
+                       g_strstrip(lines[i]);
+                       
+                       if(*(lines[i]) == '#') continue;
+                       if(*(lines[i]) == '\0') break;
+                       
+                       curr = g_strsplit(lines[i]," ",0);
+                       
+                       if (! (curr[0] != NULL && *curr[0] != '\0' && curr[1] != NULL  && *curr[1] != '\0' ) ) {
+                               /* XXX report_error */
+                               g_warning("K12xx: Format error in line %u",i+1);
+                               g_strfreev(curr);
+                               g_strfreev(lines);
+                               g_hash_table_foreach_remove(hash,free_just_key,NULL);
+                               g_hash_table_destroy(hash);
+                               return NULL;
+                       }
+                       
+                       g_strstrip(curr[0]);
+                       g_strstrip(curr[1]);
+                       handle = find_dissector(curr[1]);
+
+                       if (! handle ) {
+                               /* XXX report_error */
+                               g_warning("k12: proto %s not found",curr[1]);
+                               handle = data_handle;
+                       }
+                       
+                       g_hash_table_insert(hash,g_strdup(curr[0]),handle);
+                       g_strfreev(curr);
+                       
+               }
+
+               g_strfreev(lines);
+               return hash;
+
+       }
+       
+       g_hash_table_destroy(hash);
+                               /* XXX report_error */
+       g_warning("K12xx: I/O error");
+       return NULL;
+}
+
+
+static void k12_load_prefs(void) {
+       FILE* fp;
+       
+       if (k12_cfg) {
+               g_hash_table_foreach_remove(k12_cfg,free_just_key,NULL);
+               g_hash_table_destroy(k12_cfg);
+               k12_cfg = NULL;
+       }
+       
+       if (*k12_config_filename != '\0') {
+               if (( fp = fopen(k12_config_filename,"r") )) {
+                       k12_cfg = k12_load_config(fp);
+                       return;
+               } else {
+                       /* XXX report_error */
+                       g_warning("failed to open: %s",k12_config_filename);                    
+               }
+       }
+}
+
+void proto_reg_handoff_k12(void) {
+       k12_handle = find_dissector("k12");
+       data_handle = find_dissector("data");
+       dissector_add("wtap_encap", WTAP_ENCAP_K12, k12_handle);        
+}
+
+void
+proto_register_k12(void)
+{
+       static hf_register_info hf[] = {
+               { &hf_k12_port_id, { "Port Id", "k12.port_id", FT_UINT32, BASE_HEX,     NULL, 0x0, "", HFILL }},
+               { &hf_k12_port_name, { "Port Name", "k12.port_name", FT_STRING, BASE_NONE, NULL, 0x0,"", HFILL }},
+               { &hf_k12_stack_file, { "Stack file used", "k12.stack_file", FT_STRING, BASE_NONE, NULL, 0x0,"", HFILL }}
+       };
+       
+  static gint *ett[] = {
+    &ett_k12,
+  };
+       
+  proto_k12 = proto_register_protocol("K12xx", "K12xx", "k12");
+  proto_register_field_array(proto_k12, hf, array_length(hf));
+  proto_register_subtree_array(ett, array_length(ett));
+  register_dissector("k12", dissect_k12, proto_k12);
+
+  k12_module = prefs_register_protocol(proto_k12, k12_load_prefs);
+  
+  prefs_register_string_preference(k12_module, "config",
+                                                                  "Configuration filename",
+                                                                  "K12 module configuration filename",
+                                                                  &k12_config_filename);
+  
+}
index 660382f24cf76a0b08c2bd742665981f28c41437..d622fff1f39262fff996e040067a615e85ff09be 100644 (file)
 #include "file_wrappers.h"
 #include "buffer.h"
 
+/*
+ * the 32 bits .rf5 file contains:
+ *  an 8 byte magic number
+ *  32bit lenght
+ *  32bit number of records
+ *  other 0x200 bytes bytes of uncharted territory
+ *     1 or more copies of the num_of_records in there
+ *  the records whose first 32bits word is the length
+ *     they are stuffed by one to four words every 0x2000 bytes
+ *  and a 2 byte terminator FFFF
+ */
 
 static const guint8 k12_file_magic[] = { 0x00, 0x00, 0x02, 0x00 ,0x12, 0x05, 0x00, 0x10 };
 
-#define K12_REC_PACKET  0x00010020
-#define K12_REC_SRCDSC 0x00070041
-
-/* XXX: we don't know what is in these type of records */
-#define K12_REC_UNK001 0x00070040
-#define K12_REC_UNK002 0x00070042
-#define K12_REC_UNK003 0x00070044
-
-/* So far we've seen the following appear only at the end of the file */
-#define K12_REC_UNK004 0x00020030
-#define K12_REC_UNK005 0x00020031
+struct _k12_t {
+       guint32 file_len;
+       guint32 num_of_records; /* XXX: not sure about this */
+       
+       GHashTable* src_by_id; /* k12_srcdsc_recs by src_id */
+       GHashTable* src_by_name; /* k12_srcdsc_recs by stack_name */
+};
 
 #define K12_HDR_LEN 0x10
 
-typedef struct {
+typedef struct _k12_record_hdr_t {
        guint32 len;
        guint32 type;
        guint32 frame_len;
-       guint32 port_id;
+       guint32 input;
 } k12_record_hdr_t;
 
-typedef struct  {
-       gchar* name;
-       guint32 encap;
-} k12_stack_encap_t;
-
-typedef struct  {
-       guint32 port_id;
-       guint32 encap;
-} k12_port_encap_t;
+/* so far we've seen only 7 types of records */
+#define K12_REC_PACKET         0x00010020
+#define K12_REC_SRCDSC         0x00070041 /* port-stack mapping + more, the key of the whole thing */
+#define K12_REC_SCENARIO       0x00070040 /* what appears as the window's title */
+#define K12_REC_70042          0x00070042 /* XXX: ??? */ 
+#define K12_REC_70044          0x00070044 /* text with a grammar (conditions/responses) */
+#define K12_REC_20030          0x00020030 /* human readable start time  */ 
+#define K12_REC_20032          0x00020031 /* human readable stop time */
 
-struct _k12_t {
-       k12_stack_encap_t* stack_encap;
-       guint stack_encap_p;
-       GPtrArray *port_encaps;
-       guint32 file_len;
-};
-
-static const k12_stack_encap_t virgin_stack_encap[] = {
-       {NULL,WTAP_ENCAP_USER0},
-       {NULL,WTAP_ENCAP_USER1},
-       {NULL,WTAP_ENCAP_USER2},
-       {NULL,WTAP_ENCAP_USER3},
-       {NULL,WTAP_ENCAP_USER4},
-       {NULL,WTAP_ENCAP_USER5},
-       {NULL,WTAP_ENCAP_USER6},
-       {NULL,WTAP_ENCAP_USER7},
-       {NULL,WTAP_ENCAP_USER8},
-       {NULL,WTAP_ENCAP_USER9},
-       {NULL,WTAP_ENCAP_USER10},
-       {NULL,WTAP_ENCAP_USER11},
-       {NULL,WTAP_ENCAP_USER12},
-       {NULL,WTAP_ENCAP_USER13},
-       {NULL,WTAP_ENCAP_USER14},
-       /*      {NULL,WTAP_ENCAP_USER15},  used for unnknown sources */
-       {NULL,0}        
-};
+typedef struct _k12_src_desc_t {
+       k12_record_hdr_t hdr;
 
+       struct _record {
+               guint32 unk_10;
+               guint32 unk_14;
+               guint16 unk_18;
+               guint16 extra_len;
+               guint16 name_len;
+               guint16 stack_len;
+       } record;
+       
+       struct _variable {
+               guint8* extra_blob;
+               gchar* port_name;
+               gchar* stack_file;
+       } variable;
+} k12_src_desc_t;
 
-static guint32 choose_encap(k12_t* file_data, guint32 port_id, gchar* stack_name) {
-       guint32 encap = 0;
-       k12_port_encap_t* pe;
-       guint i;
-       
-       for (i =0; i < file_data->stack_encap_p; i++) {
-               
-               if (strcmp(stack_name,file_data->stack_encap[i].name) == 0) {
-                       encap = file_data->stack_encap[i].encap;
-                       g_free(stack_name);
-                       break;
-               }
-       }
-       
-       if (file_data->stack_encap_p > 14) {
-               /* g_warning("k12_choose_encap: Cannot handle more than 15 stack types"); */
-               return WTAP_ENCAP_USER15;
-       }
-       
-       if ( encap == 0 ) {
-               file_data->stack_encap[file_data->stack_encap_p].name = stack_name;
-               encap = file_data->stack_encap[file_data->stack_encap_p].encap;
-       }
-       
-       pe = g_malloc(sizeof(k12_port_encap_t));
-       pe->port_id = port_id;
-       pe->encap = encap;
-       
-       g_ptr_array_add(file_data->port_encaps,pe);
-       return encap;
-}
+typedef struct {
+       k12_record_hdr_t hdr;
 
-static guint32 get_encap(k12_t* file_data, guint32 port_id) {
-       guint i;
-       k12_port_encap_t* pe;
-       
-       for (i = 0; i < file_data->port_encaps->len; i++) {
-               pe = g_ptr_array_index(file_data->port_encaps,i);
-               
-               if (pe->port_id == port_id)
-                       return pe->encap;
-       }
-       
-       /*g_warning("k12_get_encap: BUG: found no encapsulation for source 0x%.8x\n"
-               "please report this to ethereal-dev@ethereal.com", port_id);*/
-       
-       return WTAP_ENCAP_USER15;
-}
+       struct {
+               guint32 unk_10; /* some bit of the second nibble is set in some frames */
+               guint32 unk_14; /* made of several fields, it increases always, 
+                                                       in consecutive packets from the same port it increases by one.
+                                               */
+               guint64 ts;
+       } record;       
+       
+       guint8* variable;
+} k12_packet_t;
 
 
 
@@ -156,48 +118,66 @@ static guint32 get_encap(k12_t* file_data, guint32 port_id) {
  *             -1 at EOF
  *       the lenght of the preamble (0 if none) if OK.
  *
- *   Record headers are 4 4byte words long,
- *       - the first is the lenght of the record
- *       - the second is the type of the record
- *       - the third is the lenght of the frame in packet records
- *              - the last is the source id to which it refers
- *
  *   Every about 0x2000 bytes up to 4 words are inserted in the file,
  *   not being able yet to understand *exactly* how and where these
  *   are inserted we need to scan the file for the next valid header.
  *
  */
-gboolean get_k12_hdr(k12_record_hdr_t* hdr, wtap* wth, int* err, gchar **err_info) {
-       guint8 hdr_buf[0x14]; /* five 32bit "slots" */
+gboolean get_k12_hdr(k12_record_hdr_t* hdr, wtap* wth, int* err) {
+       guint32 hdr_buf[5];
        guint32 magic;
        guint i;
        guint len;
-       
+#if 0
        /*
         * XXX: as most records are contiguous we could
         * avoid hunting when not in the "risky zones".
-        *
-        * gboolean risky = ( (file_offset-0x210) % 0x2000) > 0x1f00 || 
-        *                    (file_offset-0x210) % 0x2000) < 0x0100   );
-        *
+        */
+       
+       gboolean risky = (  (wth->data_offset-0x210) % 0x2000 > 0x1e00 || 
+                                               (wth->data_offset-0x210) % 0x2000 < 0x0200   );
+       if (! risky) {
+               if ( file_read(hdr, 1, sizeof(*hdr), wth->fh) != sizeof(*hdr) ) {
+                       if (! (*err = file_error(wth->fh) ) ) 
+                               *err = WTAP_ERR_SHORT_READ;
+                       return -1;
+               } else {
+                       hdr->len = 0x0000FFFF & pntohl(hdr->len);
+                       hdr->type = pntohl(hdr->type);
+                       hdr->frame_len = 0x0000FFFF & pntohl(hdr->frame_len);
+                       hdr->input = pntohl( hdr->input );
+                       return 0;
+               }
+       }
+       
+       /*
         * We'll take the conservative approach and avoid trouble altogether.
         */
+#endif
        
-       /* read the first three words inserting them from the second slot on */
+       /*
+        *  we'll hunt for valid headers by loading the candidate header
+        *  in a buffer one word longer, and checking it.
+        *  If it is ok we'll copy it and return ok.
+        *  If it doesn't we'll load the next word shinfting and trying again
+        */
        
-       if ((len = file_read(hdr_buf + 0x4, 1, 0xC, wth->fh)) != 0xC) {
+       /* read the first three words inserting them from the second slot on */
+       if ((len = file_read(hdr_buf + 1, 1, 0xC, wth->fh)) != 0xC) {
                if (len == 2) {
-                       if (hdr_buf[0x4] == 0xff && hdr_buf[0x5] == 0xff) {
+                       if ( hdr_buf[1] >> 16 == 0xffff ) {
+                               /* EOF */
+                               *err = 0;
                                return -1;
                        }
                }
                
-               *err = file_error(wth->fh);
-               if (*err == 0)
+               if (! (*err = file_error(wth->fh) ) ) 
                        *err = WTAP_ERR_SHORT_READ;
+               
                return -2;
        }
-       
+
        do {
                
                /*
@@ -205,58 +185,53 @@ gboolean get_k12_hdr(k12_record_hdr_t* hdr, wtap* wth, int* err, gchar **err_inf
                 *
                 * We do not know if the record types we know are all of them.
                 *
-                * Instead of failing we could  try to skip a record whose type we do
+                * Instead of failing we could try to skip a record whose type we do
                 * not know yet. In that case however it is possible that a "magic"
                 * number appears in the record and unpredictable things would happen.
                 * We won't try, we'll fail and ask for feedback.
                 */
                if ( len > 0x20) {
-                       /*
                         g_warning("get_k12_hdr: found more than 4 words of stuffing, this should not happen!\n"
                                           "please report this issue to ethereal-dev@ethereal.com");
-                        */
                        return -2;
                }
                
                /* read the next word into the last slot */
-               if ( file_read( hdr_buf + K12_HDR_LEN, 1, 0x4, wth->fh) != 0x4 ) {
+               if ( file_read( hdr_buf + , 1, 0x4, wth->fh) != 0x4 ) {
                        *err = WTAP_ERR_SHORT_READ;
-                       *err_info = "record too short while reading .rf5 file";
                        return -2;
                }
                
                len += 0x4;
                
-               /* shift the buffer one word left */
-               /* XXX: working with words this would be faster */
-               for ( i = 0 ; i < 16 ; i++ )
-                       hdr_buf[i] = hdr_buf[i + 0x4]; 
+               for ( i = 0 ; i < 4 ; i++ )
+                       hdr_buf[i] = hdr_buf[i + 1]; 
                
                /* we'll be done if the second word is a magic number */
-               magic = pntohl( hdr_buf + 0x4 );
+               magic = pntohl( hdr_buf + 1 );
                
        } while (magic != K12_REC_PACKET &&
                         magic != K12_REC_SRCDSC &&
-                        magic != K12_REC_UNK001 &&
-                        magic != K12_REC_UNK002 &&
-                        magic != K12_REC_UNK003 &&
-                        magic != K12_REC_UNK004 &&
-                        magic != K12_REC_UNK005 );
+                        magic != K12_REC_SCENARIO &&
+                        magic != K12_REC_70042 &&
+                        magic != K12_REC_70044 &&
+                        magic != K12_REC_20030 &&
+                        magic != K12_REC_20032 );
        
-       hdr->len = 0x0000FFFF & pntohl( hdr_buf );      /* the first two bytes off the record len may contain junk */
+       hdr->len = 0x0000FFFF & hdr_buf[0];     /* the first two bytes off the record len may be altered */
        hdr->type = magic;
-       hdr->frame_len = 0x0000FFFF & pntohl( hdr_buf + 0x8 );
-       hdr->port_id = pntohl( hdr_buf + 0xC );
-       
+       hdr->frame_len = 0x0000FFFF & pntohl( hdr_buf + 2 ); /* play defensive */
+       hdr->input = pntohl( hdr_buf + 3 );
+               
        return len - K12_HDR_LEN;
 }
 
 static gboolean k12_read(wtap *wth, int *err, gchar **err_info, long *data_offset) {
-       guint64 ts;
-       guint8 b[8];
-       guint8* junk[0x1000];
-       k12_record_hdr_t hdr;
+       guint8* b[0x1000];
+       k12_packet_t pkt;
        gint stuffing = -1;
+       gint read_len;
+       k12_src_desc_t* src_desc;
        
        *data_offset = wth->data_offset;
        
@@ -265,11 +240,11 @@ static gboolean k12_read(wtap *wth, int *err, gchar **err_info, long *data_offse
                gint s;
                
                if (stuffing >= 0) {
-                       stuffing += hdr.len;
+                       stuffing += pkt.hdr.len;
                        
                        /* skip the whole record */
                        
-                       if ( file_read(junk,1, hdr.len - K12_HDR_LEN , wth->fh) != (gint) (hdr.len - K12_HDR_LEN) ) {
+                       if ( file_read(b,1, pkt.hdr.len - K12_HDR_LEN , wth->fh) != (gint) (pkt.hdr.len - K12_HDR_LEN) ) {
                                *err = WTAP_ERR_SHORT_READ;
                                *err_info = "record too short while reading .rf5 file";
                                return FALSE;           
@@ -279,7 +254,7 @@ static gboolean k12_read(wtap *wth, int *err, gchar **err_info, long *data_offse
                        stuffing = 0;
                }
                
-               switch ( s = get_k12_hdr(&hdr, wth, err, err_info) ) {
+               switch ( s = get_k12_hdr(&pkt.hdr, wth, err) ) {
                        case -1:
                                /* eof */
                                *err = 0;
@@ -294,66 +269,69 @@ static gboolean k12_read(wtap *wth, int *err, gchar **err_info, long *data_offse
                
                stuffing += s;
                
-       } while ( hdr.type != K12_REC_PACKET
-                         || hdr.len < hdr.frame_len + 0x20 );
-       
+       } while ( pkt.hdr.type != K12_REC_PACKET
+                         || pkt.hdr.len < pkt.hdr.frame_len + 0x20 );
        wth->data_offset += stuffing + 0x10;
+
        
-       if ( wth->file_encap == WTAP_ENCAP_PER_PACKET) {
-               wth->phdr.pkt_encap = get_encap(wth->capture.k12,hdr.port_id);
-       } else {
-               wth->phdr.pkt_encap = WTAP_ENCAP_USER0;
-       }
-       
-       /* XXX: is in there something useful in these 8 bytes ? */
-       if ( file_read(b,1,8,wth->fh) != 8 ) {
+       if ( file_read(&pkt.record,1,sizeof(pkt.record),wth->fh) != sizeof(pkt.record) ) {
                *err = WTAP_ERR_SHORT_READ;
-               *err_info = "record too short while reading .rf5 file";
                return FALSE; 
        }
        
-       wth->data_offset += 8;
-       
-       
-       /* the next 8 bytes are the timestamp */
-       if ( file_read(b,1,8,wth->fh) != 8 ) {
-               *err = WTAP_ERR_SHORT_READ;
-               *err_info = "record too short while reading .rf5 file";
-               return FALSE; 
-       }
+       wth->data_offset += sizeof(pkt.record);
+               
+       pkt.record.ts = pntohll(&pkt.record.ts);
        
-       wth->data_offset += 8;
+       wth->phdr.ts.tv_usec = (guint32) ( (pkt.record.ts % 2000000) / 2);
+       wth->phdr.ts.tv_sec = (guint32) ((pkt.record.ts / 2000000) + 631152000);
        
-       ts = pntohll(b);
+       wth->phdr.caplen = wth->phdr.len = pkt.hdr.frame_len;
        
-       wth->phdr.ts.tv_usec = (guint32) ( (ts % 2000000) / 2);
-       wth->phdr.ts.tv_sec = (guint32) ((ts / 2000000) + 631152000);
+       /* the frame */
+       buffer_assure_space(wth->frame_buffer, pkt.hdr.frame_len);
+       wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), pkt.hdr.frame_len, wth->fh, err);
+       wth->data_offset += pkt.hdr.frame_len;
        
-       wth->phdr.caplen = wth->phdr.len = hdr.frame_len;
+       /*  (undef,$vp,$vc) = unpack "C12SS";  */
        
-       /* the frame */
-       buffer_assure_space(wth->frame_buffer, hdr.frame_len);
-       wtap_file_read_expected_bytes(buffer_start_ptr(wth->frame_buffer), hdr.frame_len, wth->fh, err);
-       wth->data_offset += hdr.frame_len;
+       read_len = pkt.hdr.len - ( pkt.hdr.frame_len + 0x20);
        
-       /* XXX: should we read to a junk buffer instead of seeking? */
-       /* XXX: is there useful stuff in the trailer? */
-       if ( file_read(junk,1, hdr.len - ( hdr.frame_len + 0x20) , wth->fh) != (gint) ( hdr.len - ( hdr.frame_len + 0x20)) ) {
+       if ( file_read(b,1, read_len , wth->fh) != read_len ) {
                *err = WTAP_ERR_SHORT_READ;
-               *err_info = "record too short while reading .rf5 file";
                return FALSE;           
        }
        
-       wth->data_offset += hdr.len - ( hdr.frame_len + 0x20);
+       wth->data_offset += read_len;
+       
+       src_desc = g_hash_table_lookup(wth->capture.k12->src_by_id,GUINT_TO_POINTER(pkt.hdr.input));
+       
+       wth->pseudo_header.k12.src_id = pkt.hdr.input;
+       wth->pseudo_header.k12.src_name = src_desc ? src_desc->variable.port_name : "unknown port";
+       wth->pseudo_header.k12.stack_file = src_desc ? src_desc->variable.stack_file : "unknown port";
        
        return TRUE;
 }
 
-static gboolean k12_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_header _U_, guchar *pd, int length, int *err _U_, gchar **err_info _U_) {
+static gboolean k12_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err _U_, gchar **err_info _U_) {
+       guint8 read_buffer[0x20];
+       k12_src_desc_t* src_desc;
+       guint32 input;
        
-       if ( file_seek(wth->random_fh, seek_off+0x20, SEEK_SET, err) == -1)
+       if ( file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
                return FALSE;
        
+       if( file_read(read_buffer,1,0x20,wth->random_fh) != 0x20 )
+               return FALSE;
+       
+       input = pntohl(read_buffer + 0xC);
+       
+       src_desc = g_hash_table_lookup(wth->capture.k12->src_by_id,GUINT_TO_POINTER(input));
+       
+       pseudo_header->k12.src_id = input;
+       pseudo_header->k12.src_name = src_desc ? src_desc->variable.port_name : "unknown port";
+       pseudo_header->k12.stack_file = src_desc ? src_desc->variable.stack_file : "unknown stack_file";
+       
        if ( file_read(pd, 1, length, wth->random_fh) != length) {
                *err = file_error(wth->random_fh);
                if (*err == 0)
@@ -364,25 +342,79 @@ static gboolean k12_seek_read(wtap *wth, long seek_off, union wtap_pseudo_header
        return TRUE;
 }
 
-static void destroy_k12_file_data(k12_t* file_data) {
-       guint i;
-       for (i =0; i<=file_data->stack_encap_p; i++) {
-               if (file_data->stack_encap[i].name) {
-                       g_free(file_data->stack_encap[i].name);
-                       file_data->stack_encap[i].name = NULL;
-               }
-       }
+static k12_t* new_k12_file_data() {
+       k12_t* fd = g_malloc(sizeof(k12_t));
        
-       if (file_data->port_encaps) {
-               g_ptr_array_free(file_data->port_encaps,TRUE);
-       }
+       fd->file_len = 0;
+       fd->num_of_records = 0;
+       fd->src_by_name = g_hash_table_new(g_str_hash,g_str_equal);
+       fd->src_by_id = g_hash_table_new(g_direct_hash,g_direct_equal);
+       
+       return fd;
+}
+
+static gboolean destroy_srcdsc(gpointer k _U_, gpointer v, gpointer p _U_) {
+       k12_src_desc_t* rec = v;
+       
+       if(rec->variable.extra_blob)
+               g_free(rec->variable.extra_blob);
        
+       if(rec->variable.port_name)
+               g_free(rec->variable.port_name);
+       
+       if(rec->variable.stack_file)
+               g_free(rec->variable.stack_file);
+       
+       g_free(rec);
+       
+       return TRUE;
+}
+
+static void destroy_k12_file_data(k12_t* fd) {
+       g_hash_table_destroy(fd->src_by_id);
+       g_hash_table_foreach_remove(fd->src_by_name,destroy_srcdsc,NULL);       
+       g_hash_table_destroy(fd->src_by_name);
+       g_free(fd);
 }
 
 static void k12_close(wtap *wth) {
        destroy_k12_file_data(wth->capture.k12);
 }
 
+static void add_k12_src(k12_t* fd, k12_src_desc_t* rec) {
+       k12_src_desc_t* r = g_memdup(rec,sizeof(k12_src_desc_t));
+       
+       g_hash_table_insert(fd->src_by_id,GUINT_TO_POINTER(r->hdr.input),r);
+       g_hash_table_insert(fd->src_by_name,r->variable.stack_file,r);
+}
+
+
+
+static int get_srcdsc_record(k12_src_desc_t* rec, FILE* fp, int *err) {
+       gchar read_buffer[0x1000];
+       
+       if ( file_read( read_buffer, 1, 0x14, fp) != 0x14 ) {
+               *err = WTAP_ERR_SHORT_READ;
+               return FALSE;
+       }
+       
+       /*      XXX missing some  */
+       rec->record.extra_len = pntohs( read_buffer + 0xE );
+       rec->record.name_len = pntohs( read_buffer + 0x10 );
+       rec->record.stack_len = pntohs( read_buffer + 0x12 );
+       
+       if (file_read(read_buffer,1, rec->hdr.len - 0x24,fp) != (gint)rec->hdr.len - 0x24 ) {
+               *err = WTAP_ERR_SHORT_READ;
+               return FALSE;
+       }
+       
+       rec->variable.extra_blob = g_memdup(read_buffer, rec->record.extra_len);
+       rec->variable.port_name = g_memdup(read_buffer + rec->record.extra_len,rec->record.name_len);
+       rec->variable.stack_file = g_memdup(read_buffer + rec->record.extra_len + rec->record.name_len,rec->record.stack_len);
+       
+       return TRUE;
+}
+
 /*
  * The first few records of a file contain a description of the file:
  *   - the description of the sources (ports or circuits)
@@ -392,17 +424,12 @@ static void k12_close(wtap *wth) {
  * some other (summary?) records.
  */
 
-int k12_open(wtap *wth, int *err, gchar **err_info) {
+int k12_open(wtap *wth, int *err, gchar **err_info _U_) {
        gchar read_buffer[0x1000];
-       k12_record_hdr_t hdr;
        long offset = 0;
-       gchar* stack_file;
-       gchar* port_name;
-       guint32 name_len;
-       guint32 stack_len;
-       gint read_len;
-       guint stuffing;
        k12_t* file_data;
+       k12_src_desc_t rec;
+       gint stuffing;
        
        /*
         *  let's check the magic number.
@@ -415,21 +442,18 @@ int k12_open(wtap *wth, int *err, gchar **err_info) {
        }
        
        /* the lenght of the file is in the next 4byte word */
-       if ( file_read(read_buffer,1,4,wth->fh) != 4 ) {
+       if ( file_read(read_buffer,1,8,wth->fh) != 8 ) {
                return -1;
        } 
-       
-       file_data = g_malloc(sizeof(k12_t));
-       
-       file_data->stack_encap_p = 0;
-       file_data->port_encaps = g_ptr_array_new();
-       file_data->stack_encap = g_memdup(virgin_stack_encap,sizeof(virgin_stack_encap));
+       file_data = new_k12_file_data();
+
        file_data->file_len = pntohl( read_buffer );
+       file_data->num_of_records = pntohl( read_buffer + 4 );
        
        /*
         * we don't know yet what's in the file header
         */
-       if (file_read(read_buffer,1,0x204,wth->fh) != 0x204 ) {
+       if (file_read(read_buffer,1,0x200,wth->fh) != 0x200 ) {
                destroy_k12_file_data(file_data);
                return -1;
        }
@@ -441,16 +465,22 @@ int k12_open(wtap *wth, int *err, gchar **err_info) {
         */
        
        do {
+               memset(&rec,0,sizeof(k12_src_desc_t));
+
                if (offset > 0x10000) {
                        /* too much to be ok. */
                        return 0;
                }
                
-               stuffing = get_k12_hdr(&hdr, wth, err, err_info);
+               stuffing = get_k12_hdr(&(rec.hdr), wth, err);
+               
+               if ( stuffing < 0) {
+                       return 0;
+               }
                
                offset += stuffing;
                
-               if ( hdr.type == K12_REC_PACKET) {
+               if ( rec.hdr.type == K12_REC_PACKET) {
                        /*
                         * we are at the first packet record, rewind and leave.
                         */
@@ -460,69 +490,25 @@ int k12_open(wtap *wth, int *err, gchar **err_info) {
                        }
                        
                        break;
-               } else if (hdr.type == K12_REC_SRCDSC) {
-                       
-                       if ( file_read( read_buffer, 1, 0x14, wth->fh) != 0x14 ) {
-                               *err = WTAP_ERR_SHORT_READ;
-                               return FALSE;
-                       }
-                       
-                       name_len = pntohs( read_buffer + 0x10 );
-                       stack_len = pntohs( read_buffer + 0x12 );
-                       
+               } else if (rec.hdr.type == K12_REC_SRCDSC) {
                        
-                       read_len = hdr.len - (0x10 + 0x14 + name_len + stack_len);
-                       
-                       if (read_len > 0) {
-                               /* skip the still unknown part */
-                               if (file_read(read_buffer,1, read_len,wth->fh) != read_len ) {
-                                       destroy_k12_file_data(file_data);
-                                       *err = WTAP_ERR_SHORT_READ;
-                                       return -1;
-                               }
-                       } else if (read_len < 0) {
+                       if(!get_srcdsc_record(&rec, wth->fh, err)) {
                                destroy_k12_file_data(file_data);
-                               *err = WTAP_ERR_BAD_RECORD;
-                               return -1;
-                       }
-                       
-                       /* the rest of the record contains two null terminated strings:
-                               the source label and the "stack" filename */
-                       if ( file_read(read_buffer, 1, name_len, wth->fh) != (int)name_len ) {
-                               destroy_k12_file_data(file_data);
-                               *err = WTAP_ERR_SHORT_READ;
-                               *err_info = "record too short while reading .rf5 file";
-                               return -1;
-                       }
-                       
-                       port_name = g_strndup(read_buffer,stack_len);
-                       
-                       if ( file_read(read_buffer, 1, stack_len, wth->fh) != (int)stack_len ) {
-                               destroy_k12_file_data(file_data);
-                               *err = WTAP_ERR_SHORT_READ;
-                               *err_info = "record too short while reading .rf5 file";
                                return -1;
                        }
+
+                       offset += rec.hdr.len;
                        
-                       stack_file =g_strndup(read_buffer,stack_len);
+                       add_k12_src(file_data,&rec);
                        
-                       if (choose_encap(file_data,hdr.port_id,stack_file) == WTAP_NUM_ENCAP_TYPES ) {
-                               destroy_k12_file_data(file_data);
-                               /* more encapsulation types than we can handle */
-                               return 0;
-                       }
-                       
-                       offset += hdr.len;
                        continue;
                } else {
-                       /* we don't need these other fellows */
-                       
-                       if (file_read(read_buffer,1, hdr.len - K12_HDR_LEN, wth->fh) != (int) hdr.len - K12_HDR_LEN ) {
+                       if (file_read(read_buffer,1, rec.hdr.len - K12_HDR_LEN, wth->fh) != (int) rec.hdr.len - K12_HDR_LEN ) {
                                destroy_k12_file_data(file_data);
                                return -1;
                        }
                        
-                       offset += hdr.len;
+                       offset += rec.hdr.len;
                        
                        continue;
                }
@@ -530,6 +516,7 @@ int k12_open(wtap *wth, int *err, gchar **err_info) {
        
        wth->data_offset = offset;
        wth->file_type = WTAP_FILE_K12;
+       wth->file_encap = WTAP_ENCAP_K12;
        wth->snapshot_length = 0;
        wth->subtype_read = k12_read;
        wth->subtype_seek_read = k12_seek_read;
@@ -540,11 +527,6 @@ int k12_open(wtap *wth, int *err, gchar **err_info) {
                we will use that for the whole file so we can
                use more formats to save to */
        
-       if (file_data->port_encaps->len == 1) {
-               wth->file_encap = ((k12_stack_encap_t*)g_ptr_array_index(file_data->port_encaps,0))->encap;
-       } else {
-               wth->file_encap = WTAP_ENCAP_PER_PACKET;
-       }
        
        return 1;
 }
index 2e299be2684dce852c51e01223782e144ff776f9..3d4f9f86da8daea0398fffbad7bd163ccd2b1db6 100644 (file)
 #define WTAP_GCOM_TIE1                         78
 #define WTAP_GCOM_SERIAL                       79
 #define WTAP_ENCAP_NETTL_X25                   80
+#define WTAP_ENCAP_K12                                 81
 /* last WTAP_ENCAP_ value + 1 */
-#define WTAP_NUM_ENCAP_TYPES                   81
+#define WTAP_NUM_ENCAP_TYPES                   82
 
 /* File types that can be read by wiretap.
    We support writing some many of these file types, too, so we
@@ -450,6 +451,14 @@ struct mtp2_phdr {
        guint16 link_number;  
 };
 
+/* Packet "pseudo-header" for K12 files. */
+
+struct k12_phdr {
+       guint32 src_id;
+       gchar* src_name;
+       gchar* stack_file;
+};
+
 union wtap_pseudo_header {
        struct eth_phdr         eth;
        struct x25_phdr         x25;
@@ -462,6 +471,7 @@ union wtap_pseudo_header {
        struct irda_phdr        irda;
        struct nettl_phdr       nettl;
        struct mtp2_phdr        mtp2;
+       struct k12_phdr         k12;
 };
 
 struct wtap_pkthdr {