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