/src/wireshark/wiretap/csids.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* csids.c |
2 | | * |
3 | | * Copyright (c) 2000 by Mike Hall <mlh@io.com> |
4 | | * Copyright (c) 2000 by Cisco Systems |
5 | | * |
6 | | * SPDX-License-Identifier: GPL-2.0-or-later |
7 | | */ |
8 | | |
9 | | #include "config.h" |
10 | | #include "csids.h" |
11 | | #include "wtap-int.h" |
12 | | #include "file_wrappers.h" |
13 | | |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | |
17 | | /* |
18 | | * This module reads the output from the Cisco Secure Intrusion Detection |
19 | | * System iplogging facility. The term iplogging is misleading since this |
20 | | * logger will only output TCP. There is no link layer information. |
21 | | * Packet format is 4 byte timestamp (seconds since epoch), and a 4 byte size |
22 | | * of data following for that packet. |
23 | | * |
24 | | * For a time there was an error in iplogging and the ip length, flags, and id |
25 | | * were byteswapped. We will check for this and handle it before handing to |
26 | | * wireshark. |
27 | | */ |
28 | | |
29 | | typedef struct { |
30 | | bool byteswapped; |
31 | | } csids_t; |
32 | | |
33 | | static bool csids_read(wtap *wth, wtap_rec *rec, |
34 | | int *err, char **err_info, int64_t *data_offset); |
35 | | static bool csids_seek_read(wtap *wth, int64_t seek_off, |
36 | | wtap_rec *rec, int *err, char **err_info); |
37 | | static bool csids_read_packet(FILE_T fh, csids_t *csids, |
38 | | wtap_rec *rec, int *err, char **err_info); |
39 | | |
40 | | struct csids_header { |
41 | | uint32_t seconds; /* seconds since epoch */ |
42 | | uint16_t zeropad; /* 2 byte zero'ed pads */ |
43 | | uint16_t caplen; /* the capture length */ |
44 | | }; |
45 | | |
46 | | static int csids_file_type_subtype = -1; |
47 | | |
48 | | void register_csids(void); |
49 | | |
50 | | wtap_open_return_val csids_open(wtap *wth, int *err, char **err_info) |
51 | 0 | { |
52 | | /* There is no file header. There is only a header for each packet |
53 | | * so we read a packet header and compare the caplen with iplen. They |
54 | | * should always be equal except with the weird byteswap version. |
55 | | * |
56 | | * THIS IS BROKEN-- anytime the caplen is 0x0101 or 0x0202 up to 0x0505 |
57 | | * this will byteswap it. I need to fix this. XXX --mlh |
58 | | */ |
59 | |
|
60 | 0 | int tmp,iplen; |
61 | |
|
62 | 0 | bool byteswap = false; |
63 | 0 | struct csids_header hdr; |
64 | 0 | csids_t *csids; |
65 | | |
66 | | /* check the file to make sure it is a csids file. */ |
67 | 0 | if( !wtap_read_bytes( wth->fh, &hdr, sizeof( struct csids_header), err, err_info ) ) { |
68 | 0 | if( *err != WTAP_ERR_SHORT_READ ) { |
69 | 0 | return WTAP_OPEN_ERROR; |
70 | 0 | } |
71 | 0 | return WTAP_OPEN_NOT_MINE; |
72 | 0 | } |
73 | 0 | if( hdr.zeropad != 0 || hdr.caplen == 0 ) { |
74 | 0 | return WTAP_OPEN_NOT_MINE; |
75 | 0 | } |
76 | 0 | hdr.seconds = pntoh32( &hdr.seconds ); |
77 | 0 | hdr.caplen = pntoh16( &hdr.caplen ); |
78 | 0 | if( !wtap_read_bytes( wth->fh, &tmp, 2, err, err_info ) ) { |
79 | 0 | if( *err != WTAP_ERR_SHORT_READ ) { |
80 | 0 | return WTAP_OPEN_ERROR; |
81 | 0 | } |
82 | 0 | return WTAP_OPEN_NOT_MINE; |
83 | 0 | } |
84 | 0 | if( !wtap_read_bytes(wth->fh, &iplen, 2, err, err_info ) ) { |
85 | 0 | if( *err != WTAP_ERR_SHORT_READ ) { |
86 | 0 | return WTAP_OPEN_ERROR; |
87 | 0 | } |
88 | 0 | return WTAP_OPEN_NOT_MINE; |
89 | 0 | } |
90 | 0 | iplen = pntoh16(&iplen); |
91 | |
|
92 | 0 | if ( iplen == 0 ) |
93 | 0 | return WTAP_OPEN_NOT_MINE; |
94 | | |
95 | | /* if iplen and hdr.caplen are equal, default to no byteswap. */ |
96 | 0 | if( iplen > hdr.caplen ) { |
97 | | /* maybe this is just a byteswapped version. the iplen ipflags */ |
98 | | /* and ipid are swapped. We cannot use the normal swaps because */ |
99 | | /* we don't know the host */ |
100 | 0 | iplen = GUINT16_SWAP_LE_BE(iplen); |
101 | 0 | if( iplen <= hdr.caplen ) { |
102 | | /* we know this format */ |
103 | 0 | byteswap = true; |
104 | 0 | } else { |
105 | | /* don't know this one */ |
106 | 0 | return WTAP_OPEN_NOT_MINE; |
107 | 0 | } |
108 | 0 | } else { |
109 | 0 | byteswap = false; |
110 | 0 | } |
111 | | |
112 | | /* no file header. So reset the fh to 0 so we can read the first packet */ |
113 | 0 | if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) |
114 | 0 | return WTAP_OPEN_ERROR; |
115 | | |
116 | 0 | csids = g_new(csids_t, 1); |
117 | 0 | wth->priv = (void *)csids; |
118 | 0 | csids->byteswapped = byteswap; |
119 | 0 | wth->file_encap = WTAP_ENCAP_RAW_IP; |
120 | 0 | wth->file_type_subtype = csids_file_type_subtype; |
121 | 0 | wth->snapshot_length = 0; /* not known */ |
122 | 0 | wth->subtype_read = csids_read; |
123 | 0 | wth->subtype_seek_read = csids_seek_read; |
124 | 0 | wth->file_tsprec = WTAP_TSPREC_SEC; |
125 | | |
126 | | /* |
127 | | * Add an IDB; we don't know how many interfaces were |
128 | | * involved, so we just say one interface, about which |
129 | | * we only know the link-layer type, snapshot length, |
130 | | * and time stamp resolution. |
131 | | */ |
132 | 0 | wtap_add_generated_idb(wth); |
133 | |
|
134 | 0 | return WTAP_OPEN_MINE; |
135 | 0 | } |
136 | | |
137 | | /* Find the next packet and parse it; called from wtap_read(). */ |
138 | | static bool csids_read(wtap *wth, wtap_rec *rec, |
139 | | int *err, char **err_info, int64_t *data_offset) |
140 | 0 | { |
141 | 0 | csids_t *csids = (csids_t *)wth->priv; |
142 | |
|
143 | 0 | *data_offset = file_tell(wth->fh); |
144 | |
|
145 | 0 | return csids_read_packet( wth->fh, csids, rec, err, err_info ); |
146 | 0 | } |
147 | | |
148 | | /* Used to read packets in random-access fashion */ |
149 | | static bool |
150 | | csids_seek_read(wtap *wth, |
151 | | int64_t seek_off, |
152 | | wtap_rec *rec, |
153 | | int *err, |
154 | | char **err_info) |
155 | 0 | { |
156 | 0 | csids_t *csids = (csids_t *)wth->priv; |
157 | |
|
158 | 0 | if( file_seek( wth->random_fh, seek_off, SEEK_SET, err ) == -1 ) |
159 | 0 | return false; |
160 | | |
161 | 0 | if( !csids_read_packet( wth->random_fh, csids, rec, err, err_info ) ) { |
162 | 0 | if( *err == 0 ) |
163 | 0 | *err = WTAP_ERR_SHORT_READ; |
164 | 0 | return false; |
165 | 0 | } |
166 | 0 | return true; |
167 | 0 | } |
168 | | |
169 | | static bool |
170 | | csids_read_packet(FILE_T fh, csids_t *csids, wtap_rec *rec, |
171 | | int *err, char **err_info) |
172 | 0 | { |
173 | 0 | struct csids_header hdr; |
174 | 0 | uint8_t *pd; |
175 | |
|
176 | 0 | if( !wtap_read_bytes_or_eof( fh, &hdr, sizeof( struct csids_header), err, err_info ) ) |
177 | 0 | return false; |
178 | 0 | hdr.seconds = pntoh32(&hdr.seconds); |
179 | 0 | hdr.caplen = pntoh16(&hdr.caplen); |
180 | | /* |
181 | | * The maximum value of hdr.caplen is 65535, which is less than |
182 | | * WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check |
183 | | * it. |
184 | | */ |
185 | |
|
186 | 0 | rec->rec_type = REC_TYPE_PACKET; |
187 | 0 | rec->block = wtap_block_create(WTAP_BLOCK_PACKET); |
188 | 0 | rec->presence_flags = WTAP_HAS_TS; |
189 | 0 | rec->rec_header.packet_header.len = hdr.caplen; |
190 | 0 | rec->rec_header.packet_header.caplen = hdr.caplen; |
191 | 0 | rec->ts.secs = hdr.seconds; |
192 | 0 | rec->ts.nsecs = 0; |
193 | |
|
194 | 0 | if( !wtap_read_bytes_buffer( fh, &rec->data, rec->rec_header.packet_header.caplen, err, err_info ) ) |
195 | 0 | return false; |
196 | | |
197 | 0 | pd = ws_buffer_start_ptr( &rec->data ); |
198 | 0 | if( csids->byteswapped ) { |
199 | 0 | if( rec->rec_header.packet_header.caplen >= 2 ) { |
200 | 0 | PBSWAP16(pd); /* the ip len */ |
201 | 0 | if( rec->rec_header.packet_header.caplen >= 4 ) { |
202 | 0 | PBSWAP16(pd+2); /* ip id */ |
203 | 0 | if( rec->rec_header.packet_header.caplen >= 6 ) |
204 | 0 | PBSWAP16(pd+4); /* ip flags and fragoff */ |
205 | 0 | } |
206 | 0 | } |
207 | 0 | } |
208 | |
|
209 | 0 | return true; |
210 | 0 | } |
211 | | |
212 | | static const struct supported_block_type csids_blocks_supported[] = { |
213 | | /* |
214 | | * We support packet blocks, with no comments or other options. |
215 | | */ |
216 | | { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED } |
217 | | }; |
218 | | |
219 | | static const struct file_type_subtype_info csids_info = { |
220 | | "CSIDS IPLog", "csids", NULL, NULL, |
221 | | false, BLOCKS_SUPPORTED(csids_blocks_supported), |
222 | | NULL, NULL, NULL |
223 | | }; |
224 | | |
225 | | void register_csids(void) |
226 | 2 | { |
227 | 2 | csids_file_type_subtype = wtap_register_file_type_subtype(&csids_info); |
228 | | |
229 | | /* |
230 | | * Register name for backwards compatibility with the |
231 | | * wtap_filetypes table in Lua. |
232 | | */ |
233 | 2 | wtap_register_backwards_compatibility_lua_name("CSIDS", |
234 | 2 | csids_file_type_subtype); |
235 | 2 | } |
236 | | |
237 | | /* |
238 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
239 | | * |
240 | | * Local Variables: |
241 | | * c-basic-offset: 2 |
242 | | * tab-width: 8 |
243 | | * indent-tabs-mode: nil |
244 | | * End: |
245 | | * |
246 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
247 | | * :indentSize=2:tabSize=8:noTabs=true: |
248 | | */ |