0096b98a3a5c13c60fd8d90bb5af65872859503b
[obnox/wireshark/wip.git] / wiretap / nettl.c
1 /* nettl.c
2  *
3  * $Id: nettl.c,v 1.32 2003/05/05 01:01:36 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.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 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include "wtap-int.h"
31 #include "file_wrappers.h"
32 #include "buffer.h"
33 #include "nettl.h"
34
35 static guchar nettl_magic_hpux9[12] = {
36     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x00
37 };
38 static guchar nettl_magic_hpux10[12] = {
39     0x54, 0x52, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
40 };
41
42 /* HP nettl record header for the SX25L2 subsystem - The FCS is not included in the file. */
43 struct nettlrec_sx25l2_hdr {
44     guint8      xxa[8];
45     guint8      from_dce;
46     guint8      xxb[55];
47     guint8      caplen[2];
48     guint8      length[2];
49     guint8      xxc[4];
50     guint8      sec[4];
51     guint8      usec[4];
52     guint8      xxd[4];
53 };
54
55 /* HP nettl record header for the NS_LS_IP subsystem */
56 /* This also works for BASE100 and GSC100BT */
57 struct nettlrec_ns_ls_ip_hdr {
58     guint8      xxa[28];
59     guint8      caplen[4];
60     guint8      length[4];
61     guint8      sec[4];
62     guint8      usec[4];
63     guint8      xxb[16];
64 };
65
66
67 /* header is followed by data and once again the total length (2 bytes) ! */
68
69
70 /* NL_LS_DRIVER :
71 The following shows what the header looks like for NS_LS_DRIVER
72 The capture was taken on HPUX11 and for a 100baseT interface.
73
74 000080 00 44 00 0b 00 00 00 02 00 00 00 00 20 00 00 00
75 000090 00 00 00 00 00 00 04 06 00 00 00 00 00 00 00 00
76 0000a0 00 00 00 74 00 00 00 74 3c e3 76 19 00 06 34 63
77 0000b0 ff ff ff ff 00 00 00 00 00 00 00 00 ff ff ff ff
78 0000c0 00 00 00 00 00 00 01 02 00 5c 00 5c ff ff ff ff
79 0000d0 3c e3 76 19 00 06 34 5a 00 0b 00 14 <here starts the MAC heder>
80
81 Each entry starts with 0x0044000b
82
83 The values 0x005c at position 0x0000c8 and 0x0000ca matches the number of bytes in
84 the packet up to the next entry, which starts with 0x00440b again. These probably
85 indicate the real and captured length of the packet (order unknown)
86
87 The values 0x00000074 at positions 0x0000a0 and 0x0000a4 seems to indicate
88 the same number as positions 0x0000c8 and 0x0000ca but added with 24.
89 Perhaps we have here two layers of headers.
90 The first layer is fixed and consists of all the bytes from 0x000084 up to and
91 including 0x0000c3 which is a generic header for all packets captured from any
92 device. This header might be of fixed size 64 bytes and there might be something in
93 it which indicates the type of the next header which is link type specific.
94 Following this header there is another header for the 100baseT interface which
95 in this case is 24 bytes long spanning positions 0x0000c4 to 0x0000db.
96
97 When someone reports that the loading of the captures breaks, we can compare
98 this header above with what he/she got to learn how to distinguish between different
99 types of link specific headers.
100
101
102 For now:
103 The first header seems to be
104         a normal nettlrec_ns_ls_ip_hdr
105
106 The header for 100baseT seems to be
107         0-3     unknown
108         4-5     captured length
109         6-7     actual length
110         8-11    unknown
111         12-15   secs
112         16-19   usecs
113         20-23   unknown
114 */
115 struct nettlrec_ns_ls_drv_eth_hdr {
116     guint8      xxa[4];
117     guint8      caplen[2];
118     guint8      length[2];
119     guint8      xxb[4];
120     guint8      sec[4];
121     guint8      usec[4];
122     guint8      xxc[4];
123 };
124
125
126 static gboolean nettl_read(wtap *wth, int *err, long *data_offset);
127 static gboolean nettl_seek_read(wtap *wth, long seek_off,
128                 union wtap_pseudo_header *pseudo_header, guchar *pd,
129                 int length, int *err);
130 static int nettl_read_rec_header(wtap *wth, FILE_T fh,
131                 struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
132                 int *err);
133 static gboolean nettl_read_rec_data(FILE_T fh, guchar *pd, int length,
134                 int *err);
135 static void nettl_close(wtap *wth);
136
137 int nettl_open(wtap *wth, int *err)
138 {
139     char magic[12], os_vers[2];
140     int bytes_read;
141
142     /* Read in the string that should be at the start of a HP file */
143     errno = WTAP_ERR_CANT_READ;
144     bytes_read = file_read(magic, 1, 12, wth->fh);
145     if (bytes_read != 12) {
146         *err = file_error(wth->fh);
147         if (*err != 0)
148             return -1;
149         return 0;
150     }
151
152     if (memcmp(magic, nettl_magic_hpux9, 12) &&
153         memcmp(magic, nettl_magic_hpux10, 12)) {
154         return 0;
155     }
156
157     if (file_seek(wth->fh, 0x63, SEEK_SET, err) == -1)
158         return -1;
159     wth->data_offset = 0x63;
160     bytes_read = file_read(os_vers, 1, 2, wth->fh);
161     if (bytes_read != 2) {
162         *err = file_error(wth->fh);
163         if (*err != 0)
164             return -1;
165         return 0;
166     }
167
168     if (file_seek(wth->fh, 0x80, SEEK_SET, err) == -1)
169         return -1;
170     wth->data_offset = 0x80;
171
172     /* This is an nettl file */
173     wth->file_type = WTAP_FILE_NETTL;
174     wth->capture.nettl = g_malloc(sizeof(nettl_t));
175     if (os_vers[0] == '1' && os_vers[1] == '1')
176         wth->capture.nettl->is_hpux_11 = TRUE;
177     else
178         wth->capture.nettl->is_hpux_11 = FALSE;
179     wth->subtype_read = nettl_read;
180     wth->subtype_seek_read = nettl_seek_read;
181     wth->subtype_close = nettl_close;
182     wth->snapshot_length = 0;   /* not available in header, only in frame */
183
184     return 1;
185 }
186
187 /* Read the next packet */
188 static gboolean nettl_read(wtap *wth, int *err, long *data_offset)
189 {
190     int ret;
191
192     /* Read record header. */
193     *data_offset = wth->data_offset;
194     ret = nettl_read_rec_header(wth, wth->fh, &wth->phdr, &wth->pseudo_header,
195         err);
196     if (ret <= 0) {
197         /* Read error or EOF */
198         return FALSE;
199     }
200     wth->data_offset += ret;
201
202     /*
203      * Read the packet data.
204      */
205     buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
206     if (!nettl_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
207                 wth->phdr.caplen, err))
208         return FALSE;   /* Read error */
209     wth->data_offset += wth->phdr.caplen;
210     return TRUE;
211 }
212
213 static gboolean
214 nettl_seek_read(wtap *wth, long seek_off,
215                 union wtap_pseudo_header *pseudo_header, guchar *pd,
216                 int length, int *err)
217 {
218     int ret;
219     struct wtap_pkthdr phdr;
220
221     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
222         return FALSE;
223
224     /* Read record header. */
225     ret = nettl_read_rec_header(wth, wth->random_fh, &phdr, pseudo_header,
226         err);
227     if (ret <= 0) {
228         /* Read error or EOF */
229         if (ret == 0) {
230             /* EOF means "short read" in random-access mode */
231             *err = WTAP_ERR_SHORT_READ;
232         }
233         return FALSE;
234     }
235
236     /*
237      * Read the packet data.
238      */
239     return nettl_read_rec_data(wth->random_fh, pd, length, err);
240 }
241
242 static int
243 nettl_read_rec_header(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
244                 union wtap_pseudo_header *pseudo_header, int *err)
245 {
246     int bytes_read;
247     struct nettlrec_sx25l2_hdr lapb_hdr;
248     struct nettlrec_ns_ls_ip_hdr ip_hdr;
249     struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
250     guint16 length;
251     int offset = 0;
252     guint8 encap[4];
253     guint8 dummy[4];
254
255     errno = WTAP_ERR_CANT_READ;
256     bytes_read = file_read(encap, 1, 4, fh);
257     if (bytes_read != 4) {
258         *err = file_error(fh);
259         if (*err != 0)
260             return -1;
261         if (bytes_read != 0) {
262             *err = WTAP_ERR_SHORT_READ;
263             return -1;
264         }
265         return 0;
266     }
267     offset += 4;
268
269     switch (encap[3]) {
270         case NETTL_SUBSYS_LAN100 :
271         case NETTL_SUBSYS_BASE100 :
272         case NETTL_SUBSYS_GSC100BT :
273         case NETTL_SUBSYS_PCI100BT :
274         case NETTL_SUBSYS_SPP100BT :
275         case NETTL_SUBSYS_GELAN :
276         case NETTL_SUBSYS_BTLAN :
277         case NETTL_SUBSYS_INTL100 :
278         case NETTL_SUBSYS_IGELAN :
279         case NETTL_SUBSYS_NS_LS_IP :
280         case NETTL_SUBSYS_NS_LS_LOOPBACK :
281         case NETTL_SUBSYS_NS_LS_TCP :
282         case NETTL_SUBSYS_NS_LS_UDP :
283         case NETTL_SUBSYS_NS_LS_ICMP :
284             if( (encap[3] == NETTL_SUBSYS_NS_LS_IP)
285             ||  (encap[3] == NETTL_SUBSYS_NS_LS_LOOPBACK)
286             ||  (encap[3] == NETTL_SUBSYS_NS_LS_UDP)
287             ||  (encap[3] == NETTL_SUBSYS_NS_LS_TCP) ){
288                 phdr->pkt_encap = WTAP_ENCAP_RAW_IP;
289             } else if (encap[3] == NETTL_SUBSYS_NS_LS_ICMP) {
290                 phdr->pkt_encap = WTAP_ENCAP_UNKNOWN;
291             } else {
292                 wth->file_encap = WTAP_ENCAP_ETHERNET;
293                 phdr->pkt_encap = WTAP_ENCAP_ETHERNET;
294             }
295
296             bytes_read = file_read(&ip_hdr, 1, sizeof ip_hdr, fh);
297             if (bytes_read != sizeof ip_hdr) {
298                 *err = file_error(fh);
299                 if (*err != 0)
300                     return -1;
301                 if (bytes_read != 0) {
302                     *err = WTAP_ERR_SHORT_READ;
303                     return -1;
304                 }
305                 return 0;
306             }
307             offset += sizeof ip_hdr;
308
309             /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
310              * HP-UX 9 and 10 */
311             if (wth->capture.nettl->is_hpux_11) {
312                 bytes_read = file_read(dummy, 1, 4, fh);
313                 if (bytes_read != 4) {
314                     *err = file_error(fh);
315                     if (*err != 0)
316                         return -1;
317                     if (bytes_read != 0) {
318                         *err = WTAP_ERR_SHORT_READ;
319                         return -1;
320                     }
321                     return 0;
322                 }
323                 offset += 4;
324             }
325
326             length = pntohl(&ip_hdr.length);
327             if (length <= 0) return 0;
328             phdr->len = length;
329             length = pntohl(&ip_hdr.caplen);
330             phdr->caplen = length;
331
332
333             phdr->ts.tv_sec = pntohl(&ip_hdr.sec);
334             phdr->ts.tv_usec = pntohl(&ip_hdr.usec);
335             break;
336         case NETTL_SUBSYS_NS_LS_DRIVER :
337             bytes_read = file_read(&ip_hdr, 1, sizeof ip_hdr, fh);
338             if (bytes_read != sizeof ip_hdr) {
339                 *err = file_error(fh);
340                 if (*err != 0)
341                     return -1;
342                 if (bytes_read != 0) {
343                     *err = WTAP_ERR_SHORT_READ;
344                     return -1;
345                 }
346                 return 0;
347             }
348             offset += sizeof ip_hdr;
349
350             /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
351              * HP-UX 9 and 10 */
352             if (wth->capture.nettl->is_hpux_11) {
353                 bytes_read = file_read(dummy, 1, 4, fh);
354                 if (bytes_read != 4) {
355                     *err = file_error(fh);
356                     if (*err != 0)
357                         return -1;
358                     if (bytes_read != 0) {
359                         *err = WTAP_ERR_SHORT_READ;
360                         return -1;
361                     }
362                     return 0;
363                 }
364                 offset += 4;
365             }
366
367             /* XXX we dont know how to identify this as ethernet frames, so
368                we assumes everything is. We will crash and burn for anything else */
369             /* for encapsulated 100baseT we do this */
370             phdr->pkt_encap = WTAP_ENCAP_ETHERNET;
371             bytes_read = file_read(&drv_eth_hdr, 1, sizeof drv_eth_hdr, fh);
372             if (bytes_read != sizeof drv_eth_hdr) {
373                 *err = file_error(fh);
374                 if (*err != 0)
375                     return -1;
376                 if (bytes_read != 0) {
377                     *err = WTAP_ERR_SHORT_READ;
378                     return -1;
379                 }
380                 return 0;
381             }
382             offset += sizeof drv_eth_hdr;
383
384             length = pntohs(&drv_eth_hdr.length); 
385             if (length <= 0) return 0;
386             phdr->len = length;
387             length = pntohs(&drv_eth_hdr.caplen);
388             phdr->caplen = length;
389
390             phdr->ts.tv_sec = pntohl(&ip_hdr.sec);
391             phdr->ts.tv_usec = pntohl(&ip_hdr.usec);
392             break;
393         case NETTL_SUBSYS_SX25L2 :
394             phdr->pkt_encap = WTAP_ENCAP_LAPB;
395             bytes_read = file_read(&lapb_hdr, 1, sizeof lapb_hdr, fh);
396             if (bytes_read != sizeof lapb_hdr) {
397                 *err = file_error(fh);
398                 if (*err != 0)
399                     return -1;
400                 if (bytes_read != 0) {
401                     *err = WTAP_ERR_SHORT_READ;
402                     return -1;
403                 }
404                 return 0;
405             }
406             offset += sizeof lapb_hdr;
407
408             if (wth->capture.nettl->is_hpux_11) {
409                 bytes_read = file_read(dummy, 1, 4, fh);
410                 if (bytes_read != 4) {
411                     *err = file_error(fh);
412                     if (*err != 0)
413                         return -1;
414                     if (bytes_read != 0) {
415                         *err = WTAP_ERR_SHORT_READ;
416                         return -1;
417                     }
418                     return 0;
419                 }
420                 offset += 4;
421             }
422
423             length = pntohs(&lapb_hdr.length);
424             if (length <= 0) return 0;
425             phdr->len = length;
426             phdr->caplen = length;
427
428             phdr->ts.tv_sec = pntohl(&lapb_hdr.sec);
429             phdr->ts.tv_usec = pntohl(&lapb_hdr.usec);
430             pseudo_header->x25.flags =
431                 (lapb_hdr.from_dce & 0x20 ? FROM_DCE : 0x00);
432             break;
433         default:
434             g_message("nettl: network type %u unknown or unsupported",
435                     encap[3]);
436             *err = WTAP_ERR_UNSUPPORTED_ENCAP;
437             return -1;
438     }
439     return offset;
440 }
441
442 static gboolean
443 nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
444 {
445     int bytes_read;
446
447     bytes_read = file_read(pd, 1, length, fh);
448
449     if (bytes_read != length) {
450         *err = file_error(fh);
451         if (*err == 0)
452             *err = WTAP_ERR_SHORT_READ;
453         return FALSE;
454     }
455     return TRUE;
456 }
457
458 static void nettl_close(wtap *wth)
459 {
460     g_free(wth->capture.nettl);
461 }