1 /* nettl.c
2 *
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5 *
6 * Enhancements by Mark C. Brown <mbrown@hp.com>
7 * Copyright (C) 2003, 2005 Hewlett-Packard Development Company, L.P.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "config.h"
13
14 #include <stdlib.h>
15 #include <errno.h>
16 #include <string.h>
17 #include "wtap-int.h"
18 #include "file_wrappers.h"
19 #include "nettl.h"
20
21 /* HP nettl file header */
22
23 /* Magic number size */
24 #define MAGIC_SIZE 12
25
26 /* HP-UX 9.x */
27 static const guint8 nettl_magic_hpux9[MAGIC_SIZE] = {
28 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xD0, 0x00
29 };
30 /* HP-UX 10.x and 11.x */
31 static const guint8 nettl_magic_hpux10[MAGIC_SIZE] = {
32 0x54, 0x52, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
33 };
34
35 #define FILE_HDR_SIZE 128
36 #define NETTL_FILENAME_SIZE 56
37
38 struct nettl_file_hdr {
39 guint8 magic[MAGIC_SIZE];
40 gchar file_name[NETTL_FILENAME_SIZE];
41 gchar tz[20];
42 gchar host_name[9];
43 gchar os_vers[9];
44 guint8 os_v;
45 guint8 xxa[8];
46 gchar model[11];
47 guint16 unknown; /* just padding to 128 bytes? */
48 };
49
50 /* HP nettl record header */
51 /* see /usr/include/sys/netdiag1.h for hints */
52 struct nettlrec_hdr {
53 guint16 hdr_len;
54 guint16 subsys;
55 guint32 devid;
56 guint8 xxa[4];
57 guint32 kind;
58 guint8 xxb[16];
59 guint32 caplen;
60 guint32 length;
61 guint32 sec;
62 guint32 usec;
63 guint32 pid;
64 guint8 xxc[8];
65 guint32 uid;
66 /* Other stuff might be here, but isn't always here */
67 };
68
69 /*
70 * This is what we treat as the minimum size of a record header.
71 * It is *not* necessarily the same as sizeof(struct nettlrec_hdr),
72 * because it doesn't include any padding added to the structure.
73 */
74 #define NETTL_REC_HDR_LEN 64
75
76 /* HP nettl record header for the SX25L2 subsystem - The FCS is not included
77 in the file. */
78 struct nettlrec_sx25l2_hdr {
79 guint8 xxa[8];
80 guint8 from_dce;
81 guint8 xxb[55];
82 guint8 caplen[2];
83 guint8 length[2];
84 guint8 xxc[4];
85 guint8 sec[4];
86 guint8 usec[4];
87 guint8 xxd[4];
88 };
89
90 /* NL_LS_DRIVER :
91 The following shows what the header and subheader looks like for NS_LS_DRIVER
92 The capture was taken on HPUX11 and for a 100baseT interface.
93
94 000080 00 44 00 0b 00 00 00 02 00 00 00 00 20 00 00 00
95 000090 00 00 00 00 00 00 04 06 00 00 00 00 00 00 00 00
96 0000a0 00 00 00 74 00 00 00 74 3c e3 76 19 00 06 34 63
97 0000b0 ff ff ff ff 00 00 00 00 00 00 00 00 ff ff ff ff
98 0000c0 00 00 00 00 00 00 01 02 00 5c 00 5c ff ff ff ff
99 0000d0 3c e3 76 19 00 06 34 5a 00 0b 00 14 <here starts the MAC header>
100
101 Each entry starts with 0x0044000b
102
103 The values 0x005c at position 0x0000c8 and 0x0000ca matches the number of
104 bytes in the packet up to the next entry, which starts with 0x00440b again.
105 These are the captured and real and captured length of the packet.
106
107 The values 0x00000074 at positions 0x0000a0 and 0x0000a4 seems to indicate
108 the same number as positions 0x0000c8 and 0x0000ca but added with 24.
109 Perhaps we have here two layers of headers.
110 The first layer is fixed and consists of all the bytes from 0x000084 up to and
111 including 0x0000c3 which is a generic header for all packets captured from any
112 device. This header might be of fixed size 64 bytes (although the first two
113 bytes appear to be the length of that header, in big-endian format) and there
114 might be something in it which indicates the type of the next header which is
115 link type specific. Following this header there is another header for the
116 100baseT interface which in this case is 24 bytes long spanning positions
117 0x0000c4 to 0x0000db.
118
119 In another capture, claimed to be taken on an HP-UX 8 box, but with a
120 file header suggesting it was taken on HP-UX 10.20, the header for
121 NS_LS_DRIVER looks like:
122
123 000080 00 40 00 0b ff ff ff ff 00 00 00 00 00 00 00 00
124 000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
125 0000a0 00 00 00 51 00 00 00 51 42 02 5e bf 00 0e ab 7c
126 0000b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
127 0000c0 00 02 01 00 00 3b 00 3b ff ff ff ff 42 02 5e bf
128 0000d0 00 0e 8e 44 00 0b <here starts the MAC header>
129
130 When someone reports that the loading of the captures breaks, we can
131 compare this header above with what he/she got to learn how to
132 distinguish between different types of link specific headers.
133
134
135 For now, the subheader for 100baseT seems to be
136 4-5 captured length
137 6-7 actual length
138 8-11 unknown
139 12-15 secs
140 16-19 usecs
141 20-21 unknown
142 */
143 struct nettlrec_ns_ls_drv_eth_hdr {
144 guint8 xxa[4];
145 guint8 caplen[2];
146 guint8 length[2];
147 guint8 xxb[4];
148 guint8 sec[4];
149 guint8 usec[4];
150 guint8 xxc[2];
151 };
152
153 /*
154 * This is the size of an NS_LS_DRV_ETH header; it is *not* necessarily
155 * the same as sizeof(struct nettlrec_ns_ls_drv_eth_hdr), because it
156 * doesn't include any padding added to the structure.
157 */
158 #define NS_LS_DRV_ETH_HDR_LEN 22
159
160 /* header is followed by data and once again the total length (2 bytes) ! */
161
162 typedef struct {
163 gboolean is_hpux_11;
164 } nettl_t;
165
166 static gboolean nettl_read(wtap *wth, wtap_rec *rec, Buffer *buf,
167 int *err, gchar **err_info, gint64 *data_offset);
168 static gboolean nettl_seek_read(wtap *wth, gint64 seek_off,
169 wtap_rec *rec, Buffer *buf,
170 int *err, gchar **err_info);
171 static gboolean nettl_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec,
172 Buffer *buf, int *err, gchar **err_info);
173 static gboolean nettl_dump(wtap_dumper *wdh, const wtap_rec *rec,
174 const guint8 *pd, int *err, gchar **err_info);
175
176 static int nettl_file_type_subtype = -1;
177
178 void register_nettl(void);
179
nettl_open(wtap * wth,int * err,gchar ** err_info)180 wtap_open_return_val nettl_open(wtap *wth, int *err, gchar **err_info)
181 {
182 struct nettl_file_hdr file_hdr;
183 guint16 dummy[2];
184 int subsys;
185 nettl_t *nettl;
186
187 memset(&file_hdr, 0, sizeof(file_hdr));
188
189 /* Read in the string that should be at the start of a HP file */
190 if (!wtap_read_bytes(wth->fh, file_hdr.magic, MAGIC_SIZE, err, err_info)) {
191 if (*err != WTAP_ERR_SHORT_READ)
192 return WTAP_OPEN_ERROR;
193 return WTAP_OPEN_NOT_MINE;
194 }
195
196 if (memcmp(file_hdr.magic, nettl_magic_hpux9, MAGIC_SIZE) &&
197 memcmp(file_hdr.magic, nettl_magic_hpux10, MAGIC_SIZE)) {
198 return WTAP_OPEN_NOT_MINE;
199 }
200
201 /* Read the rest of the file header */
202 if (!wtap_read_bytes(wth->fh, file_hdr.file_name, FILE_HDR_SIZE - MAGIC_SIZE,
203 err, err_info))
204 return WTAP_OPEN_ERROR;
205
206 /* This is an nettl file */
207 wth->file_type_subtype = nettl_file_type_subtype;
208 nettl = g_new(nettl_t,1);
209 wth->priv = (void *)nettl;
210 if (file_hdr.os_vers[2] == '1' && file_hdr.os_vers[3] == '1')
211 nettl->is_hpux_11 = TRUE;
212 else
213 nettl->is_hpux_11 = FALSE;
214 wth->subtype_read = nettl_read;
215 wth->subtype_seek_read = nettl_seek_read;
216 wth->snapshot_length = 0; /* not available */
217
218 /* read the first header to take a guess at the file encap */
219 if (!wtap_read_bytes_or_eof(wth->fh, dummy, 4, err, err_info)) {
220 if (*err == 0) {
221 /* EOF, so no records */
222 return WTAP_OPEN_NOT_MINE;
223 }
224 return WTAP_OPEN_ERROR;
225 }
226
227 subsys = g_ntohs(dummy[1]);
228 switch (subsys) {
229 case NETTL_SUBSYS_HPPB_FDDI :
230 case NETTL_SUBSYS_EISA_FDDI :
231 case NETTL_SUBSYS_PCI_FDDI :
232 case NETTL_SUBSYS_HSC_FDDI :
233 wth->file_encap = WTAP_ENCAP_NETTL_FDDI;
234 break;
235 case NETTL_SUBSYS_TOKEN :
236 case NETTL_SUBSYS_PCI_TR :
237 wth->file_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
238 break;
239 case NETTL_SUBSYS_NS_LS_IP :
240 case NETTL_SUBSYS_NS_LS_LOOPBACK :
241 case NETTL_SUBSYS_NS_LS_TCP :
242 case NETTL_SUBSYS_NS_LS_UDP :
243 case NETTL_SUBSYS_NS_LS_IPV6 :
244 wth->file_encap = WTAP_ENCAP_NETTL_RAW_IP;
245 break;
246 case NETTL_SUBSYS_NS_LS_ICMP :
247 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
248 break;
249 case NETTL_SUBSYS_NS_LS_ICMPV6 :
250 wth->file_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
251 break;
252 case NETTL_SUBSYS_NS_LS_TELNET :
253 wth->file_encap = WTAP_ENCAP_NETTL_RAW_TELNET;
254 break;
255 default:
256 /* If this assumption is bad, the read will catch it */
257 wth->file_encap = WTAP_ENCAP_NETTL_ETHERNET;
258 }
259
260 if (file_seek(wth->fh, FILE_HDR_SIZE, SEEK_SET, err) == -1) {
261 return WTAP_OPEN_ERROR;
262 }
263 wth->file_tsprec = WTAP_TSPREC_USEC;
264
265 return WTAP_OPEN_MINE;
266 }
267
268 /* Read the next packet */
nettl_read(wtap * wth,wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info,gint64 * data_offset)269 static gboolean nettl_read(wtap *wth, wtap_rec *rec, Buffer *buf,
270 int *err, gchar **err_info, gint64 *data_offset)
271 {
272 /* Read record. */
273 *data_offset = file_tell(wth->fh);
274 if (!nettl_read_rec(wth, wth->fh, rec, buf, err, err_info)) {
275 /* Read error or EOF */
276 return FALSE;
277 }
278
279 /*
280 * If the per-file encapsulation isn't known, set it to this
281 * packet's encapsulation.
282 *
283 * If it *is* known, and it isn't this packet's encapsulation,
284 * set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
285 * have a single encapsulation for all packets in the file.
286 */
287 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
288 wth->file_encap = rec->rec_header.packet_header.pkt_encap;
289 else {
290 if (wth->file_encap != rec->rec_header.packet_header.pkt_encap)
291 wth->file_encap = WTAP_ENCAP_PER_PACKET;
292 }
293
294 return TRUE;
295 }
296
297 static gboolean
nettl_seek_read(wtap * wth,gint64 seek_off,wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info)298 nettl_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec,
299 Buffer *buf, int *err, gchar **err_info)
300 {
301 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
302 return FALSE;
303
304 /* Read record. */
305 if (!nettl_read_rec(wth, wth->random_fh, rec, buf, err, err_info)) {
306 /* Read error or EOF */
307 if (*err == 0) {
308 /* EOF means "short read" in random-access mode */
309 *err = WTAP_ERR_SHORT_READ;
310 }
311 return FALSE;
312 }
313 return TRUE;
314 }
315
316 static gboolean
nettl_read_rec(wtap * wth,FILE_T fh,wtap_rec * rec,Buffer * buf,int * err,gchar ** err_info)317 nettl_read_rec(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
318 int *err, gchar **err_info)
319 {
320 union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
321 nettl_t *nettl = (nettl_t *)wth->priv;
322 gboolean fddihack = FALSE;
323 struct nettlrec_hdr rec_hdr;
324 guint16 hdr_len;
325 struct nettlrec_ns_ls_drv_eth_hdr drv_eth_hdr;
326 guint32 length, caplen;
327 int subsys;
328 guint padlen;
329 int datalen;
330 guint8 dummyc[16];
331 int bytes_to_read;
332 guint8 *pd;
333
334 if (!wtap_read_bytes_or_eof(fh, &rec_hdr.hdr_len, sizeof rec_hdr.hdr_len,
335 err, err_info))
336 return FALSE;
337 hdr_len = g_ntohs(rec_hdr.hdr_len);
338 if (hdr_len < NETTL_REC_HDR_LEN) {
339 *err = WTAP_ERR_BAD_FILE;
340 *err_info = g_strdup_printf("nettl: record header length %u too short",
341 hdr_len);
342 return FALSE;
343 }
344 if (!wtap_read_bytes(fh, &rec_hdr.subsys, NETTL_REC_HDR_LEN - 2,
345 err, err_info))
346 return FALSE;
347 subsys = g_ntohs(rec_hdr.subsys);
348 hdr_len -= NETTL_REC_HDR_LEN;
349 /* Skip the rest of the header. */
350 if (!wtap_read_bytes(fh, NULL, hdr_len, err, err_info))
351 return FALSE;
352
353 if ( (pntoh32(&rec_hdr.kind) & NETTL_HDR_PDU_MASK) == 0 ) {
354 /* not actually a data packet (PDU) trace record */
355 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_RAW_IP;
356 length = pntoh32(&rec_hdr.length);
357 caplen = pntoh32(&rec_hdr.caplen);
358 padlen = 0;
359 } else switch (subsys) {
360 case NETTL_SUBSYS_LAN100 :
361 case NETTL_SUBSYS_EISA100BT :
362 case NETTL_SUBSYS_BASE100 :
363 case NETTL_SUBSYS_GSC100BT :
364 case NETTL_SUBSYS_PCI100BT :
365 case NETTL_SUBSYS_SPP100BT :
366 case NETTL_SUBSYS_100VG :
367 case NETTL_SUBSYS_GELAN :
368 case NETTL_SUBSYS_BTLAN :
369 case NETTL_SUBSYS_INTL100 :
370 case NETTL_SUBSYS_IGELAN :
371 case NETTL_SUBSYS_IETHER :
372 case NETTL_SUBSYS_IXGBE :
373 case NETTL_SUBSYS_HSSN :
374 case NETTL_SUBSYS_IGSSN :
375 case NETTL_SUBSYS_ICXGBE :
376 case NETTL_SUBSYS_IEXGBE :
377 case NETTL_SUBSYS_IOCXGBE :
378 case NETTL_SUBSYS_IQXGBE :
379 case NETTL_SUBSYS_HPPB_FDDI :
380 case NETTL_SUBSYS_EISA_FDDI :
381 case NETTL_SUBSYS_PCI_FDDI :
382 case NETTL_SUBSYS_HSC_FDDI :
383 case NETTL_SUBSYS_TOKEN :
384 case NETTL_SUBSYS_PCI_TR :
385 case NETTL_SUBSYS_NS_LS_IP :
386 case NETTL_SUBSYS_NS_LS_LOOPBACK :
387 case NETTL_SUBSYS_NS_LS_TCP :
388 case NETTL_SUBSYS_NS_LS_UDP :
389 case NETTL_SUBSYS_HP_APAPORT :
390 case NETTL_SUBSYS_HP_APALACP :
391 case NETTL_SUBSYS_NS_LS_IPV6 :
392 case NETTL_SUBSYS_NS_LS_ICMPV6 :
393 case NETTL_SUBSYS_NS_LS_ICMP :
394 case NETTL_SUBSYS_NS_LS_TELNET :
395 case NETTL_SUBSYS_NS_LS_SCTP :
396 if( (subsys == NETTL_SUBSYS_NS_LS_IP)
397 || (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK)
398 || (subsys == NETTL_SUBSYS_NS_LS_UDP)
399 || (subsys == NETTL_SUBSYS_NS_LS_TCP)
400 || (subsys == NETTL_SUBSYS_NS_LS_SCTP)
401 || (subsys == NETTL_SUBSYS_NS_LS_IPV6)) {
402 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_RAW_IP;
403 } else if (subsys == NETTL_SUBSYS_NS_LS_ICMP) {
404 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMP;
405 } else if (subsys == NETTL_SUBSYS_NS_LS_ICMPV6) {
406 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_RAW_ICMPV6;
407 } else if (subsys == NETTL_SUBSYS_NS_LS_TELNET) {
408 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_RAW_TELNET;
409 } else if( (subsys == NETTL_SUBSYS_HPPB_FDDI)
410 || (subsys == NETTL_SUBSYS_EISA_FDDI)
411 || (subsys == NETTL_SUBSYS_PCI_FDDI)
412 || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
413 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_FDDI;
414 } else if( (subsys == NETTL_SUBSYS_PCI_TR)
415 || (subsys == NETTL_SUBSYS_TOKEN) ) {
416 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_TOKEN_RING;
417 } else {
418 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
419 }
420
421 length = pntoh32(&rec_hdr.length);
422 caplen = pntoh32(&rec_hdr.caplen);
423
424 /* HPPB FDDI has different inbound vs outbound trace records */
425 if (subsys == NETTL_SUBSYS_HPPB_FDDI) {
426 if (pntoh32(&rec_hdr.kind) == NETTL_HDR_PDUIN) {
427 /* inbound is very strange...
428 there are an extra 3 bytes after the DSAP and SSAP
429 for SNAP frames ???
430 */
431 fddihack=TRUE;
432 padlen = 0;
433 } else {
434 /* outbound appears to have variable padding */
435 if (!wtap_read_bytes(fh, dummyc, 9, err, err_info))
436 return FALSE;
437 /* padding is usually either a total 11 or 16 bytes??? */
438 padlen = (int)dummyc[8];
439 if (!wtap_read_bytes(fh, NULL, padlen, err, err_info))
440 return FALSE;
441 padlen += 9;
442 }
443 } else if ( (subsys == NETTL_SUBSYS_PCI_FDDI)
444 || (subsys == NETTL_SUBSYS_EISA_FDDI)
445 || (subsys == NETTL_SUBSYS_HSC_FDDI) ) {
446 /* other flavor FDDI cards have an extra 3 bytes of padding */
447 if (!wtap_read_bytes(fh, NULL, 3, err, err_info))
448 return FALSE;
449 padlen = 3;
450 } else if (subsys == NETTL_SUBSYS_NS_LS_LOOPBACK) {
451 /* LOOPBACK has an extra 26 bytes of padding */
452 if (!wtap_read_bytes(fh, NULL, 26, err, err_info))
453 return FALSE;
454 padlen = 26;
455 } else if (subsys == NETTL_SUBSYS_NS_LS_SCTP) {
456 /*
457 * SCTP 8 byte header that we will ignore...
458 * 32 bit integer defines format
459 * 1 = Log
460 * 2 = ASCII
461 * 3 = Binary (PDUs should be Binary format)
462 * 32 bit integer defines type
463 * 1 = Inbound
464 * 2 = Outbound
465 */
466 if (!wtap_read_bytes(fh, NULL, 8, err, err_info))
467 return FALSE;
468 padlen = 8;
469 } else {
470 padlen = 0;
471 }
472 break;
473
474 case NETTL_SUBSYS_NS_LS_DRIVER :
475 /* XXX we don't know how to identify this as ethernet frames, so
476 we assume everything is. We will crash and burn for anything else */
477 /* for encapsulated 100baseT we do this */
478 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
479 if (!wtap_read_bytes(fh, &drv_eth_hdr, NS_LS_DRV_ETH_HDR_LEN,
480 err, err_info))
481 return FALSE;
482
483 length = pntoh16(&drv_eth_hdr.length);
484 caplen = pntoh16(&drv_eth_hdr.caplen);
485 /*
486 * XXX - is there a length field that would give the length
487 * of this header, so that we don't have to check for
488 * nettl files from HP-UX 11?
489 *
490 * And what are the extra two bytes?
491 */
492 if (nettl->is_hpux_11) {
493 if (!wtap_read_bytes(fh, NULL, 2, err, err_info))
494 return FALSE;
495 }
496 padlen = 0;
497 break;
498
499 case NETTL_SUBSYS_SX25L2:
500 case NETTL_SUBSYS_SX25L3:
501 /*
502 * XXX - is the 24-byte padding actually a header with
503 * packet lengths, time stamps, etc., just as is the case
504 * for NETTL_SUBSYS_NS_LS_DRIVER? It might be
505 *
506 * guint8 caplen[2];
507 * guint8 length[2];
508 * guint8 xxc[4];
509 * guint8 sec[4];
510 * guint8 usec[4];
511 * guint8 xxd[4];
512 *
513 * or something such as that - if it has 4 bytes before that
514 * (making it 24 bytes), it'd be like struct
515 * nettlrec_ns_ls_drv_eth_hdr but with 2 more bytes at the end.
516 *
517 * And is "from_dce" at xxa[0] in the nettlrec_hdr structure?
518 */
519 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_X25;
520 length = pntoh32(&rec_hdr.length);
521 caplen = pntoh32(&rec_hdr.caplen);
522 padlen = 24; /* sizeof (struct nettlrec_sx25l2_hdr) - NETTL_REC_HDR_LEN + 4 */
523 if (!wtap_read_bytes(fh, NULL, padlen, err, err_info))
524 return FALSE;
525 break;
526
527 default:
528 /* We're going to assume it's ethernet if we don't recognize the
529 subsystem -- We'll probably spew junks and core if it isn't... */
530 wth->file_encap = WTAP_ENCAP_PER_PACKET;
531 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_NETTL_ETHERNET;
532 length = pntoh32(&rec_hdr.length);
533 caplen = pntoh32(&rec_hdr.caplen);
534 padlen = 0;
535 break;
536 }
537
538 if (length < padlen) {
539 *err = WTAP_ERR_BAD_FILE;
540 *err_info = g_strdup_printf("nettl: packet length %u in record header too short, less than %u",
541 length, padlen);
542 return FALSE;
543 }
544 rec->rec_type = REC_TYPE_PACKET;
545 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
546 rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
547 rec->rec_header.packet_header.len = length - padlen;
548 if (caplen < padlen) {
549 *err = WTAP_ERR_BAD_FILE;
550 *err_info = g_strdup_printf("nettl: captured length %u in record header too short, less than %u",
551 caplen, padlen);
552 return FALSE;
553 }
554 datalen = caplen - padlen;
555 rec->rec_header.packet_header.caplen = datalen;
556 rec->ts.secs = pntoh32(&rec_hdr.sec);
557 rec->ts.nsecs = pntoh32(&rec_hdr.usec) * 1000;
558
559 pseudo_header->nettl.subsys = subsys;
560 pseudo_header->nettl.devid = pntoh32(&rec_hdr.devid);
561 pseudo_header->nettl.kind = pntoh32(&rec_hdr.kind);
562 pseudo_header->nettl.pid = pntoh32(&rec_hdr.pid);
563 pseudo_header->nettl.uid = pntoh32(&rec_hdr.uid);
564
565 if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
566 /*
567 * Probably a corrupt capture file; don't blow up trying
568 * to allocate space for an immensely-large packet.
569 */
570 *err = WTAP_ERR_BAD_FILE;
571 *err_info = g_strdup_printf("nettl: File has %u-byte packet, bigger than maximum of %u",
572 rec->rec_header.packet_header.caplen, WTAP_MAX_PACKET_SIZE_STANDARD);
573 return FALSE;
574 }
575
576 /*
577 * Read the packet data.
578 */
579 ws_buffer_assure_space(buf, datalen);
580 pd = ws_buffer_start_ptr(buf);
581 if (fddihack) {
582 /* read in FC, dest, src, DSAP and SSAP */
583 bytes_to_read = 15;
584 if (bytes_to_read > datalen)
585 bytes_to_read = datalen;
586 if (!wtap_read_bytes(fh, pd, bytes_to_read, err, err_info))
587 return FALSE;
588 datalen -= bytes_to_read;
589 if (datalen == 0) {
590 /* There's nothing past the FC, dest, src, DSAP and SSAP */
591 return TRUE;
592 }
593 if (pd[13] == 0xAA) {
594 /* it's SNAP, have to eat 3 bytes??? */
595 bytes_to_read = 3;
596 if (bytes_to_read > datalen)
597 bytes_to_read = datalen;
598 if (!wtap_read_bytes(fh, NULL, bytes_to_read, err, err_info))
599 return FALSE;
600 datalen -= bytes_to_read;
601 if (datalen == 0) {
602 /* There's nothing past the FC, dest, src, DSAP, SSAP, and 3 bytes to eat */
603 return TRUE;
604 }
605 }
606 if (!wtap_read_bytes(fh, pd + 15, datalen, err, err_info))
607 return FALSE;
608 } else {
609 if (!wtap_read_bytes(fh, pd, datalen, err, err_info))
610 return FALSE;
611 }
612
613 return TRUE;
614 }
615
616 /* Returns 0 if we could write the specified encapsulation type,
617 an error indication otherwise. nettl files are WTAP_ENCAP_UNKNOWN
618 when they are first opened, so we allow that for tshark read/write.
619 */
620
nettl_dump_can_write_encap(int encap)621 static int nettl_dump_can_write_encap(int encap)
622 {
623
624 switch (encap) {
625 case WTAP_ENCAP_ETHERNET:
626 case WTAP_ENCAP_FDDI_BITSWAPPED:
627 case WTAP_ENCAP_TOKEN_RING:
628 case WTAP_ENCAP_NETTL_ETHERNET:
629 case WTAP_ENCAP_NETTL_FDDI:
630 case WTAP_ENCAP_NETTL_TOKEN_RING:
631 case WTAP_ENCAP_NETTL_RAW_IP:
632 case WTAP_ENCAP_NETTL_RAW_ICMP:
633 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
634 case WTAP_ENCAP_NETTL_RAW_TELNET:
635 /*
636 case WTAP_ENCAP_NETTL_X25:
637 */
638 case WTAP_ENCAP_PER_PACKET:
639 case WTAP_ENCAP_UNKNOWN:
640 case WTAP_ENCAP_NETTL_UNKNOWN:
641 return 0;
642 default:
643 return WTAP_ERR_UNWRITABLE_ENCAP;
644 }
645 }
646
647
648 /* Returns TRUE on success, FALSE on failure;
649 sets "*err" to an error code on failure */
nettl_dump_open(wtap_dumper * wdh,int * err,gchar ** err_info _U_)650 static gboolean nettl_dump_open(wtap_dumper *wdh, int *err, gchar **err_info _U_)
651 {
652 struct nettl_file_hdr file_hdr;
653
654 /* This is a nettl file */
655 wdh->subtype_write = nettl_dump;
656
657 /* Write the file header. */
658 memset(&file_hdr,0,sizeof(file_hdr));
659 memcpy(file_hdr.magic,nettl_magic_hpux10,sizeof(file_hdr.magic));
660 (void) g_strlcpy(file_hdr.file_name,"/tmp/wireshark.TRC000",NETTL_FILENAME_SIZE);
661 (void) g_strlcpy(file_hdr.tz,"UTC",20);
662 (void) g_strlcpy(file_hdr.host_name,"",9);
663 (void) g_strlcpy(file_hdr.os_vers,"B.11.11",9);
664 file_hdr.os_v=0x55;
665 (void) g_strlcpy(file_hdr.model,"9000/800",11);
666 file_hdr.unknown=g_htons(0x406);
667 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof file_hdr, err))
668 return FALSE;
669 wdh->bytes_dumped += sizeof(file_hdr);
670
671 return TRUE;
672 }
673
674 /* Write a record for a packet to a dump file.
675 Returns TRUE on success, FALSE on failure. */
nettl_dump(wtap_dumper * wdh,const wtap_rec * rec,const guint8 * pd,int * err,gchar ** err_info _U_)676 static gboolean nettl_dump(wtap_dumper *wdh,
677 const wtap_rec *rec,
678 const guint8 *pd, int *err, gchar **err_info _U_)
679 {
680 const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
681 struct nettlrec_hdr rec_hdr;
682 guint8 dummyc[24];
683
684 /* We can only write packet records. */
685 if (rec->rec_type != REC_TYPE_PACKET) {
686 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
687 return FALSE;
688 }
689
690 /* Don't write anything we're not willing to read. */
691 if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
692 *err = WTAP_ERR_PACKET_TOO_LARGE;
693 return FALSE;
694 }
695
696 memset(&rec_hdr,0,sizeof(rec_hdr));
697 /* HP-UX 11.X header should be 68 bytes */
698 rec_hdr.hdr_len = g_htons(sizeof(rec_hdr) + 4);
699 rec_hdr.kind = g_htonl(NETTL_HDR_PDUIN);
700 rec_hdr.sec = g_htonl(rec->ts.secs);
701 rec_hdr.usec = g_htonl(rec->ts.nsecs/1000);
702 rec_hdr.caplen = g_htonl(rec->rec_header.packet_header.caplen);
703 rec_hdr.length = g_htonl(rec->rec_header.packet_header.len);
704 rec_hdr.devid = -1;
705 rec_hdr.pid = -1;
706 rec_hdr.uid = -1;
707
708 switch (rec->rec_header.packet_header.pkt_encap) {
709
710 case WTAP_ENCAP_NETTL_FDDI:
711 /* account for pad bytes */
712 rec_hdr.caplen = g_htonl(rec->rec_header.packet_header.caplen + 3);
713 rec_hdr.length = g_htonl(rec->rec_header.packet_header.len + 3);
714 /* fall through and fill the rest of the fields */
715 /* FALL THROUGH */
716 case WTAP_ENCAP_NETTL_ETHERNET:
717 case WTAP_ENCAP_NETTL_TOKEN_RING:
718 case WTAP_ENCAP_NETTL_RAW_IP:
719 case WTAP_ENCAP_NETTL_RAW_ICMP:
720 case WTAP_ENCAP_NETTL_RAW_ICMPV6:
721 case WTAP_ENCAP_NETTL_RAW_TELNET:
722 case WTAP_ENCAP_NETTL_UNKNOWN:
723 rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
724 rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
725 rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
726 rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
727 rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
728 break;
729
730 case WTAP_ENCAP_RAW_IP:
731 rec_hdr.subsys = g_htons(NETTL_SUBSYS_NS_LS_IP);
732 break;
733
734 case WTAP_ENCAP_ETHERNET:
735 rec_hdr.subsys = g_htons(NETTL_SUBSYS_BTLAN);
736 break;
737
738 case WTAP_ENCAP_FDDI_BITSWAPPED:
739 rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_FDDI);
740 /* account for pad bytes */
741 rec_hdr.caplen = g_htonl(rec->rec_header.packet_header.caplen + 3);
742 rec_hdr.length = g_htonl(rec->rec_header.packet_header.len + 3);
743 break;
744
745 case WTAP_ENCAP_TOKEN_RING:
746 rec_hdr.subsys = g_htons(NETTL_SUBSYS_PCI_TR);
747 break;
748 #if 0
749 case WTAP_ENCAP_NETTL_X25:
750 rec_hdr.caplen = g_htonl(rec->rec_header.packet_header.caplen + 24);
751 rec_hdr.length = g_htonl(rec->rec_header.packet_header.len + 24);
752 rec_hdr.subsys = g_htons(pseudo_header->nettl.subsys);
753 rec_hdr.devid = g_htonl(pseudo_header->nettl.devid);
754 rec_hdr.kind = g_htonl(pseudo_header->nettl.kind);
755 rec_hdr.pid = g_htonl(pseudo_header->nettl.pid);
756 rec_hdr.uid = g_htons(pseudo_header->nettl.uid);
757 break;
758 #endif
759 default:
760 /* found one we don't support */
761 *err = WTAP_ERR_UNWRITABLE_ENCAP;
762 return FALSE;
763 }
764
765 if (!wtap_dump_file_write(wdh, &rec_hdr, sizeof(rec_hdr), err))
766 return FALSE;
767 wdh->bytes_dumped += sizeof(rec_hdr);
768
769 /* Write out 4 extra bytes of unknown stuff for HP-UX11
770 * header format.
771 */
772 memset(dummyc, 0, sizeof dummyc);
773 if (!wtap_dump_file_write(wdh, dummyc, 4, err))
774 return FALSE;
775 wdh->bytes_dumped += 4;
776
777 if ((rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) ||
778 (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_NETTL_FDDI)) {
779 /* add those weird 3 bytes of padding */
780 if (!wtap_dump_file_write(wdh, dummyc, 3, err))
781 return FALSE;
782 wdh->bytes_dumped += 3;
783 }
784 /*
785 } else if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_NETTL_X25) {
786 if (!wtap_dump_file_write(wdh, dummyc, 24, err))
787 return FALSE;
788 wdh->bytes_dumped += 24;
789 }
790 */
791
792 /* write actual PDU data */
793
794 if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
795 return FALSE;
796 wdh->bytes_dumped += rec->rec_header.packet_header.caplen;
797
798 return TRUE;
799 }
800
801 static const struct supported_block_type nettl_blocks_supported[] = {
802 /*
803 * We support packet blocks, with no comments or other options.
804 */
805 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
806 };
807
808 static const struct file_type_subtype_info nettl_info = {
809 "HP-UX nettl trace", "nettl", "trc0", "trc1",
810 FALSE, BLOCKS_SUPPORTED(nettl_blocks_supported),
811 nettl_dump_can_write_encap, nettl_dump_open, NULL
812 };
813
register_nettl(void)814 void register_nettl(void)
815 {
816 nettl_file_type_subtype = wtap_register_file_type_subtype(&nettl_info);
817
818 /*
819 * Register name for backwards compatibility with the
820 * wtap_filetypes table in Lua.
821 */
822 wtap_register_backwards_compatibility_lua_name("NETTL",
823 nettl_file_type_subtype);
824 }
825
826 /*
827 * Editor modelines - https://www.wireshark.org/tools/modelines.html
828 *
829 * Local variables:
830 * c-basic-offset: 4
831 * tab-width: 8
832 * indent-tabs-mode: nil
833 * End:
834 *
835 * vi: set shiftwidth=4 tabstop=8 expandtab:
836 * :indentSize=4:tabSize=8:noTabs=true:
837 */
838