Take the name-processing part of "get_nbns_name_type_class()" and put it
[obnox/wireshark/wip.git] / wiretap / ngsniffer.c
1 /* ngsniffer.c
2  *
3  * $Id: ngsniffer.c,v 1.5 1998/11/15 05:29:13 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
7  * 
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.
12  * 
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.
17  * 
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23
24 /* The code in ngsniffer.c that decodes the time fields for each packet in the
25  * Sniffer trace originally came from code from TCPVIEW:
26  *
27  * TCPVIEW
28  *
29  * Author:      Martin Hunt
30  *              Networks and Distributed Computing
31  *              Computing & Communications
32  *              University of Washington
33  *              Administration Building, AG-44
34  *              Seattle, WA  98195
35  *              Internet: martinh@cac.washington.edu
36  *
37  *
38  * Copyright 1992 by the University of Washington
39  *
40  * Permission to use, copy, modify, and distribute this software and its
41  * documentation for any purpose and without fee is hereby granted, provided
42  * that the above copyright notice appears in all copies and that both the
43  * above copyright notice and this permission notice appear in supporting
44  * documentation, and that the name of the University of Washington not be
45  * used in advertising or publicity pertaining to distribution of the software
46  * without specific, written prior permission.  This software is made
47  * available "as is", and
48  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
49  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
50  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
51  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
52  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
53  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
54  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
55  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
56  *
57  */
58
59 #include <stdlib.h>
60 #include "wtap.h"
61 #include "ngsniffer.h"
62
63 /* values for V.timeunit */
64 #define NUM_NGSNIFF_TIMEUNITS 7
65 static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 0.0, 0.1 };
66
67 #define NUM_NGSNIFF_ENCAPS 10
68 static int sniffer_encap[] = {
69                 WTAP_ENCAP_TR,
70                 WTAP_ENCAP_ETHERNET,
71                 WTAP_ENCAP_ARCNET,
72                 WTAP_ENCAP_NONE,        /* StarLAN */
73                 WTAP_ENCAP_NONE,        /* PC Network broadband */
74                 WTAP_ENCAP_NONE,        /* LocalTalk */
75                 WTAP_ENCAP_NONE,        /* type 6 not defined in Sniffer */
76                 WTAP_ENCAP_NONE,        /* Internetwork analyzer */
77                 WTAP_ENCAP_NONE,        /* type 8 not defined in Sniffer */
78                 WTAP_ENCAP_FDDI
79 };
80
81 /* Returns WTAP_FILE_NGSNIFFER on success, WTAP_FILE_UNKNOWN on failure */
82 int ngsniffer_open(wtap *wth)
83 {
84         int bytes_read;
85         char magic[18];
86         char record_type[2];
87         char record_length[4]; /* only the first 2 bytes are length,
88                                                           the last 2 are "reserved" and are thrown away */
89         guint16 type, length = 0;
90         char    network;
91         char    version[18]; /* to hold the entire version record */
92         char    timeunit;
93
94         /* Read in the string that should be at the start of a Sniffer file */
95         fseek(wth->fh, 0, SEEK_SET);
96         bytes_read = fread(magic, 1, 17, wth->fh);
97
98         if (bytes_read != 17) {
99                 return WTAP_FILE_UNKNOWN;
100         }
101
102         magic[17] = 0;
103
104         if (strcmp(magic, "TRSNIFF data    \x1a")) {
105                 return WTAP_FILE_UNKNOWN;
106         }
107
108         /* This is a ngsniffer file */
109         wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
110         wth->subtype_read = ngsniffer_read;
111         wth->snapshot_length = 16384;   /* XXX - available in header? */
112         /*wth->frame_number = 0;*/
113         /*wth->file_byte_offset = 0x10b;*/
114
115         /* Read records until we find the start of packets */
116         while (1) {
117                 fseek(wth->fh, length, SEEK_CUR);
118                 bytes_read = fread(record_type, 1, 2, wth->fh);
119                 bytes_read += fread(record_length, 1, 4, wth->fh);
120                 if (bytes_read != 6) {
121                         free(wth->capture.ngsniffer);
122                         return WTAP_FILE_UNKNOWN;
123                 }
124
125                 type = pletohs(record_type);
126                 length = pletohs(record_length);
127
128                 switch (type) {
129                         /* Version Record */
130                         case REC_VERS:
131                                 fread(version, 1, 18, wth->fh);
132                                 length = 0; /* to fake the next iteration of while() */
133
134                                 /* Get data link type */
135                                 network = version[9];
136                                 if (network >= NUM_NGSNIFF_ENCAPS) {
137                                         g_error("ngsniffer: network type %d unknown", network);
138                                         free(wth->capture.ngsniffer);
139                                         return WTAP_FILE_UNKNOWN;
140                                 }
141                                 else {
142                                         wth->encapsulation = sniffer_encap[network];
143                                 }
144
145                                 /* Get time unit */
146                                 timeunit = version[11];
147                                 if (timeunit >= NUM_NGSNIFF_TIMEUNITS) {
148                                         g_error("ngsniffer: Unknown timeunit %d", timeunit);
149                                         free(wth->capture.ngsniffer);
150                                         return WTAP_FILE_UNKNOWN;
151                                 }
152                                 else {
153                                         wth->capture.ngsniffer->timeunit = Usec[timeunit];
154                                 }
155                                 break;
156
157                         case REC_FRAME2:
158                                 wth->capture.ngsniffer->pkt_len = length - 14;
159                                 return WTAP_FILE_NGSNIFFER;
160
161                         default:
162                                 /* Continue with while() loop */
163                 }
164         }
165
166         /* never gets here */
167         return WTAP_FILE_NGSNIFFER;
168 }
169
170 /* Read the next packet */
171 int ngsniffer_read(wtap *wth)
172 {
173         int     packet_size = wth->capture.ngsniffer->pkt_len;
174         int     bytes_read;
175         char record_type[2];
176         char record_length[4]; /* only 1st 2 bytes are length */
177         guint16 type, length;
178         char frame2[14];
179         double t, x;
180         guint16 time_low, time_med, time_high, true_size, size;
181         int     data_offset;
182
183         /* if this is the very first packet, then the fh cursor will be at the
184          * start of a f_frame2_struct instead of at the start of the record.
185          * Check for this */
186         if (!packet_size) {
187
188                 /* Read record info */
189                 bytes_read = fread(record_type, 1, 2, wth->fh);
190                 bytes_read += fread(record_length, 1, 4, wth->fh);
191                 if (bytes_read != 6) {
192                         return 0;
193                 }
194
195                 type = pletohs(record_type);
196                 length = pletohs(record_length);
197
198                 if (type != REC_FRAME2) {
199                         return 0;
200                 }
201                 else {
202                         packet_size = length - 14;
203                 }
204         }
205         else {
206                 wth->capture.ngsniffer->pkt_len = 0;
207         }
208
209         /* Read the f_frame2_struct */
210         bytes_read = fread(frame2, 1, 14, wth->fh);
211         if (bytes_read != 14) {
212                 g_error("ngsniffer_read: not enough frame2 data (%d bytes)",
213                                 bytes_read);
214                 return 0;
215         }
216
217         /* Read some of the fields in frame2 */
218         size = pletohs(&frame2[6]);
219         true_size = pletohs(&frame2[10]);
220         time_low = pletohs(&frame2[0]);
221         time_med = pletohs(&frame2[2]);
222         time_high = frame2[4];
223
224         buffer_assure_space(&wth->frame_buffer, packet_size);
225         data_offset = ftell(wth->fh);
226         bytes_read = fread(buffer_start_ptr(&wth->frame_buffer), 1,
227                         packet_size, wth->fh);
228
229         if (bytes_read != packet_size) {
230                 if (ferror(wth->fh)) {
231                         g_error("ngsniffer_read: fread for data: read error\n");
232                 } else {
233                         g_error("ngsniffer_read: fread for data: %d bytes out of %d",
234                                 bytes_read, packet_size);
235                 }
236                 return -1;
237         }
238
239         x = 4.0 * (double)(1<<30);
240         t = (double)time_low+(double)(time_med)*65536.0 +
241                 (double)time_high*x;
242         t = t/1000000.0 * wth->capture.ngsniffer->timeunit; /* t = # of secs */
243
244         wth->phdr.ts.tv_sec = (long)t;
245         wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec))
246                         *1.0e6);
247         wth->phdr.len = true_size ? true_size : size;
248         wth->phdr.caplen = size;
249
250         return data_offset;
251 }