6 * Copyright (c) 2011 by Martin Warnes <Martin_Warnes@uk.ibm.com>
8 * Based on toshiba.c and vms.c
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * This module will read the contents of the iSeries (OS/400) Communication trace
27 * Both ASCII & Unicode formatted traces are supported.
29 * iSeries Comms traces consist of a header page and a subsequent number of packet records
31 * The header page contains details on the options set during running of the trace,
32 * currently the following options are a requirement for this module:
34 * 1. Object protocol = ETHERNET (Default)
35 * 2. ASCII or UNICODE file formats.
37 * The above can be acheived by passing option ASCII(*YES) with the trace command
41 /* iSeries header page
43 COMMUNICATIONS TRACE Title: OS400 - OS400 trace 10/28/05 11:44:50 Page: 1
44 Trace Description . . . . . : OS400 - OS400 trace
45 Configuration object . . . . : ETH0
46 Type . . . . . . . . . . . . : 1 1=Line, 2=Network Interface
48 Object protocol . . . . . . : ETHERNET
49 Start date/Time . . . . . . : 10/28/05 11:43:00.341
50 End date/Time . . . . . . . : 10/28/05 11:44:22.148
51 Bytes collected . . . . . . : 11999
52 Buffer size . . . . . . . . : 2048 kilobytes
53 Data direction . . . . . . . : 3 1=Sent, 2=Received, 3=Both
54 Stop on buffer full . . . . : Y Y=Yes, N=No
55 Number of bytes to trace
56 Beginning bytes . . . . . : *MAX Value, *CALC, *MAX
57 Ending bytes . . . . . . : *CALC Value, *CALC
58 Controller name . . . . . . : *ALL *ALL, name
59 Data representation . . . . : 1 1=ASCII, 2=EBCDIC, 3=*CALC
60 Format SNA data only . . . . : N Y=Yes, N=No
61 Format RR, RNR commands . . : N Y=Yes, N=No
62 Format TCP/IP data only . . : Y Y=Yes, N=No
63 IP address . . . . . . . . : *ALL *ALL, address
64 IP address . . . . . . . . : *ALL *ALL, address
65 IP port . . . . . . . . . : *ALL *ALL, IP port
66 Format UI data only . . . . : N Y=Yes, N=No
67 Select Ethernet data . . . . : 3 1=802.3, 2=ETHV2, 3=Both
68 Format Broadcast data . . . : Y Y=Yes, N=No
71 /* iSeries IPv4 formatted packet records consist of a packet header line
72 * identifying the packet number, direction, size, timestamp,
73 * source/destination MAC addresses and packet type.
75 * Thereafter there will be a formated display of the headers above
76 * the link layer, such as ARP, IP, TCP, UDP, and ICMP (all but
77 * ICMP have either been seen in captures or on pages such as the ones
80 * http://www-912.ibm.com/s_dir/SLKBase.nsf/1ac66549a21402188625680b0002037e/e05fb0515bc3449686256ce600512c37?OpenDocument
84 * http://publib.boulder.ibm.com/infocenter/javasdk/v5r0/index.jsp?topic=%2Fcom.ibm.java.doc.diagnostics.50%2Fdiag%2Fproblem_determination%2Fi5os_perf_io_commstrace.html
86 * so we cannot assume that "IP Header" or "TCP Header" will appear). The
87 * formatted display includes lines that show the contents of some of the
88 * fields in the header, as well as hex strings dumps of the headers
89 * themselves, with tags such as "IP Header :", "ARP Header :",
90 * "TCP Header :", "UDP Header :", and (presumably) "ICMP Header:".
92 * If the packet contains data this is displayed as 4 groups of 16 hex digits
93 * followed by an ASCII representaion of the data line.
95 * Information from the packet header line, higher-level headers and, if
96 * available, data lines are extracted by the module for displaying.
99 Record Data Record Controller Destination Source Frame
100 Number S/R Length Timer Name MAC Address MAC Address Format
101 ------ --- ------ --------------- ---------- ------------ ------------ ------
102 8 S 145 11:43:59.82956 0006299C14AE 0006299C14FE ETHV2 Type: 0800
103 Frame Type : IP DSCP: 0 ECN: 00-NECT Length: 145 Protocol: TCP Datagram ID: 388B
104 Src Addr: 10.20.144.150 Dest Addr: 10.20.144.151 Fragment Flags: DON'T,LAST
105 IP Header : 45000091388B40004006CC860A1490960A149097
107 TCP . . . : Src Port: 6006,Unassigned Dest Port: 35366,Unassigned
108 SEQ Number: 2666470699 ('9EEF1D2B'X) ACK Number: 2142147535 ('7FAE93CF'X)
109 Code Bits: ACK PSH Window: 32648 TCP Option: NO OP
110 TCP Header : 17768A269EEF1D2B7FAE93CF80187F885B5600000101080A0517E0F805166DE0
111 Data . . . . . : 5443503200020010 0000004980000000 B800000080470103 01001E0000002000 *TCP2.......I*...*...*G........ .*
112 002F010080000004 0300800700C00600 4002008000000304 00800000060FB067 *./..*.....*..*..@..*.....*....*G*
113 FC276228786B3EB0 EF34F5F1D27EF8DF 20926820E7B322AA 739F1FB20D **'B(XK>**4***.** *H **"*S*.*. *
116 /* iSeries IPv6 formatted traces are similar to the IPv4 version above,
117 * except that the higher-level headers have "IPv6 Header:" and
118 * "ICMPv6 Hdr:", and data data is no longer output in groups of 16 hex
122 Record Data Record Destination Source Frame
123 Number S/R Length Timer MAC Address MAC Address Format
124 ------ --- ------ ------------ ------------ ------------ ------
125 218 S 1488 15:01:14.389 0011BC358680 00096B6BD918 ETHV2 Type: 86DD
126 IPv6 Data: Ver: 06 Traffic Class: 00 Flow Label: 000000
127 Payload Length: 1448 Next Header: 06,TCP Hop Limit: 64
128 Src Addr: fd00:0:0:20f2::122
129 Dest Addr: fd00:0:0:20a0::155
130 IPv6 Header: 6000000005A80640FD000000000020F20000000000000122FD000000000020A0
132 TCP . . . : Src Port: 21246,Unassigned Dest Port: 13601,Unassigned
133 SEQ Number: 2282300877 ('880925CD'X) ACK Number: 3259003715 ('C2407343'X)
134 Code Bits: ACK Window: 65535 TCP Option: NO OP
135 TCP Header : 52FE3521880925CDC24073438010FFFFCFBB00000101080A0E15127000237A08
136 Data . . . . . : 54435032000200140000061880000000ECBEB867F0000000004CE640E6C1D9D5 *TCP2........*...***g*....L*@*****
137 C9D5C740E3C8C9E240C9E240E3C8C540E6C1D9D5C9D5C740C6C9C5D3C4404040 ****@****@**@***@*******@*****@@@*
138 4040404040404040404040404040404040404040404040404040404040404040 *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
141 /* iSeries unformatted packet record consist of the same header record as
142 * the formatted trace but all other records are simply unformatted data
143 * containing higher-level headers and packet data combined.
145 Record Data Record Controller Destination Source Frame Number Number Poll/
146 Number S/R Length Timer Name MAC Address MAC Address Format Command Sent Received Final DSAP SSAP
147 ------ --- ------ --------------- ---------- ------------ ------------ ------ ------- ------ -------- ----- ---- ----
148 1 R 64 12:19:29.97108 000629ECF48E 0006D78E23C2 ETHV2 Type: 0800
149 Data . . . . . : 4500003C27954000 3A06CE3D9797440F 0A5964EAC4F50554 58C9915500000000 *E..<'*@.:.*=**D..YD***.TX**U....*
150 A00216D06A200000 020405B40402080A 1104B6C000000000 010303000B443BF1 **..*J .....*......**.........D;**
154 #include "wtap-int.h"
157 #include "file_wrappers.h"
165 #include <wsutil/str_util.h>
167 #define ISERIES_HDR_MAGIC_STR "COMMUNICATIONS TRACE"
168 #define ISERIES_HDR_MAGIC_LEN 20
169 #define ISERIES_LINE_LENGTH 270
170 #define ISERIES_HDR_LINES_TO_CHECK 100
171 #define ISERIES_PKT_LINES_TO_CHECK 4
172 #define ISERIES_MAX_PACKET_LEN 16384
173 #define ISERIES_MAX_TRACE_LEN 99999999
174 #define ISERIES_PKT_ALLOC_SIZE (pkt_len*2)+1
175 #define ISERIES_FORMAT_ASCII 1
176 #define ISERIES_FORMAT_UNICODE 2
179 gboolean have_date
; /* TRUE if we found a capture start date */
180 int year
, month
, day
; /* The start date */
181 int format
; /* Trace format type */
184 static gboolean
iseries_read (wtap
* wth
, int *err
, gchar
** err_info
,
185 gint64
*data_offset
);
186 static gboolean
iseries_seek_read (wtap
* wth
, gint64 seek_off
,
187 struct wtap_pkthdr
*phdr
,
188 Buffer
* buf
, int len
, int *err
,
190 static gboolean
iseries_check_file_type (wtap
* wth
, int *err
, gchar
**err_info
,
192 static gint64
iseries_seek_next_packet (wtap
* wth
, int *err
, gchar
**err_info
);
193 static gboolean
iseries_parse_packet (wtap
* wth
, FILE_T fh
,
194 struct wtap_pkthdr
*phdr
,
195 Buffer
* buf
, int *err
, gchar
** err_info
);
196 static int iseries_UNICODE_to_ASCII (guint8
* buf
, guint bytes
);
197 static gboolean
iseries_parse_hex_string (const char * ascii
, guint8
* buf
,
201 iseries_open (wtap
* wth
, int *err
, gchar
** err_info
)
205 char magic
[ISERIES_LINE_LENGTH
];
206 char unicodemagic
[] =
207 { '\x43', '\x00', '\x4F', '\x00', '\x4D',
208 '\x00', '\x4D', '\x00', '\x55', '\x00', '\x4E', '\x00', '\x49', '\x00',
209 '\x43', '\x00', '\x41'
213 * Check that file starts with a valid iSeries COMMS TRACE header
214 * by scanning for it in the first line
216 errno
= WTAP_ERR_CANT_READ
;
217 bytes_read
= file_read (&magic
, sizeof magic
, wth
->fh
);
218 if (bytes_read
!= sizeof magic
)
220 *err
= file_error (wth
->fh
, err_info
);
221 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
227 * Check if this is a UNICODE formatted file by scanning for the magic string
230 while ((unsigned)offset
< (ISERIES_LINE_LENGTH
- (sizeof unicodemagic
)))
232 if (memcmp (magic
+ offset
, unicodemagic
, sizeof unicodemagic
) == 0) {
233 if (file_seek (wth
->fh
, 0, SEEK_SET
, err
) == -1)
238 * Do some basic sanity checking to ensure we can handle the
239 * contents of this trace
241 if (!iseries_check_file_type (wth
, err
, err_info
, ISERIES_FORMAT_UNICODE
))
249 wth
->file_encap
= WTAP_ENCAP_ETHERNET
;
250 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_ISERIES
;
251 wth
->snapshot_length
= 0;
252 wth
->subtype_read
= iseries_read
;
253 wth
->subtype_seek_read
= iseries_seek_read
;
254 wth
->tsprecision
= WTAP_FILE_TSPREC_USEC
;
256 if (file_seek (wth
->fh
, 0, SEEK_SET
, err
) == -1)
266 * Check if this is a ASCII formatted file by scanning for the magic string
269 while (offset
< (ISERIES_LINE_LENGTH
- ISERIES_HDR_MAGIC_LEN
))
271 if (memcmp (magic
+ offset
, ISERIES_HDR_MAGIC_STR
, ISERIES_HDR_MAGIC_LEN
) == 0)
273 if (file_seek (wth
->fh
, 0, SEEK_SET
, err
) == -1)
278 * Do some basic sanity checking to ensure we can handle the
279 * contents of this trace
281 if (!iseries_check_file_type (wth
, err
, err_info
, ISERIES_FORMAT_ASCII
))
289 wth
->file_encap
= WTAP_ENCAP_ETHERNET
;
290 wth
->file_type_subtype
= WTAP_FILE_TYPE_SUBTYPE_ISERIES
;
291 wth
->snapshot_length
= 0;
292 wth
->subtype_read
= iseries_read
;
293 wth
->subtype_seek_read
= iseries_seek_read
;
294 wth
->tsprecision
= WTAP_FILE_TSPREC_USEC
;
296 if (file_seek (wth
->fh
, 0, SEEK_SET
, err
) == -1)
305 /* Neither ASCII or UNICODE so not supported */
310 * Do some basic sanity checking to ensure we can handle the
311 * contents of this trace by checking the header page for
312 * requisit requirements and additional information.
315 iseries_check_file_type (wtap
* wth
, int *err
, gchar
**err_info
, int format
)
318 int num_items_scanned
;
319 char buf
[ISERIES_LINE_LENGTH
], protocol
[9];
322 /* Save trace format for passing between packets */
323 iseries
= (iseries_t
*) g_malloc (sizeof (iseries_t
));
324 wth
->priv
= (void *) iseries
;
325 iseries
->have_date
= FALSE
;
326 iseries
->format
= format
;
328 for (line
= 0; line
< ISERIES_HDR_LINES_TO_CHECK
; line
++)
330 if (file_gets (buf
, ISERIES_LINE_LENGTH
, wth
->fh
) == NULL
)
333 *err
= file_error (wth
->fh
, err_info
);
334 if (*err
== WTAP_ERR_SHORT_READ
)
340 * Check that we are dealing with an ETHERNET trace
342 if (iseries
->format
== ISERIES_FORMAT_UNICODE
)
344 iseries_UNICODE_to_ASCII ((guint8
*)buf
, ISERIES_LINE_LENGTH
);
346 ascii_strup_inplace (buf
);
347 num_items_scanned
= sscanf (buf
,
348 "%*[ \n\t]OBJECT PROTOCOL%*[ .:\n\t]%8s",
350 if (num_items_scanned
== 1)
352 if (memcmp (protocol
, "ETHERNET", 8) != 0)
357 * The header is the only place where the date part of the timestamp is held, so
358 * extract it here and store for all packets to access
360 num_items_scanned
= sscanf (buf
,
361 "%*[ \n\t]START DATE/TIME%*[ .:\n\t]%2d/%2d/%2d",
362 &iseries
->month
, &iseries
->day
,
364 if (num_items_scanned
== 3)
366 iseries
->have_date
= TRUE
;
374 * Find the next packet and parse it; called from wtap_read().
377 iseries_read (wtap
* wth
, int *err
, gchar
** err_info
, gint64
*data_offset
)
382 * Locate the next packet
384 offset
= iseries_seek_next_packet (wth
, err
, err_info
);
387 *data_offset
= offset
;
390 * Parse the packet and extract the various fields
392 return iseries_parse_packet (wth
, wth
->fh
, &wth
->phdr
, wth
->frame_buffer
,
397 * Seeks to the beginning of the next packet, and returns the
398 * byte offset. Returns -1 on failure or EOF; on EOF, sets
399 * *err to 0, and, on failure, sets *err to the error and *err_info
400 * to null or an additional error string.
403 iseries_seek_next_packet (wtap
* wth
, int *err
, gchar
**err_info
)
405 iseries_t
*iseries
= (iseries_t
*)wth
->priv
;
406 char buf
[ISERIES_LINE_LENGTH
],type
[5];
407 int line
, num_items_scanned
;
411 for (line
= 0; line
< ISERIES_MAX_TRACE_LEN
; line
++)
413 if (file_gets (buf
, ISERIES_LINE_LENGTH
, wth
->fh
) == NULL
)
416 *err
= file_error (wth
->fh
, err_info
);
419 /* Convert UNICODE to ASCII if required and determine */
420 /* the number of bytes to rewind to beginning of record. */
421 if (iseries
->format
== ISERIES_FORMAT_UNICODE
)
423 /* buflen is #bytes to 1st 0x0A */
424 buflen
= iseries_UNICODE_to_ASCII ((guint8
*) buf
, ISERIES_LINE_LENGTH
);
428 /* Else buflen is just length of the ASCII string */
429 buflen
= (long) strlen (buf
);
431 ascii_strup_inplace (buf
);
432 /* If packet header found return the offset */
435 "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type
);
436 if (num_items_scanned
== 1)
438 /* Rewind to beginning of line */
439 cur_off
= file_tell (wth
->fh
);
442 *err
= file_error (wth
->fh
, err_info
);
445 if (file_seek (wth
->fh
, cur_off
- buflen
, SEEK_SET
, err
) == -1)
449 return cur_off
- buflen
;
453 *err
= WTAP_ERR_BAD_FILE
;
455 g_strdup_printf ("iseries: next packet header not found within %d lines",
456 ISERIES_MAX_TRACE_LEN
);
461 * Read packets in random-access fashion
464 iseries_seek_read (wtap
* wth
, gint64 seek_off
, struct wtap_pkthdr
*phdr
,
465 Buffer
* buf
, int len _U_
, int *err
, gchar
** err_info
)
468 /* seek to packet location */
469 if (file_seek (wth
->random_fh
, seek_off
- 1, SEEK_SET
, err
) == -1)
473 * Parse the packet and extract the various fields
475 return iseries_parse_packet (wth
, wth
->random_fh
, phdr
, buf
,
480 append_hex_digits(char *ascii_buf
, int ascii_offset
, int max_offset
,
481 char *data
, int *err
, gchar
**err_info
)
483 int in_offset
, out_offset
;
486 gboolean overflow
= FALSE
;
489 out_offset
= ascii_offset
;
493 * Process a block of up to 16 hex digits.
494 * The block is terminated early by an end-of-line indication (NUL,
495 * CR, or LF), by a space (which terminates the last block of the
496 * data we're processing), or by a "*", which introduces the ASCII representation
498 * All characters in the block must be upper-case hex digits;
499 * there might or might not be a space *after* a block, but, if so,
500 * that will be skipped over after the block is processed.
502 for (i
= 0; i
< 16; i
++, in_offset
++)
505 * If we see an end-of-line indication, or an early-end-of-block
506 * indication (space), we're done. (Only the last block ends
509 c
= data
[in_offset
] & 0xFF;
510 if (c
== '\0' || c
== ' ' || c
== '*' || c
== '\r' || c
== '\n')
514 if (!isxdigit(c
) || islower(c
))
517 * Not a hex digit, or a lower-case hex digit.
518 * Treat this as an indication that the line isn't a data
519 * line, so we just ignore it.
521 * XXX - do so only for continuation lines; treat non-hex-digit
522 * characters as errors for other lines?
524 return ascii_offset
; /* pretend we appended nothing */
526 if (out_offset
>= max_offset
)
530 ascii_buf
[out_offset
] = c
;
535 * Skip blanks, if any.
537 for (; (data
[in_offset
] & 0xFF) == ' '; in_offset
++)
542 * If we processed an *odd* number of hex digits, report an error.
546 *err
= WTAP_ERR_BAD_FILE
;
547 *err_info
= g_strdup("iseries: odd number of hex digits in a line");
552 *err
= WTAP_ERR_BAD_FILE
;
553 *err_info
= g_strdup("iseries: more packet data than the packet length indicated");
559 /* Parses a packet. */
561 iseries_parse_packet (wtap
* wth
, FILE_T fh
, struct wtap_pkthdr
*phdr
,
562 Buffer
*buf
, int *err
, gchar
**err_info
)
564 iseries_t
*iseries
= (iseries_t
*)wth
->priv
;
566 gboolean isValid
, isCurrentPacket
;
567 int num_items_scanned
, line
, pktline
, buflen
;
568 int pkt_len
, pktnum
, hr
, min
, sec
;
569 char direction
[2], destmac
[13], srcmac
[13], type
[5], csec
[9+1];
570 char data
[ISERIES_LINE_LENGTH
* 2];
577 * Check for packet headers in first 3 lines this should handle page breaks
578 * situations and the header lines output at each page throw and ensure we
579 * read both the captured and packet lengths.
582 for (line
= 1; line
< ISERIES_PKT_LINES_TO_CHECK
; line
++)
584 if (file_gets (data
, ISERIES_LINE_LENGTH
, fh
) == NULL
)
586 *err
= file_error (fh
, err_info
);
589 /* Convert UNICODE data to ASCII */
590 if (iseries
->format
== ISERIES_FORMAT_UNICODE
)
592 iseries_UNICODE_to_ASCII ((guint8
*)data
, ISERIES_LINE_LENGTH
);
594 ascii_strup_inplace (data
);
597 "%*[ \n\t]%6d%*[ *\n\t]%1s%*[ \n\t]%6d%*[ \n\t]%2d:%2d:%2d.%9[0-9]%*[ \n\t]"
598 "%12s%*[ \n\t]%12s%*[ \n\t]ETHV2%*[ \n\t]TYPE:%*[ \n\t]%4s",
599 &pktnum
, direction
, &pkt_len
, &hr
, &min
, &sec
, csec
, destmac
,
601 if (num_items_scanned
== 10)
603 /* OK! We found the packet header line */
606 * XXX - The Capture length returned by the iSeries trace doesn't
607 * seem to include the Ethernet header, so we add its length here.
615 * If no packet header found we exit at this point and inform the user.
619 *err
= WTAP_ERR_BAD_FILE
;
620 *err_info
= g_strdup ("iseries: packet header isn't valid");
624 phdr
->presence_flags
= WTAP_HAS_CAP_LEN
;
627 * If we have Wiretap Header then populate it here
629 * Timer resolution on the iSeries is hardware dependent. We determine
630 * the resolution based on how many digits we see.
632 if (iseries
->have_date
)
634 phdr
->presence_flags
|= WTAP_HAS_TS
;
635 tm
.tm_year
= 100 + iseries
->year
;
636 tm
.tm_mon
= iseries
->month
- 1;
637 tm
.tm_mday
= iseries
->day
;
642 phdr
->ts
.secs
= mktime (&tm
);
643 switch (strlen(csec
))
649 phdr
->ts
.nsecs
= atoi(csec
) * 100000000;
652 phdr
->ts
.nsecs
= atoi(csec
) * 10000000;
655 phdr
->ts
.nsecs
= atoi(csec
) * 1000000;
658 phdr
->ts
.nsecs
= atoi(csec
) * 100000;
661 phdr
->ts
.nsecs
= atoi(csec
) * 10000;
664 phdr
->ts
.nsecs
= atoi(csec
) * 1000;
667 phdr
->ts
.nsecs
= atoi(csec
) * 100;
670 phdr
->ts
.nsecs
= atoi(csec
) * 10;
673 phdr
->ts
.nsecs
= atoi(csec
);
679 phdr
->pkt_encap
= WTAP_ENCAP_ETHERNET
;
680 phdr
->pseudo_header
.eth
.fcs_len
= -1;
682 ascii_buf
= (char *)g_malloc (ISERIES_PKT_ALLOC_SIZE
);
683 g_snprintf(ascii_buf
, ISERIES_PKT_ALLOC_SIZE
, "%s%s%s", destmac
, srcmac
, type
);
684 ascii_offset
= 14*2; /* 14-byte Ethernet header, 2 characters per byte */
687 * Start reading packet contents
689 isCurrentPacket
= TRUE
;
691 /* loop through packet lines and breakout when the next packet header is read */
693 while (isCurrentPacket
)
696 /* Read the next line */
697 if (file_gets (data
, ISERIES_LINE_LENGTH
, fh
) == NULL
)
699 *err
= file_error (fh
, err_info
);
702 /* Hit the EOF without an error */
708 /* Convert UNICODE data to ASCII and determine line length */
709 if (iseries
->format
== ISERIES_FORMAT_UNICODE
)
711 buflen
= iseries_UNICODE_to_ASCII ((guint8
*)data
, ISERIES_LINE_LENGTH
);
715 /* Else bytes to rewind is just length of ASCII string */
716 buflen
= (int) strlen (data
);
720 * Skip leading white space.
722 for (offset
= 0; isspace(data
[offset
]); offset
++)
726 * The higher-level header information starts at an offset of
727 * 22 characters. The header tags are 14 characters long.
729 * XXX - for IPv6, if the next header isn't the last header,
730 * the intermediate headers do *NOT* appear to be shown in
731 * the dump file *at all*, so the packet *cannot* be
736 if (strncmp(data
+ 22, "IP Header : ", 14) == 0 ||
737 strncmp(data
+ 22, "IPv6 Header: ", 14) == 0 ||
738 strncmp(data
+ 22, "ARP Header : ", 14) == 0 ||
739 strncmp(data
+ 22, "TCP Header : ", 14) == 0 ||
740 strncmp(data
+ 22, "UDP Header : ", 14) == 0 ||
741 strncmp(data
+ 22, "ICMP Header: ", 14) == 0 ||
742 strncmp(data
+ 22, "ICMPv6 Hdr: ", 14) == 0 ||
743 strncmp(data
+ 22, "Option Hdr: ", 14) == 0)
745 ascii_offset
= append_hex_digits(ascii_buf
, ascii_offset
,
746 ISERIES_PKT_ALLOC_SIZE
- 1,
749 if (ascii_offset
== -1)
759 * Is this a data line?
761 * The "Data" starts at an offset of 8.
765 if (strncmp(data
+ 9, "Data . . . . . : ", 18) == 0)
767 ascii_offset
= append_hex_digits(ascii_buf
, ascii_offset
,
768 ISERIES_PKT_ALLOC_SIZE
- 1,
771 if (ascii_offset
== -1)
781 * Is this a continuation of a previous header or data line?
782 * That's blanks followed by hex digits; first try the
783 * "no column separators" form.
785 * Continuations of header lines begin at an offset of 36;
786 * continuations of data lines begin at an offset of 27.
788 if (offset
== 36 || offset
== 27)
790 ascii_offset
= append_hex_digits(ascii_buf
, ascii_offset
,
791 ISERIES_PKT_ALLOC_SIZE
- 1,
794 if (ascii_offset
== -1)
803 * If we see the identifier for the next packet then rewind and set
804 * isCurrentPacket FALSE
806 ascii_strup_inplace (data
);
807 /* If packet header found return the offset */
810 "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type
);
811 if ((num_items_scanned
== 1) && pktline
> 1)
813 isCurrentPacket
= FALSE
;
814 cur_off
= file_tell( fh
);
818 *err
= file_error (fh
, err_info
);
821 if (file_seek (fh
, cur_off
- buflen
, SEEK_SET
, err
) == -1)
823 /* XXX: need to set err_info ?? */
828 ascii_buf
[ascii_offset
] = '\0';
831 * Make the captured length be the amount of bytes we've read (which
832 * is half the number of characters of hex dump we have).
834 * XXX - this can happen for IPv6 packets if the next header isn't the
837 phdr
->caplen
= ((guint32
) strlen (ascii_buf
))/2;
839 /* Make sure we have enough room for the packet. */
840 buffer_assure_space (buf
, ISERIES_MAX_PACKET_LEN
);
841 /* Convert ascii data to binary and return in the frame buffer */
842 iseries_parse_hex_string (ascii_buf
, buffer_start_ptr (buf
), strlen (ascii_buf
));
844 /* free buffer allocs and return */
855 * Simple routine to convert an UNICODE buffer to ASCII
857 * XXX - This may be possible with iconv or similar
860 iseries_UNICODE_to_ASCII (guint8
* buf
, guint bytes
)
867 for (i
= 0; i
< bytes
; i
++)
886 * Simple routine to convert an ASCII hex string to binary data
887 * Requires ASCII hex data and buffer to populate with binary data
890 iseries_parse_hex_string (const char * ascii
, guint8
* buf
, size_t len
)
898 for (i
= 0; i
< len
; i
++)
900 hexvalue
= g_ascii_xdigit_value(ascii
[i
]);
903 return FALSE
; /* not a valid hex digit */
904 bytevalue
= (guint8
)(hexvalue
<< 4);
906 return FALSE
; /* only one hex digit of the byte is present */
907 hexvalue
= g_ascii_xdigit_value(ascii
[i
]);
909 return FALSE
; /* not a valid hex digit */
910 bytevalue
|= (guint8
) hexvalue
;
911 buf
[byte
] = bytevalue
;
918 * Editor modelines - http://www.wireshark.org/tools/modelines.html
923 * indent-tabs-mode: nil
926 * vi: set shiftwidth=2 tabstop=8 expandtab:
927 * :indentSize=2:tabSize=8:noTabs=true: