file_read() can return -1; don't just blindly add it to a previous
[obnox/wireshark/wip.git] / wiretap / snoop.c
index b5aab4b46dd790e21834b9b644115877bb5ec9d2..89cc8a5f8a8cc5e41e71757f197d1136eba8be6e 100644 (file)
@@ -94,12 +94,12 @@ static gboolean snoop_seek_read(wtap *wth, gint64 seek_off,
     union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
     int *err, gchar **err_info);
 static gboolean snoop_read_atm_pseudoheader(FILE_T fh,
-    union wtap_pseudo_header *pseudo_header, int *err);
+    union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
 static gboolean snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
     union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info,
     int *header_size);
 static gboolean snoop_read_rec_data(FILE_T fh, guchar *pd, int length,
-    int *err);
+    int *err, gchar **err_info);
 static gboolean snoop_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
 
@@ -213,6 +213,18 @@ int snoop_open(wtap *wth, int *err, gchar **err_info)
                WTAP_ENCAP_UNKNOWN,     /* 100BaseT (but that's just Ethernet) */
        };
        #define NUM_SNOOP_ENCAPS (sizeof snoop_encap / sizeof snoop_encap[0])
+       #define SNOOP_PRIVATE_BIT 0x80000000
+       static const int snoop_private_encap[] = {
+               WTAP_ENCAP_UNKNOWN,     /* Not Used */
+               WTAP_ENCAP_UNKNOWN,     /* IPv4 Tunnel Link */
+               WTAP_ENCAP_UNKNOWN,     /* IPv6 Tunnel Link */
+               WTAP_ENCAP_UNKNOWN,     /* Virtual network interface */
+               WTAP_ENCAP_UNKNOWN,     /* IEEE 802.11 */
+               WTAP_ENCAP_IPNET,       /* ipnet(7D) link */
+               WTAP_ENCAP_UNKNOWN,     /* IPMP stub interface */
+               WTAP_ENCAP_UNKNOWN,     /* 6to4 Tunnel Link */
+       };
+       #define NUM_SNOOP_PRIVATE_ENCAPS (sizeof snoop_private_encap / sizeof snoop_private_encap[0])
        static const int shomiti_encap[] = {
                WTAP_ENCAP_ETHERNET,    /* IEEE 802.3 */
                WTAP_ENCAP_UNKNOWN,     /* IEEE 802.4 Token Bus */
@@ -239,9 +251,9 @@ int snoop_open(wtap *wth, int *err, gchar **err_info)
 
        /* Read in the string that should be at the start of a "snoop" file */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
+       bytes_read = file_read(magic, sizeof magic, wth->fh);
        if (bytes_read != sizeof magic) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err != 0)
                        return -1;
                return 0;
@@ -254,9 +266,9 @@ int snoop_open(wtap *wth, int *err, gchar **err_info)
 
        /* Read the rest of the header. */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
+       bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
        if (bytes_read != sizeof hdr) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err != 0)
                        return -1;
                return 0;
@@ -315,9 +327,9 @@ int snoop_open(wtap *wth, int *err, gchar **err_info)
 
        /* Read first record header. */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(&rec_hdr, 1, sizeof rec_hdr, wth->fh);
+       bytes_read = file_read(&rec_hdr, sizeof rec_hdr, wth->fh);
        if (bytes_read != sizeof rec_hdr) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0 && bytes_read != 0)
                        *err = WTAP_ERR_SHORT_READ;
                if (*err != 0) {
@@ -382,6 +394,18 @@ int snoop_open(wtap *wth, int *err, gchar **err_info)
 
                /* This is a Shomiti file */
                wth->file_type = WTAP_FILE_SHOMITI;
+       } else if (hdr.network & SNOOP_PRIVATE_BIT) {
+               if ((hdr.network^SNOOP_PRIVATE_BIT) >= NUM_SNOOP_PRIVATE_ENCAPS
+                   || snoop_private_encap[hdr.network^SNOOP_PRIVATE_BIT] == WTAP_ENCAP_UNKNOWN) {
+                       *err = WTAP_ERR_UNSUPPORTED_ENCAP;
+                       *err_info = g_strdup_printf("snoop: private network type %u unknown or unsupported",
+                           hdr.network);
+                       return -1;
+               }
+               file_encap = snoop_private_encap[hdr.network^SNOOP_PRIVATE_BIT];
+
+               /* This is a snoop file */
+               wth->file_type = WTAP_FILE_SNOOP;
        } else {
                if (hdr.network >= NUM_SNOOP_ENCAPS
                    || snoop_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
@@ -437,9 +461,9 @@ static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
 
        /* Read record header. */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
+       bytes_read = file_read(&hdr, sizeof hdr, wth->fh);
        if (bytes_read != sizeof hdr) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0 && bytes_read != 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -491,7 +515,7 @@ static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
                        return FALSE;
                }
                if (!snoop_read_atm_pseudoheader(wth->fh, &wth->pseudo_header,
-                   err))
+                   err, err_info))
                        return FALSE;   /* Read error */
 
                /*
@@ -542,7 +566,7 @@ static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
 
        buffer_assure_space(wth->frame_buffer, packet_size);
        if (!snoop_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
-           packet_size, err))
+           packet_size, err, err_info))
                return FALSE;   /* Read error */
        wth->data_offset += packet_size;
 
@@ -583,9 +607,9 @@ static gboolean snoop_read(wtap *wth, int *err, gchar **err_info,
                if ((unsigned)bytes_to_read > sizeof padbuf)
                        bytes_to_read = sizeof padbuf;
                errno = WTAP_ERR_CANT_READ;
-               bytes_read = file_read(padbuf, 1, bytes_to_read, wth->fh);
+               bytes_read = file_read(padbuf, bytes_to_read, wth->fh);
                if (bytes_read != bytes_to_read) {
-                       *err = file_error(wth->fh);
+                       *err = file_error(wth->fh, err_info);
                        if (*err == 0)
                                *err = WTAP_ERR_SHORT_READ;
                        return FALSE;
@@ -609,7 +633,7 @@ snoop_seek_read(wtap *wth, gint64 seek_off,
 
        case WTAP_ENCAP_ATM_PDUS:
                if (!snoop_read_atm_pseudoheader(wth->random_fh, pseudo_header,
-                   err)) {
+                   err, err_info)) {
                        /* Read error */
                        return FALSE;
                }
@@ -639,7 +663,7 @@ snoop_seek_read(wtap *wth, gint64 seek_off,
        /*
         * Read the packet data.
         */
-       if (!snoop_read_rec_data(wth->random_fh, pd, length, err))
+       if (!snoop_read_rec_data(wth->random_fh, pd, length, err, err_info))
                return FALSE;   /* failed */
 
        /*
@@ -654,7 +678,7 @@ snoop_seek_read(wtap *wth, gint64 seek_off,
 
 static gboolean
 snoop_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
-    int *err)
+    int *err, gchar **err_info)
 {
        struct snoop_atm_hdr atm_phdr;
        int     bytes_read;
@@ -662,9 +686,9 @@ snoop_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
        guint16 vci;
 
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(&atm_phdr, 1, sizeof (struct snoop_atm_hdr), fh);
+       bytes_read = file_read(&atm_phdr, sizeof (struct snoop_atm_hdr), fh);
        if (bytes_read != sizeof (struct snoop_atm_hdr)) {
-               *err = file_error(fh);
+               *err = file_error(fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -755,9 +779,9 @@ snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
        int     rsize;
 
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(&whdr, 1, sizeof (shomiti_wireless_header), fh);
+       bytes_read = file_read(&whdr, sizeof (shomiti_wireless_header), fh);
        if (bytes_read != sizeof (shomiti_wireless_header)) {
-               *err = file_error(fh);
+               *err = file_error(fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -785,7 +809,7 @@ snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
        }
        /* Skip the header. */
        rsize = ((int) whdr.pad[3]) - 8;
-       if (file_seek(wth->fh, rsize, SEEK_CUR, err) == -1)
+       if (file_seek(fh, rsize, SEEK_CUR, err) == -1)
                return FALSE;
 
        pseudo_header->ieee_802_11.fcs_len = 4;
@@ -801,15 +825,16 @@ snoop_read_shomiti_wireless_pseudoheader(FILE_T fh,
 }
 
 static gboolean
-snoop_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
+snoop_read_rec_data(FILE_T fh, guchar *pd, int length, int *err,
+    gchar **err_info)
 {
        int     bytes_read;
 
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(pd, 1, length, fh);
+       bytes_read = file_read(pd, length, fh);
 
        if (bytes_read != length) {
-               *err = file_error(fh);
+               *err = file_error(fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -851,36 +876,23 @@ int snoop_dump_can_write_encap(int encap)
 
 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
    failure */
-gboolean snoop_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
+gboolean snoop_dump_open(wtap_dumper *wdh, int *err)
 {
        struct snoop_hdr file_hdr;
-       size_t nwritten;
 
        /* This is a snoop file */
        wdh->subtype_write = snoop_dump;
        wdh->subtype_close = NULL;
 
        /* Write the file header. */
-       nwritten = fwrite(&snoop_magic, 1, sizeof snoop_magic, wdh->fh);
-       if (nwritten != sizeof snoop_magic) {
-               if (nwritten == 0 && ferror(wdh->fh))
-                       *err = errno;
-               else
-                       *err = WTAP_ERR_SHORT_WRITE;
+       if (!wtap_dump_file_write(wdh, &snoop_magic, sizeof snoop_magic, err))
                return FALSE;
-       }
 
        /* current "snoop" format is 2 */
        file_hdr.version = g_htonl(2);
        file_hdr.network = g_htonl(wtap_encap[wdh->encap]);
-       nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
-       if (nwritten != sizeof file_hdr) {
-               if (nwritten == 0 && ferror(wdh->fh))
-                       *err = errno;
-               else
-                       *err = WTAP_ERR_SHORT_WRITE;
+       if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err))
                return FALSE;
-       }
 
        return TRUE;
 }
@@ -893,7 +905,6 @@ static gboolean snoop_dump(wtap_dumper *wdh,
        const guchar *pd, int *err)
 {
        struct snooprec_hdr rec_hdr;
-       size_t nwritten;
        int reclen;
        guint padlen;
        static char zeroes[4];
@@ -918,14 +929,8 @@ static gboolean snoop_dump(wtap_dumper *wdh,
        rec_hdr.cum_drops = 0;
        rec_hdr.ts_sec = g_htonl(phdr->ts.secs);
        rec_hdr.ts_usec = g_htonl(phdr->ts.nsecs / 1000);
-       nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
-       if (nwritten != sizeof rec_hdr) {
-               if (nwritten == 0 && ferror(wdh->fh))
-                       *err = errno;
-               else
-                       *err = WTAP_ERR_SHORT_WRITE;
+       if (!wtap_dump_file_write(wdh, &rec_hdr, sizeof rec_hdr, err))
                return FALSE;
-       }
 
        if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
                /*
@@ -962,33 +967,15 @@ static gboolean snoop_dump(wtap_dumper *wdh,
                }
                atm_hdr.vpi = (guint8) pseudo_header->atm.vpi;
                atm_hdr.vci = g_htons(pseudo_header->atm.vci);
-               nwritten = fwrite(&atm_hdr, 1, sizeof atm_hdr, wdh->fh);
-               if (nwritten != sizeof atm_hdr) {
-                       if (nwritten == 0 && ferror(wdh->fh))
-                               *err = errno;
-                       else
-                               *err = WTAP_ERR_SHORT_WRITE;
+               if (!wtap_dump_file_write(wdh, &atm_hdr, sizeof atm_hdr, err))
                        return FALSE;
-               }
        }
 
-       nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
-       if (nwritten != phdr->caplen) {
-               if (nwritten == 0 && ferror(wdh->fh))
-                       *err = errno;
-               else
-                       *err = WTAP_ERR_SHORT_WRITE;
+       if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
                return FALSE;
-       }
 
        /* Now write the padding. */
-       nwritten = fwrite(zeroes, 1, padlen, wdh->fh);
-       if (nwritten != padlen) {
-               if (nwritten == 0 && ferror(wdh->fh))
-                       *err = errno;
-               else
-                       *err = WTAP_ERR_SHORT_WRITE;
+       if (!wtap_dump_file_write(wdh, zeroes, padlen, err))
                return FALSE;
-       }
        return TRUE;
 }