Remove write capabilities from wtap_optionblocks.
[metze/wireshark/wip.git] / wiretap / daintree-sna.c
index c6c51b351f02e34829a7bd8ac590d8f73fd28936..233c08e2744dc923d868ddca0eddf24908ce6313 100644 (file)
@@ -3,16 +3,14 @@
  * Sensor Network Analyzer for 802.15.4 radios
  * Copyright 2009, Exegin Technologies Limited <fff@exegin.com>
  *
- * $Id$
- *
  * Wireshark - Network traffic analyzer
  * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
- * Started with packetlogger.c as a template, but little packetlogger code 
- * remains. Borrowed many snippets from dbs-etherwatch.c, the 
- * daintree_sna_hex_char function having the largest chunk.
- * 
+ * Started with packetlogger.c as a template, but little packetlogger code
+ * remains. Borrowed many snippets from dbs-etherwatch.c, the
+ * daintree_sna_process_hex_data function having the largest chunk.
+ *
  * 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
@@ -29,7 +27,7 @@
  * USA.
  */
 
-/* This module reads capture files saved by Daintree's Sensor Network Analyzer. 
+/* This module reads capture files saved by Daintree's Sensor Network Analyzer.
  * Daintree captures are plain text files with a two line header,
  * followed by packet records, one per line, with whitespace separated fields
  * consisting of: packet number, time, bytes of capture data, capture data,
@@ -37,7 +35,7 @@
  */
 
 /* Example capture file:
+
 #Format=4
 # SNA v2.2.0.4 SUS:20090709 ACT:819705
 1 1233783799.326400 10 030809ffffffff07ffff 42 1 -69 25 2 0 1 32767
 
 #include "config.h"
 
-#include <glib.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <string.h>
-#include <ctype.h>
 
-#include "wtap.h"
 #include "wtap-int.h"
-#include "buffer.h"
 #include "file_wrappers.h"
 #include "daintree-sna.h"
 
@@ -83,43 +76,49 @@ static gboolean daintree_sna_read(wtap *wth, int *err, gchar **err_info,
        gint64 *data_offset);
 
 static gboolean daintree_sna_seek_read(wtap *wth, gint64 seek_off,
-       union wtap_pseudo_header *pseudo_header _U_,
-       guint8 *pd, int len, int *err,
-       gchar **err_info);
+       struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
 
-static guint daintree_sna_hex_char(guchar *str, int *err);
+static gboolean daintree_sna_read_packet(FILE_T fh, struct wtap_pkthdr *phdr,
+       Buffer *buf, int *err, gchar **err_info);
 
 /* Open a file and determine if it's a Daintree file */
-int daintree_sna_open(wtap *wth, int *err _U_, gchar **err_info _U_)
+wtap_open_return_val daintree_sna_open(wtap *wth, int *err, gchar **err_info)
 {
        char readLine[DAINTREE_MAX_LINE_SIZE];
-       guint i; 
 
        /* get first line of file header */
-       if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) return 0;
+       if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) {
+               *err = file_error(wth->fh, err_info);
+               if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+                       return WTAP_OPEN_ERROR;
+               return WTAP_OPEN_NOT_MINE;
+       }
 
        /* check magic text */
-       i = 0;
-       while (i < DAINTREE_MAGIC_TEXT_SIZE) {
-               if (readLine[i] != daintree_magic_text[i]) return 0; /* not daintree format */
-               i++;
-       } 
+       if (memcmp(readLine, daintree_magic_text, DAINTREE_MAGIC_TEXT_SIZE) != 0)
+               return WTAP_OPEN_NOT_MINE; /* not daintree format */
 
        /* read second header line */
-       if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) return 0;
-       if (readLine[0] != COMMENT_LINE) return 0; /* daintree files have a two line header */
+       if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh)==NULL) {
+               *err = file_error(wth->fh, err_info);
+               if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+                       return WTAP_OPEN_ERROR;
+               return WTAP_OPEN_NOT_MINE;
+       }
+       if (readLine[0] != COMMENT_LINE)
+               return WTAP_OPEN_NOT_MINE; /* daintree files have a two line header */
 
        /* set up the pointers to the handlers for this file type */
        wth->subtype_read = daintree_sna_read;
        wth->subtype_seek_read = daintree_sna_seek_read;
 
        /* set up for file type */
-       wth->file_type = WTAP_FILE_DAINTREE_SNA;
+       wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_DAINTREE_SNA;
        wth->file_encap = WTAP_ENCAP_IEEE802_15_4_NOFCS;
-       wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+       wth->file_tsprec = WTAP_TSPREC_USEC;
        wth->snapshot_length = 0; /* not available in header */
 
-       return 1; /* it's a Daintree file */
+       return WTAP_OPEN_MINE; /* it's a Daintree file */
 }
 
 /* Read the capture file sequentially
@@ -127,142 +126,106 @@ int daintree_sna_open(wtap *wth, int *err _U_, gchar **err_info _U_)
 static gboolean
 daintree_sna_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
 {
-       char readLine[DAINTREE_MAX_LINE_SIZE];
-       guint64 seconds;
-       char readData[READDATA_BUF_SIZE];
-
        *data_offset = file_tell(wth->fh);
 
-       /* we've only seen file header lines starting with '#', but
-        * if others appear in the file, they are tossed */
-       do {
-               if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->fh) == NULL) {
-                       *err = file_error(wth->fh, err_info);
-                       return FALSE; /* all done */
-               }
-       } while (readLine[0] == COMMENT_LINE);
-
-       wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
-
-       /* parse one line of capture data */
-       if (sscanf(readLine, "%*s %18" G_GINT64_MODIFIER "u.%9d %9u %" READDATA_MAX_FIELD_SIZE "s",
-           &seconds, &wth->phdr.ts.nsecs, &wth->phdr.len, readData) != 4) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("daintree_sna: invalid read record");
-               return FALSE;
-       }
+       /* parse that line and the following packet data */
+       return daintree_sna_read_packet(wth->fh, &wth->phdr,
+           wth->frame_buffer, err, err_info);
+}
 
-       /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
-       if (wth->phdr.len <= FCS_LENGTH) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup_printf("daintree_sna: packet length <= %u bytes, no frame data present",
-                   FCS_LENGTH);
-               return FALSE;
-       }
-       wth->phdr.len -= FCS_LENGTH;
-
-       wth->phdr.ts.secs = (time_t) seconds;
-       wth->phdr.ts.nsecs *= 1000; /* convert mS to nS */
-
-       /* convert packet data from ASCII string to hex, sanity-check its length against what we assume is the
-        * packet length field, write data to frame buffer */
-       if ((wth->phdr.caplen = daintree_sna_hex_char(readData, err)) > FCS_LENGTH) {
-               /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
-               wth->phdr.caplen -= FCS_LENGTH;
-               if (wth->phdr.caplen <= wth->phdr.len) {
-                       buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
-                       memcpy(buffer_start_ptr(wth->frame_buffer), readData, wth->phdr.caplen);
-               } else {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup_printf("daintree_sna: capture length (%u) > packet length (%u)",
-                               wth->phdr.caplen, wth->phdr.len);
-                       return FALSE;
-               }
-       } else {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("daintree_sna: invalid packet data");
+/* Read the capture file randomly
+ * Wireshark opens the capture file for random access when displaying user-selected packets */
+static gboolean
+daintree_sna_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
+       Buffer *buf, int *err, gchar **err_info)
+{
+       if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
                return FALSE;
-       }
 
-       return TRUE;
+       /* parse that line and the following packet data */
+       return daintree_sna_read_packet(wth->random_fh, phdr, buf, err,
+           err_info);
 }
 
-/* Read the capture file randomly 
- * Wireshark opens the capture file for random access when displaying user-selected packets */
+/* Read a header line, scan it, and fill in a struct wtap_pkthdr.
+ * Then convert packet data from ASCII hex string to binary in place,
+ * sanity-check its length against what we assume is the packet length field,
+ * and copy it into a Buffer. */
 static gboolean
-daintree_sna_seek_read(wtap *wth, gint64 seek_off, union wtap_pseudo_header
-       *pseudo_header _U_, guint8 *pd, int len, int *err,
-       gchar **err_info)
+daintree_sna_read_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+    int *err, gchar **err_info)
 {
+       guint64 seconds;
+       int useconds;
        char readLine[DAINTREE_MAX_LINE_SIZE];
-       guint pkt_len;
        char readData[READDATA_BUF_SIZE];
+       guchar *str = (guchar *)readData;
+       guint bytes;
+       guint8 *p;
 
-       if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
-               return FALSE;
-
-       /* It appears only file header lines start with '#', but
-        * if we find any others, we toss them */
+       /* we've only seen file header lines starting with '#', but
+        * if others appear in the file, they are tossed */
        do {
-               if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, wth->random_fh) == NULL) {
-                       *err = file_error(wth->random_fh, err_info);
+               if (file_gets(readLine, DAINTREE_MAX_LINE_SIZE, fh) == NULL) {
+                       *err = file_error(fh, err_info);
                        return FALSE; /* all done */
                }
        } while (readLine[0] == COMMENT_LINE);
 
-       /* ignore all but packet data, since the sequential read pass stored everything else */
-       if (sscanf(readLine, "%*s %*u.%*u %*u %" READDATA_MAX_FIELD_SIZE "s", readData) != 1) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("daintree_sna: corrupted seek record");
-               return FALSE;
-       }
+       phdr->rec_type = REC_TYPE_PACKET;
+       phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
 
-       /* convert packet data from ASCII hex string to guchar */
-       if ((pkt_len = daintree_sna_hex_char(readData, err)) <= FCS_LENGTH) {
+       if (sscanf(readLine, "%*s %18" G_GINT64_MODIFIER "u.%9d %9u %" READDATA_MAX_FIELD_SIZE "s",
+           &seconds, &useconds, &phdr->len, readData) != 4) {
                *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("daintree_sna: corrupted packet data");
+               *err_info = g_strdup("daintree_sna: invalid read record");
                return FALSE;
        }
 
-       pkt_len -= FCS_LENGTH; /* remove padded bytes that Daintree stores instead of FCS */
-
-       if (pkt_len == (guint) len) {
-               /* move to frame buffer for dissection */
-               memcpy(pd, readData, pkt_len);
-       } else {
+       /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
+       if (phdr->len <= FCS_LENGTH) {
                *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("daintree-sna: corrupted frame");
+               *err_info = g_strdup_printf("daintree_sna: packet length <= %u bytes, no frame data present",
+                   FCS_LENGTH);
                return FALSE;
-       } 
-
-       return TRUE;
-}
+       }
+       phdr->len -= FCS_LENGTH;
 
-/* Convert an ASCII hex string to guint8 */
-static guint
-daintree_sna_hex_char(guchar *str, int *err _U_) {
-       guint bytes;
-       guint8 *p;
+       phdr->ts.secs = (time_t) seconds;
+       phdr->ts.nsecs = useconds * 1000; /* convert mS to nS */
 
+       /*
+        * READDATA_BUF_SIZE is < WTAP_MAX_PACKET_SIZE, and is the maximum
+        * number of bytes of packet data we can generate, so we don't
+        * need to check the packet length.
+        */
        p = str; /* overlay source buffer */
        bytes = 0;
        /* convert hex string to guint8 */
        while(*str) {
-               if (!isxdigit((guchar)*str)) return 0;
                /* most significant nibble */
-               if(isdigit((guchar)*str)) {
+               if (!g_ascii_isxdigit(*str)) {
+                       *err = WTAP_ERR_BAD_FILE;
+                       *err_info = g_strdup("daintree_sna: non-hex digit in hex data");
+                       return FALSE;
+               }
+               if(g_ascii_isdigit(*str)) {
                        *p = (*str - '0') << 4;
                } else {
-                       *p = ((tolower(*str) - 'a') + 10) << 4;
+                       *p = ((g_ascii_tolower(*str) - 'a') + 10) << 4;
                }
                str++;
 
-               if (!isxdigit((guchar)*str)) return 0;
                /* least significant nibble */
-               if(isdigit((guchar)*str)) {
+               if (!g_ascii_isxdigit(*str)) {
+                       *err = WTAP_ERR_BAD_FILE;
+                       *err_info = g_strdup("daintree_sna: non-hex digit in hex data");
+                       return FALSE;
+               }
+               if(g_ascii_isdigit(*str)) {
                        *p += *str - '0';
                } else {
-                       *p += (tolower(*str) - 'a') + 10;
+                       *p += (g_ascii_tolower(*str) - 'a') + 10;
                }
                str++;
 
@@ -271,5 +234,37 @@ daintree_sna_hex_char(guchar *str, int *err _U_) {
                bytes++;
        }
 
-       return bytes;
+       /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */
+       if (bytes <= FCS_LENGTH) {
+               *err = WTAP_ERR_BAD_FILE;
+               *err_info = g_strdup_printf("daintree_sna: Only %u bytes of packet data",
+                   bytes);
+               return FALSE;
+       }
+       bytes -= FCS_LENGTH;
+       if (bytes > phdr->len) {
+               *err = WTAP_ERR_BAD_FILE;
+               *err_info = g_strdup_printf("daintree_sna: capture length (%u) > packet length (%u)",
+                   bytes, phdr->len);
+               return FALSE;
+       }
+
+       phdr->caplen = bytes;
+
+       ws_buffer_assure_space(buf, bytes);
+       memcpy(ws_buffer_start_ptr(buf), readData, bytes);
+       return TRUE;
 }
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */