Revert "Allow wtap_read() and wtap_seek_read() to return non-packet records."
[metze/wireshark/wip.git] / wiretap / csids.c
1 /* csids.c
2  *
3  * Copyright (c) 2000 by Mike Hall <mlh@io.com>
4  * Copyright (c) 2000 by Cisco Systems
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20
21 #include "config.h"
22 #include "wtap-int.h"
23 #include "buffer.h"
24 #include "csids.h"
25 #include "file_wrappers.h"
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 /*
32  * This module reads the output from the Cisco Secure Intrusion Detection
33  * System iplogging facility. The term iplogging is misleading since this
34  * logger will only output TCP. There is no link layer information.
35  * Packet format is 4 byte timestamp (seconds since epoch), and a 4 byte size
36  * of data following for that packet.
37  *
38  * For a time there was an error in iplogging and the ip length, flags, and id
39  * were byteswapped. We will check for this and handle it before handing to
40  * wireshark.
41  */
42
43 typedef struct {
44         gboolean byteswapped;
45 } csids_t;
46
47 static gboolean csids_read(wtap *wth, int *err, gchar **err_info,
48         gint64 *data_offset);
49 static gboolean csids_seek_read(wtap *wth, gint64 seek_off,
50         struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
51 static gboolean csids_read_packet(FILE_T fh, csids_t *csids,
52         struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
53
54 struct csids_header {
55   guint32 seconds; /* seconds since epoch */
56   guint16 zeropad; /* 2 byte zero'ed pads */
57   guint16 caplen;  /* the capture length  */
58 };
59
60 /* XXX - return -1 on I/O error and actually do something with 'err'. */
61 int csids_open(wtap *wth, int *err, gchar **err_info)
62 {
63   /* There is no file header. There is only a header for each packet
64    * so we read a packet header and compare the caplen with iplen. They
65    * should always be equal except with the weird byteswap version.
66    *
67    * THIS IS BROKEN-- anytime the caplen is 0x0101 or 0x0202 up to 0x0505
68    * this will byteswap it. I need to fix this. XXX --mlh
69    */
70
71   int tmp,iplen,bytesRead;
72
73   gboolean byteswap = FALSE;
74   struct csids_header hdr;
75   csids_t *csids;
76
77   /* check the file to make sure it is a csids file. */
78   bytesRead = file_read( &hdr, sizeof( struct csids_header), wth->fh );
79   if( bytesRead != sizeof( struct csids_header) ) {
80     *err = file_error( wth->fh, err_info );
81     if( *err != 0 && *err != WTAP_ERR_SHORT_READ ) {
82       return -1;
83     }
84     return 0;
85   }
86   if( hdr.zeropad != 0 || hdr.caplen == 0 ) {
87         return 0;
88   }
89   hdr.seconds = pntoh32( &hdr.seconds );
90   hdr.caplen = pntoh16( &hdr.caplen );
91   bytesRead = file_read( &tmp, 2, wth->fh );
92   if( bytesRead != 2 ) {
93     *err = file_error( wth->fh, err_info );
94     if( *err != 0 && *err != WTAP_ERR_SHORT_READ ) {
95       return -1;
96     }
97     return 0;
98   }
99   bytesRead = file_read( &iplen, 2, wth->fh );
100   if( bytesRead != 2 ) {
101     *err = file_error( wth->fh, err_info );
102     if( *err != 0 && *err != WTAP_ERR_SHORT_READ ) {
103       return -1;
104     }
105     return 0;
106   }
107   iplen = pntoh16(&iplen);
108
109   if ( iplen == 0 )
110     return 0;
111
112   /* if iplen and hdr.caplen are equal, default to no byteswap. */
113   if( iplen > hdr.caplen ) {
114     /* maybe this is just a byteswapped version. the iplen ipflags */
115     /* and ipid are swapped. We cannot use the normal swaps because */
116     /* we don't know the host */
117     iplen = GUINT16_SWAP_LE_BE(iplen);
118     if( iplen <= hdr.caplen ) {
119       /* we know this format */
120       byteswap = TRUE;
121     } else {
122       /* don't know this one */
123       return 0;
124     }
125   } else {
126     byteswap = FALSE;
127   }
128
129   /* no file header. So reset the fh to 0 so we can read the first packet */
130   if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
131     return -1;
132
133   csids = (csids_t *)g_malloc(sizeof(csids_t));
134   wth->priv = (void *)csids;
135   csids->byteswapped = byteswap;
136   wth->file_encap = WTAP_ENCAP_RAW_IP;
137   wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_CSIDS;
138   wth->snapshot_length = 0; /* not known */
139   wth->subtype_read = csids_read;
140   wth->subtype_seek_read = csids_seek_read;
141   wth->tsprecision = WTAP_FILE_TSPREC_SEC;
142
143   return 1;
144 }
145
146 /* Find the next packet and parse it; called from wtap_read(). */
147 static gboolean csids_read(wtap *wth, int *err, gchar **err_info,
148     gint64 *data_offset)
149 {
150   csids_t *csids = (csids_t *)wth->priv;
151
152   *data_offset = file_tell(wth->fh);
153
154   return csids_read_packet( wth->fh, csids, &wth->phdr, wth->frame_buffer,
155                             err, err_info );
156 }
157
158 /* Used to read packets in random-access fashion */
159 static gboolean
160 csids_seek_read(wtap *wth,
161                  gint64 seek_off,
162                  struct wtap_pkthdr *phdr,
163                  Buffer *buf,
164                  int *err,
165                  gchar **err_info)
166 {
167   csids_t *csids = (csids_t *)wth->priv;
168
169   if( file_seek( wth->random_fh, seek_off, SEEK_SET, err ) == -1 )
170     return FALSE;
171
172   if( !csids_read_packet( wth->random_fh, csids, phdr, buf, err, err_info ) ) {
173     if( *err == 0 )
174       *err = WTAP_ERR_SHORT_READ;
175     return FALSE;
176   }
177   return TRUE;
178 }
179
180 static gboolean
181 csids_read_packet(FILE_T fh, csids_t *csids, struct wtap_pkthdr *phdr,
182                   Buffer *buf, int *err, gchar **err_info)
183 {
184   struct csids_header hdr;
185   int bytesRead = 0;
186   guint8 *pd;
187
188   bytesRead = file_read( &hdr, sizeof( struct csids_header), fh );
189   if( bytesRead != sizeof( struct csids_header) ) {
190     *err = file_error( fh, err_info );
191     if (*err == 0 && bytesRead != 0)
192       *err = WTAP_ERR_SHORT_READ;
193     return FALSE;
194   }
195   hdr.seconds = pntoh32(&hdr.seconds);
196   hdr.caplen = pntoh16(&hdr.caplen);
197
198   phdr->presence_flags = WTAP_HAS_TS;
199   phdr->len = hdr.caplen;
200   phdr->caplen = hdr.caplen;
201   phdr->ts.secs = hdr.seconds;
202   phdr->ts.nsecs = 0;
203
204   if( !wtap_read_packet_bytes( fh, buf, phdr->caplen, err, err_info ) )
205     return FALSE;
206
207   pd = buffer_start_ptr( buf );
208   if( csids->byteswapped ) {
209     if( phdr->caplen >= 2 ) {
210       PBSWAP16(pd);   /* the ip len */
211       if( phdr->caplen >= 4 ) {
212         PBSWAP16(pd+2); /* ip id */
213         if( phdr->caplen >= 6 )
214           PBSWAP16(pd+4); /* ip flags and fragoff */
215       }
216     }
217   }
218
219   return TRUE;
220 }