4 * Copyright (c) 2011 by Martin Warnes <Martin_Warnes@uk.ibm.com>
6 * Based on toshiba.c and vms.c
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * This module will read the contents of the iSeries (OS/400) Communication trace
25 * Both ASCII & Unicode formatted traces are supported.
27 * iSeries Comms traces consist of a header page and a subsequent number of packet records
29 * The header page contains details on the options set during running of the trace,
30 * currently the following options are a requirement for this module:
32 * 1. Object protocol = ETHERNET (Default)
33 * 2. ASCII or UNICODE file formats.
35 * The above can be acheived by passing option ASCII(*YES) with the trace command
39 /* iSeries header page
41 COMMUNICATIONS TRACE Title: OS400 - OS400 trace 10/28/05 11:44:50 Page: 1
42 Trace Description . . . . . : OS400 - OS400 trace
43 Configuration object . . . . : ETH0
44 Type . . . . . . . . . . . . : 1 1=Line, 2=Network Interface
46 Object protocol . . . . . . : ETHERNET
47 Start date/Time . . . . . . : 10/28/05 11:43:00.341
48 End date/Time . . . . . . . : 10/28/05 11:44:22.148
49 Bytes collected . . . . . . : 11999
50 Buffer size . . . . . . . . : 2048 kilobytes
51 Data direction . . . . . . . : 3 1=Sent, 2=Received, 3=Both
52 Stop on buffer full . . . . : Y Y=Yes, N=No
53 Number of bytes to trace
54 Beginning bytes . . . . . : *MAX Value, *CALC, *MAX
55 Ending bytes . . . . . . : *CALC Value, *CALC
56 Controller name . . . . . . : *ALL *ALL, name
57 Data representation . . . . : 1 1=ASCII, 2=EBCDIC, 3=*CALC
58 Format SNA data only . . . . : N Y=Yes, N=No
59 Format RR, RNR commands . . : N Y=Yes, N=No
60 Format TCP/IP data only . . : Y Y=Yes, N=No
61 IP address . . . . . . . . : *ALL *ALL, address
62 IP address . . . . . . . . : *ALL *ALL, address
63 IP port . . . . . . . . . : *ALL *ALL, IP port
64 Format UI data only . . . . : N Y=Yes, N=No
65 Select Ethernet data . . . . : 3 1=802.3, 2=ETHV2, 3=Both
66 Format Broadcast data . . . : Y Y=Yes, N=No
69 /* iSeries IPv4 formatted packet records consist of a packet header line
70 * identifying the packet number, direction, size, timestamp,
71 * source/destination MAC addresses and packet type.
73 * Thereafter there will be a formated display of the headers above
74 * the link layer, such as ARP, IP, TCP, UDP, and ICMP (all but
75 * ICMP have either been seen in captures or on pages such as the ones
78 * http://www-912.ibm.com/s_dir/SLKBase.nsf/1ac66549a21402188625680b0002037e/e05fb0515bc3449686256ce600512c37?OpenDocument
82 * 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
84 * so we cannot assume that "IP Header" or "TCP Header" will appear). The
85 * formatted display includes lines that show the contents of some of the
86 * fields in the header, as well as hex strings dumps of the headers
87 * themselves, with tags such as "IP Header :", "ARP Header :",
88 * "TCP Header :", "UDP Header :", and (presumably) "ICMP Header:".
90 * If the packet contains data this is displayed as 4 groups of 16 hex digits
91 * followed by an ASCII representaion of the data line.
93 * Information from the packet header line, higher-level headers and, if
94 * available, data lines are extracted by the module for displaying.
97 Record Data Record Controller Destination Source Frame
98 Number S/R Length Timer Name MAC Address MAC Address Format
99 ------ --- ------ --------------- ---------- ------------ ------------ ------
100 8 S 145 11:43:59.82956 0006299C14AE 0006299C14FE ETHV2 Type: 0800
101 Frame Type : IP DSCP: 0 ECN: 00-NECT Length: 145 Protocol: TCP Datagram ID: 388B
102 Src Addr: 10.20.144.150 Dest Addr: 10.20.144.151 Fragment Flags: DON'T,LAST
103 IP Header : 45000091388B40004006CC860A1490960A149097
105 TCP . . . : Src Port: 6006,Unassigned Dest Port: 35366,Unassigned
106 SEQ Number: 2666470699 ('9EEF1D2B'X) ACK Number: 2142147535 ('7FAE93CF'X)
107 Code Bits: ACK PSH Window: 32648 TCP Option: NO OP
108 TCP Header : 17768A269EEF1D2B7FAE93CF80187F885B5600000101080A0517E0F805166DE0
109 Data . . . . . : 5443503200020010 0000004980000000 B800000080470103 01001E0000002000 *TCP2.......I*...*...*G........ .*
110 002F010080000004 0300800700C00600 4002008000000304 00800000060FB067 *./..*.....*..*..@..*.....*....*G*
111 FC276228786B3EB0 EF34F5F1D27EF8DF 20926820E7B322AA 739F1FB20D **'B(XK>**4***.** *H **"*S*.*. *
114 /* iSeries IPv6 formatted traces are similar to the IPv4 version above,
115 * except that the higher-level headers have "IPv6 Header:" and
116 * "ICMPv6 Hdr:", and data data is no longer output in groups of 16 hex
120 Record Data Record Destination Source Frame
121 Number S/R Length Timer MAC Address MAC Address Format
122 ------ --- ------ ------------ ------------ ------------ ------
123 218 S 1488 15:01:14.389 0011BC358680 00096B6BD918 ETHV2 Type: 86DD
124 IPv6 Data: Ver: 06 Traffic Class: 00 Flow Label: 000000
125 Payload Length: 1448 Next Header: 06,TCP Hop Limit: 64
126 Src Addr: fd00:0:0:20f2::122
127 Dest Addr: fd00:0:0:20a0::155
128 IPv6 Header: 6000000005A80640FD000000000020F20000000000000122FD000000000020A0
130 TCP . . . : Src Port: 21246,Unassigned Dest Port: 13601,Unassigned
131 SEQ Number: 2282300877 ('880925CD'X) ACK Number: 3259003715 ('C2407343'X)
132 Code Bits: ACK Window: 65535 TCP Option: NO OP
133 TCP Header : 52FE3521880925CDC24073438010FFFFCFBB00000101080A0E15127000237A08
134 Data . . . . . : 54435032000200140000061880000000ECBEB867F0000000004CE640E6C1D9D5 *TCP2........*...***g*....L*@*****
135 C9D5C740E3C8C9E240C9E240E3C8C540E6C1D9D5C9D5C740C6C9C5D3C4404040 ****@****@**@***@*******@*****@@@*
136 4040404040404040404040404040404040404040404040404040404040404040 *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*
139 /* iSeries unformatted packet record consist of the same header record as
140 * the formatted trace but all other records are simply unformatted data
141 * containing higher-level headers and packet data combined.
143 Record Data Record Controller Destination Source Frame Number Number Poll/
144 Number S/R Length Timer Name MAC Address MAC Address Format Command Sent Received Final DSAP SSAP
145 ------ --- ------ --------------- ---------- ------------ ------------ ------ ------- ------ -------- ----- ---- ----
146 1 R 64 12:19:29.97108 000629ECF48E 0006D78E23C2 ETHV2 Type: 0800
147 Data . . . . . : 4500003C27954000 3A06CE3D9797440F 0A5964EAC4F50554 58C9915500000000 *E..<'*@.:.*=**D..YD***.TX**U....*
148 A00216D06A200000 020405B40402080A 1104B6C000000000 010303000B443BF1 **..*J .....*......**.........D;**
152 #include "wtap-int.h"
154 #include "file_wrappers.h"
160 #include <wsutil/str_util.h>
162 #define ISERIES_HDR_MAGIC_STR "COMMUNICATIONS TRACE"
163 #define ISERIES_HDR_MAGIC_LEN 20
164 #define ISERIES_LINE_LENGTH 270
165 #define ISERIES_HDR_LINES_TO_CHECK 100
166 #define ISERIES_PKT_LINES_TO_CHECK 4
167 #define ISERIES_MAX_PACKET_LEN 16384
168 #define ISERIES_MAX_TRACE_LEN 99999999
169 #define ISERIES_PKT_ALLOC_SIZE (pkt_len*2)+1
170 #define ISERIES_FORMAT_ASCII 1
171 #define ISERIES_FORMAT_UNICODE 2
174 gboolean have_date; /* TRUE if we found a capture start date */
175 int year, month, day; /* The start date */
176 int format; /* Trace format type */
179 static gboolean iseries_read (wtap * wth, int *err, gchar ** err_info,
180 gint64 *data_offset);
181 static gboolean iseries_seek_read (wtap * wth, gint64 seek_off,
182 struct wtap_pkthdr *phdr,
183 Buffer * buf, int *err, gchar ** err_info);
184 static gboolean iseries_check_file_type (wtap * wth, int *err, gchar **err_info,
186 static gint64 iseries_seek_next_packet (wtap * wth, int *err, gchar **err_info);
187 static gboolean iseries_parse_packet (wtap * wth, FILE_T fh,
188 struct wtap_pkthdr *phdr,
189 Buffer * buf, int *err, gchar ** err_info);
190 static int iseries_UNICODE_to_ASCII (guint8 * buf, guint bytes);
191 static gboolean iseries_parse_hex_string (const char * ascii, guint8 * buf,
195 iseries_open (wtap * wth, int *err, gchar ** err_info)
198 char magic[ISERIES_LINE_LENGTH];
199 char unicodemagic[] =
200 { '\x43', '\x00', '\x4F', '\x00', '\x4D',
201 '\x00', '\x4D', '\x00', '\x55', '\x00', '\x4E', '\x00', '\x49', '\x00',
202 '\x43', '\x00', '\x41'
206 * Check that file starts with a valid iSeries COMMS TRACE header
207 * by scanning for it in the first line
209 if (!wtap_read_bytes (wth->fh, &magic, sizeof magic, err, err_info))
211 if (*err != WTAP_ERR_SHORT_READ)
212 return WTAP_OPEN_ERROR;
213 return WTAP_OPEN_NOT_MINE;
217 * Check if this is a UNICODE formatted file by scanning for the magic string
220 while ((unsigned int)offset < (ISERIES_LINE_LENGTH - (sizeof unicodemagic)))
222 if (memcmp (magic + offset, unicodemagic, sizeof unicodemagic) == 0) {
223 if (file_seek (wth->fh, 0, SEEK_SET, err) == -1)
225 return WTAP_OPEN_NOT_MINE;
228 * Do some basic sanity checking to ensure we can handle the
229 * contents of this trace
231 if (!iseries_check_file_type (wth, err, err_info, ISERIES_FORMAT_UNICODE))
234 return WTAP_OPEN_NOT_MINE;
236 return WTAP_OPEN_ERROR;
239 wth->file_encap = WTAP_ENCAP_ETHERNET;
240 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_ISERIES;
241 wth->snapshot_length = 0;
242 wth->subtype_read = iseries_read;
243 wth->subtype_seek_read = iseries_seek_read;
244 wth->file_tsprec = WTAP_TSPREC_USEC;
246 if (file_seek (wth->fh, 0, SEEK_SET, err) == -1)
248 return WTAP_OPEN_NOT_MINE;
250 return WTAP_OPEN_MINE;
256 * Check if this is a ASCII formatted file by scanning for the magic string
259 while (offset < (ISERIES_LINE_LENGTH - ISERIES_HDR_MAGIC_LEN))
261 if (memcmp (magic + offset, ISERIES_HDR_MAGIC_STR, ISERIES_HDR_MAGIC_LEN) == 0)
263 if (file_seek (wth->fh, 0, SEEK_SET, err) == -1)
265 return WTAP_OPEN_NOT_MINE;
268 * Do some basic sanity checking to ensure we can handle the
269 * contents of this trace
271 if (!iseries_check_file_type (wth, err, err_info, ISERIES_FORMAT_ASCII))
274 return WTAP_OPEN_NOT_MINE;
276 return WTAP_OPEN_ERROR;
279 wth->file_encap = WTAP_ENCAP_ETHERNET;
280 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_ISERIES;
281 wth->snapshot_length = 0;
282 wth->subtype_read = iseries_read;
283 wth->subtype_seek_read = iseries_seek_read;
284 wth->file_tsprec = WTAP_TSPREC_USEC;
286 if (file_seek (wth->fh, 0, SEEK_SET, err) == -1)
288 return WTAP_OPEN_NOT_MINE;
290 return WTAP_OPEN_MINE;
295 /* Neither ASCII or UNICODE so not supported */
296 return WTAP_OPEN_NOT_MINE;
300 * Do some basic sanity checking to ensure we can handle the
301 * contents of this trace by checking the header page for
302 * requisit requirements and additional information.
305 iseries_check_file_type (wtap * wth, int *err, gchar **err_info, int format)
308 int num_items_scanned;
309 char buf[ISERIES_LINE_LENGTH], protocol[9];
312 /* Save trace format for passing between packets */
313 iseries = (iseries_t *) g_malloc (sizeof (iseries_t));
314 wth->priv = (void *) iseries;
315 iseries->have_date = FALSE;
316 iseries->format = format;
318 for (line = 0; line < ISERIES_HDR_LINES_TO_CHECK; line++)
320 if (file_gets (buf, ISERIES_LINE_LENGTH, wth->fh) == NULL)
323 *err = file_error (wth->fh, err_info);
324 if (*err == WTAP_ERR_SHORT_READ)
330 * Check that we are dealing with an ETHERNET trace
332 if (iseries->format == ISERIES_FORMAT_UNICODE)
334 iseries_UNICODE_to_ASCII ((guint8 *)buf, ISERIES_LINE_LENGTH);
336 ascii_strup_inplace (buf);
337 num_items_scanned = sscanf (buf,
338 "%*[ \n\t]OBJECT PROTOCOL%*[ .:\n\t]%8s",
340 if (num_items_scanned == 1)
342 if (memcmp (protocol, "ETHERNET", 8) != 0)
347 * The header is the only place where the date part of the timestamp is held, so
348 * extract it here and store for all packets to access
350 num_items_scanned = sscanf (buf,
351 "%*[ \n\t]START DATE/TIME%*[ .:\n\t]%2d/%2d/%2d",
352 &iseries->month, &iseries->day,
354 if (num_items_scanned == 3)
356 iseries->have_date = TRUE;
364 * Find the next packet and parse it; called from wtap_read().
367 iseries_read (wtap * wth, int *err, gchar ** err_info, gint64 *data_offset)
372 * Locate the next packet
374 offset = iseries_seek_next_packet (wth, err, err_info);
377 *data_offset = offset;
380 * Parse the packet and extract the various fields
382 return iseries_parse_packet (wth, wth->fh, &wth->phdr, wth->frame_buffer,
387 * Seeks to the beginning of the next packet, and returns the
388 * byte offset. Returns -1 on failure or EOF; on EOF, sets
389 * *err to 0, and, on failure, sets *err to the error and *err_info
390 * to null or an additional error string.
393 iseries_seek_next_packet (wtap * wth, int *err, gchar **err_info)
395 iseries_t *iseries = (iseries_t *)wth->priv;
396 char buf[ISERIES_LINE_LENGTH],type[5];
397 int line, num_items_scanned;
401 for (line = 0; line < ISERIES_MAX_TRACE_LEN; line++)
403 if (file_gets (buf, ISERIES_LINE_LENGTH, wth->fh) == NULL)
406 *err = file_error (wth->fh, err_info);
409 /* Convert UNICODE to ASCII if required and determine */
410 /* the number of bytes to rewind to beginning of record. */
411 if (iseries->format == ISERIES_FORMAT_UNICODE)
413 /* buflen is #bytes to 1st 0x0A */
414 buflen = iseries_UNICODE_to_ASCII ((guint8 *) buf, ISERIES_LINE_LENGTH);
418 /* Else buflen is just length of the ASCII string */
419 buflen = (long) strlen (buf);
421 ascii_strup_inplace (buf);
422 /* If packet header found return the offset */
425 "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type);
426 if (num_items_scanned == 1)
428 /* Rewind to beginning of line */
429 cur_off = file_tell (wth->fh);
432 *err = file_error (wth->fh, err_info);
435 if (file_seek (wth->fh, cur_off - buflen, SEEK_SET, err) == -1)
439 return cur_off - buflen;
443 *err = WTAP_ERR_BAD_FILE;
445 g_strdup_printf ("iseries: next packet header not found within %d lines",
446 ISERIES_MAX_TRACE_LEN);
451 * Read packets in random-access fashion
454 iseries_seek_read (wtap * wth, gint64 seek_off, struct wtap_pkthdr *phdr,
455 Buffer * buf, int *err, gchar ** err_info)
458 /* seek to packet location */
459 if (file_seek (wth->random_fh, seek_off - 1, SEEK_SET, err) == -1)
463 * Parse the packet and extract the various fields
465 return iseries_parse_packet (wth, wth->random_fh, phdr, buf,
470 append_hex_digits(char *ascii_buf, int ascii_offset, int max_offset,
471 char *data, int *err, gchar **err_info)
473 int in_offset, out_offset;
476 gboolean overflow = FALSE;
479 out_offset = ascii_offset;
483 * Process a block of up to 16 hex digits.
484 * The block is terminated early by an end-of-line indication (NUL,
485 * CR, or LF), by a space (which terminates the last block of the
486 * data we're processing), or by a "*", which introduces the ASCII representation
488 * All characters in the block must be upper-case hex digits;
489 * there might or might not be a space *after* a block, but, if so,
490 * that will be skipped over after the block is processed.
492 for (i = 0; i < 16; i++, in_offset++)
495 * If we see an end-of-line indication, or an early-end-of-block
496 * indication (space), we're done. (Only the last block ends
499 c = data[in_offset] & 0xFF;
500 if (c == '\0' || c == ' ' || c == '*' || c == '\r' || c == '\n')
504 if (!g_ascii_isxdigit(c) || g_ascii_islower(c))
507 * Not a hex digit, or a lower-case hex digit.
508 * Treat this as an indication that the line isn't a data
509 * line, so we just ignore it.
511 * XXX - do so only for continuation lines; treat non-hex-digit
512 * characters as errors for other lines?
514 return ascii_offset; /* pretend we appended nothing */
516 if (out_offset >= max_offset)
520 ascii_buf[out_offset] = c;
525 * Skip blanks, if any.
527 for (; (data[in_offset] & 0xFF) == ' '; in_offset++)
532 * If we processed an *odd* number of hex digits, report an error.
536 *err = WTAP_ERR_BAD_FILE;
537 *err_info = g_strdup("iseries: odd number of hex digits in a line");
542 *err = WTAP_ERR_BAD_FILE;
543 *err_info = g_strdup("iseries: more packet data than the packet length indicated");
549 /* Parses a packet. */
551 iseries_parse_packet (wtap * wth, FILE_T fh, struct wtap_pkthdr *phdr,
552 Buffer *buf, int *err, gchar **err_info)
554 iseries_t *iseries = (iseries_t *)wth->priv;
556 gboolean isValid, isCurrentPacket;
557 int num_items_scanned, line, pktline, buflen;
558 int pkt_len, pktnum, hr, min, sec;
559 char direction[2], destmac[13], srcmac[13], type[5], csec[9+1];
560 char data[ISERIES_LINE_LENGTH * 2];
567 * Check for packet headers in first 3 lines this should handle page breaks
568 * situations and the header lines output at each page throw and ensure we
569 * read both the captured and packet lengths.
572 for (line = 1; line < ISERIES_PKT_LINES_TO_CHECK; line++)
574 if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
576 *err = file_error (fh, err_info);
579 /* Convert UNICODE data to ASCII */
580 if (iseries->format == ISERIES_FORMAT_UNICODE)
582 iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
584 ascii_strup_inplace (data);
587 "%*[ \n\t]%6d%*[ *\n\t]%1s%*[ \n\t]%6d%*[ \n\t]%2d:%2d:%2d.%9[0-9]%*[ \n\t]"
588 "%12s%*[ \n\t]%12s%*[ \n\t]ETHV2%*[ \n\t]TYPE:%*[ \n\t]%4s",
589 &pktnum, direction, &pkt_len, &hr, &min, &sec, csec, destmac,
591 if ((num_items_scanned == 10) && (pkt_len >= 0))
593 /* OK! We found the packet header line */
596 * XXX - The Capture length returned by the iSeries trace doesn't
597 * seem to include the Ethernet header, so we add its length here.
605 * If no packet header found we exit at this point and inform the user.
609 *err = WTAP_ERR_BAD_FILE;
610 *err_info = g_strdup ("iseries: packet header isn't valid");
614 phdr->rec_type = REC_TYPE_PACKET;
615 phdr->presence_flags = WTAP_HAS_CAP_LEN;
618 * If we have Wiretap Header then populate it here
620 * Timer resolution on the iSeries is hardware dependent. We determine
621 * the resolution based on how many digits we see.
623 if (iseries->have_date)
625 phdr->presence_flags |= WTAP_HAS_TS;
626 tm.tm_year = 100 + iseries->year;
627 tm.tm_mon = iseries->month - 1;
628 tm.tm_mday = iseries->day;
633 phdr->ts.secs = mktime (&tm);
634 csec[sizeof(csec) - 1] = '\0';
635 switch (strlen(csec))
641 phdr->ts.nsecs = atoi(csec) * 100000000;
644 phdr->ts.nsecs = atoi(csec) * 10000000;
647 phdr->ts.nsecs = atoi(csec) * 1000000;
650 phdr->ts.nsecs = atoi(csec) * 100000;
653 phdr->ts.nsecs = atoi(csec) * 10000;
656 phdr->ts.nsecs = atoi(csec) * 1000;
659 phdr->ts.nsecs = atoi(csec) * 100;
662 phdr->ts.nsecs = atoi(csec) * 10;
665 phdr->ts.nsecs = atoi(csec);
671 phdr->pkt_encap = WTAP_ENCAP_ETHERNET;
672 phdr->pseudo_header.eth.fcs_len = -1;
674 ascii_buf = (char *)g_malloc (ISERIES_PKT_ALLOC_SIZE);
675 g_snprintf(ascii_buf, ISERIES_PKT_ALLOC_SIZE, "%s%s%s", destmac, srcmac, type);
676 ascii_offset = 14*2; /* 14-byte Ethernet header, 2 characters per byte */
679 * Start reading packet contents
681 isCurrentPacket = TRUE;
683 /* loop through packet lines and breakout when the next packet header is read */
685 while (isCurrentPacket)
688 /* Read the next line */
689 if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
691 *err = file_error (fh, err_info);
694 /* Hit the EOF without an error */
700 /* Convert UNICODE data to ASCII and determine line length */
701 if (iseries->format == ISERIES_FORMAT_UNICODE)
703 buflen = iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
707 /* Else bytes to rewind is just length of ASCII string */
708 buflen = (int) strlen (data);
712 * Skip leading white space.
714 for (offset = 0; g_ascii_isspace(data[offset]); offset++)
718 * The higher-level header information starts at an offset of
719 * 22 characters. The header tags are 14 characters long.
721 * XXX - for IPv6, if the next header isn't the last header,
722 * the intermediate headers do *NOT* appear to be shown in
723 * the dump file *at all*, so the packet *cannot* be
728 if (strncmp(data + 22, "IP Header : ", 14) == 0 ||
729 strncmp(data + 22, "IPv6 Header: ", 14) == 0 ||
730 strncmp(data + 22, "ARP Header : ", 14) == 0 ||
731 strncmp(data + 22, "TCP Header : ", 14) == 0 ||
732 strncmp(data + 22, "UDP Header : ", 14) == 0 ||
733 strncmp(data + 22, "ICMP Header: ", 14) == 0 ||
734 strncmp(data + 22, "ICMPv6 Hdr: ", 14) == 0 ||
735 strncmp(data + 22, "Option Hdr: ", 14) == 0)
737 ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
738 ISERIES_PKT_ALLOC_SIZE - 1,
741 if (ascii_offset == -1)
751 * Is this a data line?
753 * The "Data" starts at an offset of 8.
757 if (strncmp(data + 9, "Data . . . . . : ", 18) == 0)
759 ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
760 ISERIES_PKT_ALLOC_SIZE - 1,
763 if (ascii_offset == -1)
773 * Is this a continuation of a previous header or data line?
774 * That's blanks followed by hex digits; first try the
775 * "no column separators" form.
777 * Continuations of header lines begin at an offset of 36;
778 * continuations of data lines begin at an offset of 27.
780 if (offset == 36 || offset == 27)
782 ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
783 ISERIES_PKT_ALLOC_SIZE - 1,
786 if (ascii_offset == -1)
795 * If we see the identifier for the next packet then rewind and set
796 * isCurrentPacket FALSE
798 ascii_strup_inplace (data);
799 /* If packet header found return the offset */
802 "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type);
803 if ((num_items_scanned == 1) && pktline > 1)
805 isCurrentPacket = FALSE;
806 cur_off = file_tell( fh);
810 *err = file_error (fh, err_info);
813 if (file_seek (fh, cur_off - buflen, SEEK_SET, err) == -1)
815 /* XXX: need to set err_info ?? */
820 ascii_buf[ascii_offset] = '\0';
823 * Make the captured length be the amount of bytes we've read (which
824 * is half the number of characters of hex dump we have).
826 * XXX - this can happen for IPv6 packets if the next header isn't the
829 phdr->caplen = ((guint32) strlen (ascii_buf))/2;
831 /* Make sure we have enough room for the packet. */
832 ws_buffer_assure_space (buf, ISERIES_MAX_PACKET_LEN);
833 /* Convert ascii data to binary and return in the frame buffer */
834 iseries_parse_hex_string (ascii_buf, ws_buffer_start_ptr (buf), strlen (ascii_buf));
836 /* free buffer allocs and return */
847 * Simple routine to convert an UNICODE buffer to ASCII
849 * XXX - This may be possible with iconv or similar
852 iseries_UNICODE_to_ASCII (guint8 * buf, guint bytes)
859 for (i = 0; i < bytes; i++)
878 * Simple routine to convert an ASCII hex string to binary data
879 * Requires ASCII hex data and buffer to populate with binary data
882 iseries_parse_hex_string (const char * ascii, guint8 * buf, size_t len)
890 for (i = 0; i < len; i++)
892 hexvalue = g_ascii_xdigit_value(ascii[i]);
895 return FALSE; /* not a valid hex digit */
896 bytevalue = (guint8)(hexvalue << 4);
898 return FALSE; /* only one hex digit of the byte is present */
899 hexvalue = g_ascii_xdigit_value(ascii[i]);
901 return FALSE; /* not a valid hex digit */
902 bytevalue |= (guint8) hexvalue;
903 buf[byte] = bytevalue;
910 * Editor modelines - http://www.wireshark.org/tools/modelines.html
915 * indent-tabs-mode: nil
918 * vi: set shiftwidth=2 tabstop=8 expandtab:
919 * :indentSize=2:tabSize=8:noTabs=true: