kerberos dissect KERBEROS_AD_GSS_API_ETYPE_NEGOTIATION content
[metze/wireshark/wip.git] / wiretap / logcat.c
index f50b118fe304f1591fdbb3b9acf69e2c8980c232..00b0e6e5812de568e95039a8b9eae2ca69fd32f0 100644 (file)
@@ -2,29 +2,15 @@
  *
  * Copyright 2014, Michal Labedzki for Tieto Corporation
  *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * SPDX-License-Identifier: GPL-2.0-or-later
  */
 
 #include "config.h"
 
 #include <string.h>
-#include <time.h>
 
 #include "wtap-int.h"
 #include "file_wrappers.h"
-#include <wsutil/buffer.h>
 
 #include "logcat.h"
 
@@ -38,9 +24,16 @@ static gchar get_priority(const guint8 priority) {
     return priorities[priority];
 }
 
-static gint detect_version(wtap *wth, int *err, gchar **err_info)
+/*
+ * Returns:
+ *
+ *  -2 if we get an EOF at the beginning;
+ *  -1 on an I/O error;
+ *  0 if the record doesn't appear to be valid;
+ *  1-{max gint} as a version number if we got a valid record.
+ */
+static gint detect_version(FILE_T fh, int *err, gchar **err_info)
 {
-    gint                     bytes_read;
     guint16                  payload_length;
     guint16                  hdr_size;
     guint16                  read_sofar;
@@ -56,32 +49,34 @@ static gint detect_version(wtap *wth, int *err, gchar **err_info)
     guint16                  msg_len;
 
     /* 16-bit payload length */
-    bytes_read = file_read(&tmp, 2, wth->fh);
-    if (bytes_read != 2) {
-        *err = file_error(wth->fh, err_info);
-        if (*err == 0 && bytes_read != 0)
-            *err = WTAP_ERR_SHORT_READ;
-        return -1;
+    if (!wtap_read_bytes_or_eof(fh, &tmp, 2, err, err_info)) {
+        if (*err == 0) {
+            /*
+             * Got an EOF at the beginning.
+             */
+            return -2;
+        }
+        if (*err != WTAP_ERR_SHORT_READ)
+            return -1;
+        return 0;
     }
     payload_length = pletoh16(&tmp);
 
-    /* 16-bit header length (or padding, equal to 0x0000) */
-    bytes_read = file_read(&tmp, 2, wth->fh);
-    if (bytes_read != 2) {
-        *err = file_error(wth->fh, err_info);
-        if (*err == 0 && bytes_read != 0)
-            *err = WTAP_ERR_SHORT_READ;
-        return -1;
-    }
-    hdr_size = pletoh16(&tmp);
-    read_sofar = 4;
-
     /* must contain at least priority and two nulls as separator */
     if (payload_length < 3)
-        return -1;
+        return 0;
     /* payload length may not exceed the maximum payload size */
     if (payload_length > LOGGER_ENTRY_MAX_PAYLOAD)
-        return -1;
+        return 0;
+
+    /* 16-bit header length (or padding, equal to 0x0000) */
+    if (!wtap_read_bytes(fh, &tmp, 2, err, err_info)) {
+        if (*err != WTAP_ERR_SHORT_READ)
+            return -1;
+        return 0;
+    }
+    hdr_size = pletoh16(&tmp);
+    read_sofar = 4;
 
     /* ensure buffer is large enough for all versions */
     buffer = (guint8 *) g_malloc(sizeof(*log_entry_v2) + payload_length);
@@ -100,18 +95,17 @@ static gint detect_version(wtap *wth, int *err, gchar **err_info)
             entry_len = sizeof(*log_entry_v2) + payload_length;
             if (hdr_size != sizeof(*log_entry_v2))
                 continue;
+        } else {
+            continue;
         }
 
-        bytes_read = file_read(buffer + read_sofar, entry_len - read_sofar,
-                wth->fh);
-        if (bytes_read != entry_len - read_sofar) {
-            *err = file_error(wth->fh, err_info);
-            if (*err == 0 && bytes_read != 0)
-                *err = WTAP_ERR_SHORT_READ;
-            /* short read, end of file? Whatever, this cannot be valid. */
-            break;
+        if (!wtap_read_bytes(fh, buffer + read_sofar, entry_len - read_sofar, err, err_info)) {
+            g_free(buffer);
+            if (*err != WTAP_ERR_SHORT_READ)
+                return -1;
+            return 0;
         }
-        read_sofar += bytes_read;
+        read_sofar += entry_len - read_sofar;
 
         /* A v2 msg has a 32-bit userid instead of v1 priority */
         if (get_priority(msg_payload[0]) == '?')
@@ -134,8 +128,9 @@ static gint detect_version(wtap *wth, int *err, gchar **err_info)
         return version;
     }
 
+    /* No version number is valid */
     g_free(buffer);
-    return -1;
+    return 0;
 }
 
 gint logcat_exported_pdu_length(const guint8 *pd) {
@@ -159,20 +154,15 @@ gint logcat_exported_pdu_length(const guint8 *pd) {
 }
 
 static gboolean logcat_read_packet(struct logcat_phdr *logcat, FILE_T fh,
-    struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
+    wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
 {
-    gint                 bytes_read;
     gint                 packet_size;
     guint16              payload_length;
     guint                tmp[2];
     guint8              *pd;
     struct logger_entry *log_entry;
 
-    bytes_read = file_read(&tmp, 2, fh);
-    if (bytes_read != 2) {
-        *err = file_error(fh, err_info);
-        if (*err == 0 && bytes_read != 0)
-            *err = WTAP_ERR_SHORT_READ;
+    if (!wtap_read_bytes_or_eof(fh, &tmp, 2, err, err_info)) {
         return FALSE;
     }
     payload_length = pletoh16(tmp);
@@ -184,6 +174,12 @@ static gboolean logcat_read_packet(struct logcat_phdr *logcat, FILE_T fh,
     } else {
         return FALSE;
     }
+    /*
+     * The maximum value of payload_length is 65535, which, even after
+     * the size of the logger entry structure is added to it, is less
+     * than WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check
+     * it.
+     */
 
     ws_buffer_assure_space(buf, packet_size);
     pd = ws_buffer_start_ptr(buf);
@@ -193,22 +189,18 @@ static gboolean logcat_read_packet(struct logcat_phdr *logcat, FILE_T fh,
     memcpy(pd, tmp, 2);
 
     /* Read the rest of the packet. */
-    bytes_read = file_read(pd + 2, packet_size - 2, fh);
-    if (bytes_read != packet_size - 2) {
-        *err = file_error(fh, err_info);
-        if (*err == 0)
-            *err = WTAP_ERR_SHORT_READ;
+    if (!wtap_read_bytes(fh, pd + 2, packet_size - 2, err, err_info)) {
         return FALSE;
     }
 
-    phdr->rec_type = REC_TYPE_PACKET;
-    phdr->presence_flags = WTAP_HAS_TS;
-    phdr->ts.secs = (time_t) GINT32_FROM_LE(log_entry->sec);
-    phdr->ts.nsecs = GINT32_FROM_LE(log_entry->nsec);
-    phdr->caplen = packet_size;
-    phdr->len = packet_size;
+    rec->rec_type = REC_TYPE_PACKET;
+    rec->presence_flags = WTAP_HAS_TS;
+    rec->ts.secs = (time_t) GINT32_FROM_LE(log_entry->sec);
+    rec->ts.nsecs = GINT32_FROM_LE(log_entry->nsec);
+    rec->rec_header.packet_header.caplen = packet_size;
+    rec->rec_header.packet_header.len = packet_size;
 
-    phdr->pseudo_header.logcat.version = logcat->version;
+    rec->rec_header.packet_header.pseudo_header.logcat.version = logcat->version;
 
     return TRUE;
 }
@@ -219,18 +211,18 @@ static gboolean logcat_read(wtap *wth, int *err, gchar **err_info,
     *data_offset = file_tell(wth->fh);
 
     return logcat_read_packet((struct logcat_phdr *) wth->priv, wth->fh,
-        &wth->phdr, wth->frame_buffer, err, err_info);
+        &wth->rec, wth->rec_data, err, err_info);
 }
 
 static gboolean logcat_seek_read(wtap *wth, gint64 seek_off,
-    struct wtap_pkthdr *phdr, Buffer *buf,
+    wtap_rec *rec, Buffer *buf,
     int *err, gchar **err_info)
 {
     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
         return FALSE;
 
     if (!logcat_read_packet((struct logcat_phdr *) wth->priv, wth->random_fh,
-         phdr, buf, err, err_info)) {
+         rec, buf, err, err_info)) {
         if (*err == 0)
             *err = WTAP_ERR_SHORT_READ;
         return FALSE;
@@ -238,33 +230,52 @@ static gboolean logcat_seek_read(wtap *wth, gint64 seek_off,
     return TRUE;
 }
 
-int logcat_open(wtap *wth, int *err, gchar **err_info _U_)
+wtap_open_return_val logcat_open(wtap *wth, int *err, gchar **err_info)
 {
-    int                 local_err;
-    gchar              *local_err_info;
     gint                version;
     gint                tmp_version;
     struct logcat_phdr *logcat;
 
     /* check first 3 packets (or 2 or 1 if EOF) versions to check file format is correct */
-    version = detect_version(wth, &local_err, &local_err_info);
-    if (version <= 0)
-        return 0;
-
-    tmp_version = detect_version(wth, &local_err, &local_err_info);
-    if (tmp_version < 0 && !file_eof(wth->fh)) {
-        return 0;
-    } else if (tmp_version > 0) {
-        if (tmp_version != version)
-            return 0;
+    version = detect_version(wth->fh, err, err_info); /* first packet */
+    if (version == -1)
+        return WTAP_OPEN_ERROR; /* I/O error */
+    if (version == 0)
+        return WTAP_OPEN_NOT_MINE;  /* not a logcat file */
+    if (version == -2)
+        return WTAP_OPEN_NOT_MINE;  /* empty file, so not any type of file */
+
+    tmp_version = detect_version(wth->fh, err, err_info); /* second packet */
+    if (tmp_version == -1)
+        return WTAP_OPEN_ERROR; /* I/O error */
+    if (tmp_version == 0)
+        return WTAP_OPEN_NOT_MINE;  /* not a logcat file */
+    if (tmp_version != -2) {
+        /* we've read two packets; do they have the same version? */
+        if (tmp_version != version) {
+            /* no, so this is presumably not a logcat file */
+            return WTAP_OPEN_NOT_MINE;
+        }
 
-        tmp_version = detect_version(wth, &local_err, &local_err_info);
-        if (tmp_version != version && !file_eof(wth->fh))
-            return 0;
+        tmp_version = detect_version(wth->fh, err, err_info); /* third packet */
+        if (tmp_version < 0)
+            return WTAP_OPEN_ERROR; /* I/O error */
+        if (tmp_version == 0)
+            return WTAP_OPEN_NOT_MINE;  /* not a logcat file */
+        if (tmp_version != -2) {
+            /*
+             * we've read three packets and the first two have the same
+             * version; does the third have the same version?
+             */
+            if (tmp_version != version) {
+                /* no, so this is presumably not a logcat file */
+                return WTAP_OPEN_NOT_MINE;
+            }
+        }
     }
 
     if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
-        return -1;
+        return WTAP_OPEN_ERROR;
 
     logcat = (struct logcat_phdr *) g_malloc(sizeof(struct logcat_phdr));
     logcat->version = version;
@@ -277,9 +288,9 @@ int logcat_open(wtap *wth, int *err, gchar **err_info _U_)
 
     wth->subtype_read = logcat_read;
     wth->subtype_seek_read = logcat_seek_read;
-    wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+    wth->file_tsprec = WTAP_TSPREC_USEC;
 
-    return 1;
+    return WTAP_OPEN_MINE;
 }
 
 int logcat_dump_can_write_encap(int encap)
@@ -288,24 +299,24 @@ int logcat_dump_can_write_encap(int encap)
         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
 
     if (encap != WTAP_ENCAP_LOGCAT && encap != WTAP_ENCAP_WIRESHARK_UPPER_PDU)
-        return WTAP_ERR_UNSUPPORTED_ENCAP;
+        return WTAP_ERR_UNWRITABLE_ENCAP;
 
     return 0;
 }
 
 static gboolean logcat_binary_dump(wtap_dumper *wdh,
-    const struct wtap_pkthdr *phdr,
-    const guint8 *pd, int *err)
+    const wtap_rec *rec,
+    const guint8 *pd, int *err, gchar **err_info _U_)
 {
     int caplen;
 
     /* We can only write packet records. */
-    if (phdr->rec_type != REC_TYPE_PACKET) {
-        *err = WTAP_ERR_REC_TYPE_UNSUPPORTED;
+    if (rec->rec_type != REC_TYPE_PACKET) {
+        *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
         return FALSE;
     }
 
-    caplen = phdr->caplen;
+    caplen = rec->rec_header.packet_header.caplen;
 
     /* Skip EXPORTED_PDU*/
     if (wdh->encap == WTAP_ENCAP_WIRESHARK_UPPER_PDU) {
@@ -324,21 +335,9 @@ static gboolean logcat_binary_dump(wtap_dumper *wdh,
     return TRUE;
 }
 
-gboolean logcat_binary_dump_open(wtap_dumper *wdh, int *err)
+gboolean logcat_binary_dump_open(wtap_dumper *wdh, int *err _U_)
 {
     wdh->subtype_write = logcat_binary_dump;
-    wdh->subtype_close = NULL;
-
-    switch (wdh->encap) {
-        case WTAP_ENCAP_LOGCAT:
-        case WTAP_ENCAP_WIRESHARK_UPPER_PDU:
-            wdh->tsprecision = WTAP_FILE_TSPREC_USEC;
-            break;
-
-        default:
-            *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
-            return FALSE;
-    }
 
     return TRUE;
 }