MSWSP: use GuidPropertySet_find_guid() in parse_CFullPropSpec()
[wireshark-wip.git] / wiretap / ascendtext.c
blob5c8636f7dac23e4da9c8f3a9f91d5bf5bfbc394f
1 /* ascendtext.c
3 * $Id$
5 * Wiretap Library
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "config.h"
24 #include "wtap-int.h"
25 #include "buffer.h"
26 #include "ascendtext.h"
27 #include "ascend-int.h"
28 #include "file_wrappers.h"
29 #include <wsutil/file_util.h>
31 #include <errno.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
37 #include <ctype.h>
38 #include <string.h>
40 /* Last updated: Feb 03 2005: Josh Bailey (joshbailey@lucent.com).
42 This module reads the text hex dump output of various TAOS
43 (Lucent/Ascend Max, Max TNT, APX, etc) debug commands, including:
45 * pridisplay traces primary rate ISDN
46 * ether-display traces Ethernet packets (dangerous! CPU intensive)
47 * wanopening, wandisplay, wannext, wandsess
48 traces PPP or other WAN connections
50 Please see ascend.y for examples.
52 Detailed documentation on TAOS products is at http://support.lucent.com.
54 Support for other commands will be added on an ongoing basis. */
56 typedef struct _ascend_magic_string {
57 guint type;
58 const gchar *strptr;
59 } ascend_magic_string;
61 #define ASCEND_MAGIC_STRINGS 11
62 #define ASCEND_DATE "Date:"
64 /* these magic strings signify the headers of a supported debug commands */
65 static const ascend_magic_string ascend_magic[] = {
66 { ASCEND_PFX_ISDN_X, "PRI-XMIT-" },
67 { ASCEND_PFX_ISDN_R, "PRI-RCV-" },
68 { ASCEND_PFX_WDS_X, "XMIT-" },
69 { ASCEND_PFX_WDS_R, "RECV-" },
70 { ASCEND_PFX_WDS_X, "XMIT:" },
71 { ASCEND_PFX_WDS_R, "RECV:" },
72 { ASCEND_PFX_WDS_X, "PPP-OUT" },
73 { ASCEND_PFX_WDS_R, "PPP-IN" },
74 { ASCEND_PFX_WDD, ASCEND_DATE },
75 { ASCEND_PFX_WDD, "WD_DIALOUT_DISP:" },
76 { ASCEND_PFX_ETHER, "ETHER" },
79 static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
80 gint64 *data_offset);
81 static gboolean ascend_seek_read(wtap *wth, gint64 seek_off,
82 struct wtap_pkthdr *phdr, Buffer *buf, int len,
83 int *err, gchar **err_info);
85 /* Seeks to the beginning of the next packet, and returns the
86 byte offset at which the header for that packet begins.
87 Returns -1 on failure. */
88 static gint64 ascend_seek(wtap *wth, int *err, gchar **err_info)
90 int byte;
91 gint64 date_off = -1, cur_off, packet_off;
92 size_t string_level[ASCEND_MAGIC_STRINGS];
93 guint string_i = 0, type = 0;
94 guint excessive_read_count = 262144;
96 memset(&string_level, 0, sizeof(string_level));
98 while (((byte = file_getc(wth->fh)) != EOF)) {
99 excessive_read_count--;
101 if (!excessive_read_count) {
102 *err = 0;
103 return -1;
106 for (string_i = 0; string_i < ASCEND_MAGIC_STRINGS; string_i++) {
107 const gchar *strptr = ascend_magic[string_i].strptr;
108 size_t len = strlen(strptr);
110 if (byte == *(strptr + string_level[string_i])) {
111 string_level[string_i]++;
112 if (string_level[string_i] >= len) {
113 cur_off = file_tell(wth->fh);
114 if (cur_off == -1) {
115 /* Error. */
116 *err = file_error(wth->fh, err_info);
117 return -1;
120 /* Date: header is a special case. Remember the offset,
121 but keep looking for other headers. */
122 if (strcmp(strptr, ASCEND_DATE) == 0) {
123 date_off = cur_off - len;
124 } else {
125 if (date_off == -1) {
126 /* Back up over the header we just read; that's where a read
127 of this packet should start. */
128 packet_off = cur_off - len;
129 } else {
130 /* This packet has a date/time header; a read of it should
131 start at the beginning of *that* header. */
132 packet_off = date_off;
135 type = ascend_magic[string_i].type;
136 goto found;
139 } else {
140 string_level[string_i] = 0;
145 *err = file_error(wth->fh, err_info);
146 return -1;
148 found:
150 * Move to where the read for this packet should start, and return
151 * that seek offset.
153 if (file_seek(wth->fh, packet_off, SEEK_SET, err) == -1)
154 return -1;
156 wth->phdr.pseudo_header.ascend.type = type;
158 return packet_off;
161 int ascend_open(wtap *wth, int *err, gchar **err_info)
163 gint64 offset;
164 ws_statb64 statbuf;
165 ascend_t *ascend;
167 /* We haven't yet allocated a data structure for our private stuff;
168 set the pointer to null, so that "ascend_seek()" knows not to
169 fill it in. */
170 wth->priv = NULL;
172 offset = ascend_seek(wth, err, err_info);
173 if (offset == -1) {
174 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
175 return -1;
176 return 0;
179 /* Do a trial parse of the first packet just found to see if we might really have an Ascend file */
180 init_parse_ascend();
181 if (!check_ascend(wth->fh, &wth->phdr)) {
182 return 0;
185 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_ASCEND;
187 switch(wth->phdr.pseudo_header.ascend.type) {
188 case ASCEND_PFX_ISDN_X:
189 case ASCEND_PFX_ISDN_R:
190 wth->file_encap = WTAP_ENCAP_ISDN;
191 break;
193 case ASCEND_PFX_ETHER:
194 wth->file_encap = WTAP_ENCAP_ETHERNET;
195 break;
197 default:
198 wth->file_encap = WTAP_ENCAP_ASCEND;
201 wth->snapshot_length = ASCEND_MAX_PKT_LEN;
202 wth->subtype_read = ascend_read;
203 wth->subtype_seek_read = ascend_seek_read;
204 ascend = (ascend_t *)g_malloc(sizeof(ascend_t));
205 wth->priv = (void *)ascend;
207 /* The first packet we want to read is the one that "ascend_seek()"
208 just found; start searching for it at the offset at which it
209 found it. */
210 ascend->next_packet_seek_start = offset;
212 /* MAXen and Pipelines report the time since reboot. In order to keep
213 from reporting packet times near the epoch, we subtract the first
214 packet's timestamp from the capture file's ctime, which gives us an
215 offset that we can apply to each packet.
217 if (wtap_fstat(wth, &statbuf, err) == -1) {
218 return -1;
220 ascend->inittime = statbuf.st_ctime;
221 ascend->adjusted = FALSE;
222 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
224 init_parse_ascend();
226 return 1;
229 /* Read the next packet; called from wtap_read(). */
230 static gboolean ascend_read(wtap *wth, int *err, gchar **err_info,
231 gint64 *data_offset)
233 ascend_t *ascend = (ascend_t *)wth->priv;
234 gint64 offset;
236 /* parse_ascend() will advance the point at which to look for the next
237 packet's header, to just after the last packet's header (ie. at the
238 start of the last packet's data). We have to get past the last
239 packet's header because we might mistake part of it for a new header. */
240 if (file_seek(wth->fh, ascend->next_packet_seek_start,
241 SEEK_SET, err) == -1)
242 return FALSE;
244 offset = ascend_seek(wth, err, err_info);
245 if (offset == -1)
246 return FALSE;
247 if (parse_ascend(ascend, wth->fh, &wth->phdr, wth->frame_buffer,
248 wth->snapshot_length) != PARSED_RECORD) {
249 *err = WTAP_ERR_BAD_FILE;
250 *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
251 return FALSE;
254 *data_offset = offset;
255 return TRUE;
258 static gboolean ascend_seek_read(wtap *wth, gint64 seek_off,
259 struct wtap_pkthdr *phdr, Buffer *buf, int len _U_,
260 int *err, gchar **err_info)
262 ascend_t *ascend = (ascend_t *)wth->priv;
264 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
265 return FALSE;
266 if (parse_ascend(ascend, wth->random_fh, phdr, buf,
267 wth->snapshot_length) != PARSED_RECORD) {
268 *err = WTAP_ERR_BAD_FILE;
269 *err_info = g_strdup((ascend_parse_error != NULL) ? ascend_parse_error : "parse error");
270 return FALSE;
273 return TRUE;