28de0166e2fa851a2f644ba5522f7c63130c42da
[obnox/wireshark/wip.git] / wiretap / nettl.c
1 /* nettl.c
2  *
3  * $Id: nettl.c,v 1.30 2002/07/29 06:09:59 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      length[2];
48     guint8      length2[2];    /* don't know which one is captured length / real length */
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      length[4];
60     guint8      length2[4];    /* don't know which one is captured length / real length */
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     length1   these are probably total/captured len. unknown which.
109         6-7     length2
110         8-11    unknown 
111         12-15   secs
112         16-19   100 x nsec
113         20-23   unknown
114 */
115 struct nettlrec_ns_ls_drv_eth_hdr {
116     guint8      xxa[4];
117     guint8      length[2];
118     guint8      length2[2];
119     guint8      xxb[4];
120     guint8      sec[4];
121     guint8      cnsec[4];  /* unit of 100 nsec */
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_BASE100 :
271         case NETTL_SUBSYS_GSC100BT :
272         case NETTL_SUBSYS_NS_LS_IP :
273         case NETTL_SUBSYS_NS_LS_LOOPBACK :
274         case NETTL_SUBSYS_NS_LS_TCP :
275         case NETTL_SUBSYS_NS_LS_UDP :
276         case 0xb9:      /* XXX unknown encapsulation name */
277         case NETTL_SUBSYS_NS_LS_ICMP :
278             if( (encap[3] == NETTL_SUBSYS_NS_LS_IP) 
279             ||  (encap[3] == NETTL_SUBSYS_NS_LS_LOOPBACK) 
280             ||  (encap[3] == NETTL_SUBSYS_NS_LS_UDP) 
281             ||  (encap[3] == NETTL_SUBSYS_NS_LS_TCP) ){
282                 phdr->pkt_encap = WTAP_ENCAP_RAW_IP; 
283             } else if (encap[3] == NETTL_SUBSYS_NS_LS_ICMP) {
284                 phdr->pkt_encap = WTAP_ENCAP_UNKNOWN; 
285             } else {
286                 wth->file_encap = WTAP_ENCAP_ETHERNET;
287                 phdr->pkt_encap = WTAP_ENCAP_ETHERNET; 
288             }
289
290             bytes_read = file_read(&ip_hdr, 1, sizeof ip_hdr, fh);
291             if (bytes_read != sizeof ip_hdr) {
292                 *err = file_error(fh);
293                 if (*err != 0)
294                     return -1;
295                 if (bytes_read != 0) {
296                     *err = WTAP_ERR_SHORT_READ;
297                     return -1;
298                 }
299                 return 0;
300             }
301             offset += sizeof ip_hdr;
302
303             /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
304              * HP-UX 9 and 10 */
305             if (wth->capture.nettl->is_hpux_11) {
306                 bytes_read = file_read(dummy, 1, 4, fh);
307                 if (bytes_read != 4) {
308                     *err = file_error(fh);
309                     if (*err != 0)
310                         return -1;
311                     if (bytes_read != 0) {
312                         *err = WTAP_ERR_SHORT_READ;
313                         return -1;
314                     }
315                     return 0;
316                 }
317                 offset += 4;
318             }
319
320             length = pntohl(&ip_hdr.length);
321             if (length <= 0) return 0;
322             phdr->len = length;
323             phdr->caplen = length;
324
325             
326             phdr->ts.tv_sec = pntohl(&ip_hdr.sec);
327             /* this filed is in units of 0.1 us for HPUX 11 */
328             if (wth->capture.nettl->is_hpux_11) {
329                     phdr->ts.tv_usec = pntohl(&ip_hdr.usec)/10;
330             } else {
331                     phdr->ts.tv_usec = pntohl(&ip_hdr.usec);
332             }
333             break;
334         case NETTL_SUBSYS_NS_LS_DRIVER :
335             bytes_read = file_read(&ip_hdr, 1, sizeof ip_hdr, fh);
336             if (bytes_read != sizeof ip_hdr) {
337                 *err = file_error(fh);
338                 if (*err != 0)
339                     return -1;
340                 if (bytes_read != 0) {
341                     *err = WTAP_ERR_SHORT_READ;
342                     return -1;
343                 }
344                 return 0;
345             }
346             offset += sizeof ip_hdr;
347
348             /* The packet header in HP-UX 11 nettl traces is 4 octets longer than
349              * HP-UX 9 and 10 */
350             if (wth->capture.nettl->is_hpux_11) {
351                 bytes_read = file_read(dummy, 1, 4, fh);
352                 if (bytes_read != 4) {
353                     *err = file_error(fh);
354                     if (*err != 0)
355                         return -1;
356                     if (bytes_read != 0) {
357                         *err = WTAP_ERR_SHORT_READ;
358                         return -1;
359                     }
360                     return 0;
361                 }
362                 offset += 4;
363             }
364
365             /* XXX we dont know how to identify this as ehternet frames, so
366                we assumes everything is. We will crash and burn for anything else */
367             /* for encapsulated 100baseT we do this */
368             phdr->pkt_encap = WTAP_ENCAP_ETHERNET; 
369             bytes_read = file_read(&drv_eth_hdr, 1, sizeof drv_eth_hdr, fh);
370             if (bytes_read != sizeof drv_eth_hdr) {
371                 *err = file_error(fh);
372                 if (*err != 0)
373                     return -1;
374                 if (bytes_read != 0) {
375                     *err = WTAP_ERR_SHORT_READ;
376                     return -1;
377                 }
378                 return 0;
379             }
380             offset += sizeof drv_eth_hdr;
381
382             length = pntohl(&ip_hdr.length);
383             if (length <= 0) return 0;
384             phdr->len = length;
385             phdr->caplen = length;
386
387             
388             phdr->ts.tv_sec = pntohl(&ip_hdr.sec);
389             /* this filed is in units of 0.1 us for HPUX 11 */
390             if (wth->capture.nettl->is_hpux_11) {
391                     phdr->ts.tv_usec = pntohl(&ip_hdr.usec)/10;
392             } else {
393                     phdr->ts.tv_usec = pntohl(&ip_hdr.usec);
394             }
395             break;
396         case NETTL_SUBSYS_SX25L2 :
397             phdr->pkt_encap = WTAP_ENCAP_LAPB;
398             bytes_read = file_read(&lapb_hdr, 1, sizeof lapb_hdr, fh);
399             if (bytes_read != sizeof lapb_hdr) {
400                 *err = file_error(fh);
401                 if (*err != 0)
402                     return -1;
403                 if (bytes_read != 0) {
404                     *err = WTAP_ERR_SHORT_READ;
405                     return -1;
406                 }
407                 return 0;
408             }
409             offset += sizeof lapb_hdr;
410
411             if (wth->capture.nettl->is_hpux_11) {
412                 bytes_read = file_read(dummy, 1, 4, fh);
413                 if (bytes_read != 4) {
414                     *err = file_error(fh);
415                     if (*err != 0)
416                         return -1;
417                     if (bytes_read != 0) {
418                         *err = WTAP_ERR_SHORT_READ;
419                         return -1;
420                     }
421                     return 0;
422                 }
423                 offset += 4;
424             }
425
426             length = pntohs(&lapb_hdr.length);
427             if (length <= 0) return 0;
428             phdr->len = length;
429             phdr->caplen = length;
430
431             phdr->ts.tv_sec = pntohl(&lapb_hdr.sec);
432             phdr->ts.tv_usec = pntohl(&lapb_hdr.usec);
433             pseudo_header->x25.flags =
434                 (lapb_hdr.from_dce & 0x20 ? FROM_DCE : 0x00);
435             break;
436         default:
437             g_message("nettl: network type %u unknown or unsupported",
438                     encap[3]);
439             *err = WTAP_ERR_UNSUPPORTED_ENCAP;
440             return -1;
441     }
442     return offset;
443 }
444
445 static gboolean
446 nettl_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
447 {
448     int bytes_read;
449
450     bytes_read = file_read(pd, 1, length, fh);
451
452     if (bytes_read != length) {
453         *err = file_error(fh);
454         if (*err == 0)
455             *err = WTAP_ERR_SHORT_READ;
456         return FALSE;
457     }
458     return TRUE;
459 }
460
461 static void nettl_close(wtap *wth)
462 {
463     g_free(wth->capture.nettl);
464 }