X-Git-Url: http://git.samba.org/samba.git/?p=obnox%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=wiretap%2Fiptrace.c;h=f427cff95ba47e827739786e6a4d0c1a4b725100;hp=91cffe0f9c89099e17c2a3286b2a80b6daebe18e;hb=0f4379723401ff6b5df9c652e9f41e878bda47d4;hpb=476367857a8b56f584106293d25e19e8024f24c5 diff --git a/wiretap/iptrace.c b/wiretap/iptrace.c index 91cffe0f9c..f427cff95b 100644 --- a/wiretap/iptrace.c +++ b/wiretap/iptrace.c @@ -1,20 +1,20 @@ /* iptrace.c * - * $Id: iptrace.c,v 1.29 2000/05/19 23:06:51 gram Exp $ + * $Id$ * * Wiretap Library - * Copyright (c) 1998 by Gilbert Ramirez - * + * Copyright (c) 1998 by Gilbert Ramirez + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -25,34 +25,38 @@ #endif #include #include -#include #include #include "wtap-int.h" #include "file_wrappers.h" #include "buffer.h" +#include "atm.h" #include "iptrace.h" -static int iptrace_read_1_0(wtap *wth, int *err); -static int iptrace_seek_read_1_0(wtap *wth, int seek_off, - union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size); -static int iptrace_read_2_0(wtap *wth, int *err); -static int iptrace_seek_read_2_0(wtap *wth, int seek_off, - union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size); +static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info, + long *data_offset); +static gboolean iptrace_seek_read_1_0(wtap *wth, long seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size, + int *err, gchar **err_info); + +static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info, + long *data_offset); +static gboolean iptrace_seek_read_2_0(wtap *wth, long seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size, + int *err, gchar **err_info); + static int iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err); -static int iptrace_read_rec_data(FILE_T fh, guint8 *data_ptr, int packet_size, - int *err); -static void get_atm_pseudo_header(union wtap_pseudo_header *pseudo_header, - guint8 *header); +static gboolean iptrace_read_rec_data(FILE_T fh, guint8 *data_ptr, + int packet_size, int *err); +static void fill_in_pseudo_header(int encap, const guint8 *pd, guint32 len, + union wtap_pseudo_header *pseudo_header, guint8 *header); static int wtap_encap_ift(unsigned int ift); -int iptrace_open(wtap *wth, int *err) +int iptrace_open(wtap *wth, int *err, gchar **err_info _U_) { int bytes_read; char name[12]; - file_seek(wth->fh, 0, SEEK_SET); - wth->data_offset = 0; errno = WTAP_ERR_CANT_READ; bytes_read = file_read(name, 1, 11, wth->fh); if (bytes_read != 11) { @@ -85,7 +89,24 @@ int iptrace_open(wtap *wth, int *err) * iptrace 1.0 * ***********************************************************/ -/* iptrace 1.0, discovered through inspection */ +/* + * iptrace 1.0, discovered through inspection + * + * Packet record contains: + * + * an initial header, with a length field and a time stamp, in + * seconds since the Epoch; + * + * data, with the specified length. + * + * The data contains: + * + * a bunch of information about the packet; + * + * padding, at least for FDDI; + * + * the raw packet data. + */ typedef struct { /* 0-3 */ guint32 pkt_length; /* packet length + 0x16 */ /* 4-7 */ guint32 tv_sec; /* time stamp, seconds since the Epoch */ @@ -96,31 +117,64 @@ typedef struct { /* 29 */ guint8 tx_flag; /* 0=receive, 1=transmit */ } iptrace_1_0_phdr; +#define IPTRACE_1_0_PHDR_SIZE 30 /* initial header plus packet data */ +#define IPTRACE_1_0_PDATA_SIZE 22 /* packet data */ + /* Read the next packet */ -static int iptrace_read_1_0(wtap *wth, int *err) +static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info _U_, + long *data_offset) { - int record_offset; int ret; guint32 packet_size; - guint8 header[30]; + guint8 header[IPTRACE_1_0_PHDR_SIZE]; guint8 *data_ptr; iptrace_1_0_phdr pkt_hdr; + guchar fddi_padding[3]; /* Read the descriptor data */ - record_offset = wth->data_offset; - ret = iptrace_read_rec_header(wth->fh, header, 30, err); + *data_offset = wth->data_offset; + ret = iptrace_read_rec_header(wth->fh, header, IPTRACE_1_0_PHDR_SIZE, + err); if (ret <= 0) { /* Read error or EOF */ - return ret; + return FALSE; } - wth->data_offset += 30; + wth->data_offset += IPTRACE_1_0_PHDR_SIZE; + + /* + * Byte 28 of the frame header appears to be a BSD-style IFT_xxx + * value giving the type of the interface. Check out the + * header file. + */ + pkt_hdr.if_type = header[28]; + wth->phdr.pkt_encap = wtap_encap_ift(pkt_hdr.if_type); /* Read the packet data */ - packet_size = pntohl(&header[0]) - 0x16; + packet_size = pntohl(&header[0]) - IPTRACE_1_0_PDATA_SIZE; + + /* + * AIX appears to put 3 bytes of padding in front of FDDI + * frames; strip that crap off. + */ + if (wth->phdr.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) { + /* + * The packet size is really a record size and includes + * the padding. + */ + packet_size -= 3; + wth->data_offset += 3; + + /* + * Read the padding. + */ + if (!iptrace_read_rec_data(wth->fh, fddi_padding, 3, err)) + return FALSE; /* Read error */ + } + buffer_assure_space( wth->frame_buffer, packet_size ); data_ptr = buffer_start_ptr( wth->frame_buffer ); - if (iptrace_read_rec_data(wth->fh, data_ptr, packet_size, err) < 0) - return -1; /* Read error */ + if (!iptrace_read_rec_data(wth->fh, data_ptr, packet_size, err)) + return FALSE; /* Read error */ wth->data_offset += packet_size; wth->phdr.len = packet_size; @@ -128,24 +182,16 @@ static int iptrace_read_1_0(wtap *wth, int *err) wth->phdr.ts.tv_sec = pntohl(&header[4]); wth->phdr.ts.tv_usec = 0; - /* - * Byte 28 of the frame header appears to be a BSD-style IFT_xxx - * value giving the type of the interface. Check out the - * header file. - */ - pkt_hdr.if_type = header[28]; - wth->phdr.pkt_encap = wtap_encap_ift(pkt_hdr.if_type); - if (wth->phdr.pkt_encap == WTAP_ENCAP_UNKNOWN) { - g_message("iptrace: interface type IFT=0x%02x unknown or unsupported", - pkt_hdr.if_type); *err = WTAP_ERR_UNSUPPORTED_ENCAP; - return -1; + *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported", + pkt_hdr.if_type); + return FALSE; } - if ( wth->phdr.pkt_encap == WTAP_ENCAP_ATM_SNIFFER ) { - get_atm_pseudo_header(&wth->pseudo_header, header); - } + /* Fill in the pseudo-header. */ + fill_in_pseudo_header(wth->phdr.pkt_encap, data_ptr, wth->phdr.caplen, + &wth->pseudo_header, header); /* If the per-file encapsulation isn't known, set it to this packet's encapsulation. @@ -160,38 +206,83 @@ static int iptrace_read_1_0(wtap *wth, int *err) wth->file_encap = WTAP_ENCAP_PER_PACKET; } - return record_offset; + return TRUE; } -static int iptrace_seek_read_1_0(wtap *wth, int seek_off, - union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size) +static gboolean iptrace_seek_read_1_0(wtap *wth, long seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size, + int *err, gchar **err_info _U_) { int ret; - int err; /* XXX - return this */ - guint8 header[30]; + guint8 header[IPTRACE_1_0_PHDR_SIZE]; + int pkt_encap; + guchar fddi_padding[3]; - file_seek(wth->random_fh, seek_off, SEEK_SET); + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; /* Read the descriptor data */ - ret = iptrace_read_rec_header(wth->random_fh, header, 30, &err); + ret = iptrace_read_rec_header(wth->random_fh, header, + IPTRACE_1_0_PHDR_SIZE, err); if (ret <= 0) { /* Read error or EOF */ - return ret; + if (ret == 0) { + /* EOF means "short read" in random-access mode */ + *err = WTAP_ERR_SHORT_READ; + } + return FALSE; } - if ( wtap_encap_ift(header[28]) == WTAP_ENCAP_ATM_SNIFFER ) { - get_atm_pseudo_header(pseudo_header, header); + /* + * Get the interface type. + */ + pkt_encap = wtap_encap_ift(header[28]); + + /* + * AIX appears to put 3 bytes of padding in front of FDDI + * frames; strip that crap off. + */ + if (pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) { + /* + * Read the padding. + */ + if (!iptrace_read_rec_data(wth->random_fh, fddi_padding, 3, err)) + return FALSE; /* Read error */ } - /* Read the packet data */ - return iptrace_read_rec_data(wth->random_fh, pd, packet_size, &err); + /* Get the packet data */ + if (!iptrace_read_rec_data(wth->random_fh, pd, packet_size, err)) + return FALSE; + + /* Fill in the pseudo_header. */ + fill_in_pseudo_header(pkt_encap, pd, packet_size, pseudo_header, + header); + + return TRUE; } /*********************************************************** * iptrace 2.0 * ***********************************************************/ -/* iptrace 2.0, discovered through inspection */ +/* + * iptrace 2.0, discovered through inspection + * + * Packet record contains: + * + * an initial header, with a length field and a time stamp, in + * seconds since the Epoch; + * + * data, with the specified length. + * + * The data contains: + * + * a bunch of information about the packet; + * + * padding, at least for FDDI; + * + * the raw packet data. + */ typedef struct { /* 0-3 */ guint32 pkt_length; /* packet length + 32 */ /* 4-7 */ guint32 tv_sec0; /* time stamp, seconds since the Epoch */ @@ -205,31 +296,64 @@ typedef struct { /* 36-39 */ guint32 tv_nsec; /* nanoseconds since that second */ } iptrace_2_0_phdr; +#define IPTRACE_2_0_PHDR_SIZE 40 /* initial header plus packet data */ +#define IPTRACE_2_0_PDATA_SIZE 32 /* packet data */ + /* Read the next packet */ -static int iptrace_read_2_0(wtap *wth, int *err) +static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info _U_, + long *data_offset) { - int record_offset; int ret; guint32 packet_size; - guint8 header[40]; + guint8 header[IPTRACE_2_0_PHDR_SIZE]; guint8 *data_ptr; iptrace_2_0_phdr pkt_hdr; + guchar fddi_padding[3]; /* Read the descriptor data */ - record_offset = wth->data_offset; - ret = iptrace_read_rec_header(wth->fh, header, 40, err); + *data_offset = wth->data_offset; + ret = iptrace_read_rec_header(wth->fh, header, IPTRACE_2_0_PHDR_SIZE, + err); if (ret <= 0) { /* Read error or EOF */ - return ret; + return FALSE; } - wth->data_offset += 40; + wth->data_offset += IPTRACE_2_0_PHDR_SIZE; + + /* + * Byte 28 of the frame header appears to be a BSD-style IFT_xxx + * value giving the type of the interface. Check out the + * header file. + */ + pkt_hdr.if_type = header[28]; + wth->phdr.pkt_encap = wtap_encap_ift(pkt_hdr.if_type); /* Read the packet data */ - packet_size = pntohl(&header[0]) - 32; + packet_size = pntohl(&header[0]) - IPTRACE_2_0_PDATA_SIZE; + + /* + * AIX appears to put 3 bytes of padding in front of FDDI + * frames; strip that crap off. + */ + if (wth->phdr.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) { + /* + * The packet size is really a record size and includes + * the padding. + */ + packet_size -= 3; + wth->data_offset += 3; + + /* + * Read the padding. + */ + if (!iptrace_read_rec_data(wth->fh, fddi_padding, 3, err)) + return FALSE; /* Read error */ + } + buffer_assure_space( wth->frame_buffer, packet_size ); data_ptr = buffer_start_ptr( wth->frame_buffer ); - if (iptrace_read_rec_data(wth->fh, data_ptr, packet_size, err) < 0) - return -1; /* Read error */ + if (!iptrace_read_rec_data(wth->fh, data_ptr, packet_size, err)) + return FALSE; /* Read error */ wth->data_offset += packet_size; /* AIX saves time in nsec, not usec. It's easier to make iptrace @@ -241,24 +365,16 @@ static int iptrace_read_2_0(wtap *wth, int *err) wth->phdr.ts.tv_sec = pntohl(&header[32]); wth->phdr.ts.tv_usec = pntohl(&header[36]) / 1000; - /* - * Byte 28 of the frame header appears to be a BSD-style IFT_xxx - * value giving the type of the interface. Check out the - * header file. - */ - pkt_hdr.if_type = header[28]; - wth->phdr.pkt_encap = wtap_encap_ift(pkt_hdr.if_type); - if (wth->phdr.pkt_encap == WTAP_ENCAP_UNKNOWN) { - g_message("iptrace: interface type IFT=0x%02x unknown or unsupported", - pkt_hdr.if_type); *err = WTAP_ERR_UNSUPPORTED_ENCAP; - return -1; + *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported", + pkt_hdr.if_type); + return FALSE; } - if ( wth->phdr.pkt_encap == WTAP_ENCAP_ATM_SNIFFER ) { - get_atm_pseudo_header(&wth->pseudo_header, header); - } + /* Fill in the pseudo-header. */ + fill_in_pseudo_header(wth->phdr.pkt_encap, data_ptr, wth->phdr.caplen, + &wth->pseudo_header, header); /* If the per-file encapsulation isn't known, set it to this packet's encapsulation. @@ -273,31 +389,59 @@ static int iptrace_read_2_0(wtap *wth, int *err) wth->file_encap = WTAP_ENCAP_PER_PACKET; } - return record_offset; + return TRUE; } -static int iptrace_seek_read_2_0(wtap *wth, int seek_off, - union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size) +static gboolean iptrace_seek_read_2_0(wtap *wth, long seek_off, + union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size, + int *err, gchar **err_info _U_) { int ret; - int err; /* XXX - return this */ - guint8 header[40]; + guint8 header[IPTRACE_2_0_PHDR_SIZE]; + int pkt_encap; + guchar fddi_padding[3]; - file_seek(wth->random_fh, seek_off, SEEK_SET); + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; /* Read the descriptor data */ - ret = iptrace_read_rec_header(wth->random_fh, header, 40, &err); + ret = iptrace_read_rec_header(wth->random_fh, header, + IPTRACE_2_0_PHDR_SIZE, err); if (ret <= 0) { /* Read error or EOF */ - return ret; + if (ret == 0) { + /* EOF means "short read" in random-access mode */ + *err = WTAP_ERR_SHORT_READ; + } + return FALSE; } - if ( wtap_encap_ift(header[28]) == WTAP_ENCAP_ATM_SNIFFER ) { - get_atm_pseudo_header(pseudo_header, header); + /* + * Get the interface type. + */ + pkt_encap = wtap_encap_ift(header[28]); + + /* + * AIX appears to put 3 bytes of padding in front of FDDI + * frames; strip that crap off. + */ + if (pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) { + /* + * Read the padding. + */ + if (!iptrace_read_rec_data(wth->random_fh, fddi_padding, 3, err)) + return FALSE; /* Read error */ } - /* Read the packet data */ - return iptrace_read_rec_data(wth->random_fh, pd, packet_size, &err); + /* Get the packet data */ + if (!iptrace_read_rec_data(wth->random_fh, pd, packet_size, err)) + return FALSE; + + /* Fill in the pseudo-header. */ + fill_in_pseudo_header(pkt_encap, pd, packet_size, pseudo_header, + header); + + return TRUE; } static int @@ -320,7 +464,7 @@ iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err) return 1; } -static int +static gboolean iptrace_read_rec_data(FILE_T fh, guint8 *data_ptr, int packet_size, int *err) { int bytes_read; @@ -332,21 +476,22 @@ iptrace_read_rec_data(FILE_T fh, guint8 *data_ptr, int packet_size, int *err) *err = file_error(fh); if (*err == 0) *err = WTAP_ERR_SHORT_READ; - return -1; + return FALSE; } - return 0; + return TRUE; } /* - * Fill in the pseudo-header information we can; alas, "iptrace" doesn't - * tell us what type of traffic is in the packet - it was presumably - * run on a machine that was one of the endpoints of the connection, so - * in theory it could presumably have told us, but, for whatever reason, - * it failed to do so - perhaps the low-level mechanism that feeds the - * presumably-AAL5 frames to us doesn't have access to that information - * (e.g., because it's in the ATM driver, and the ATM driver merely knows - * that stuff on VPI/VCI X.Y should be handed up to some particular - * client, it doesn't know what that client is). + * Fill in the pseudo-header information we can. + * + * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic + * is in the packet - it was presumably run on a machine that was one of + * the endpoints of the connection, so in theory it could presumably have + * told us, but, for whatever reason, it failed to do so - perhaps the + * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't + * have access to that information (e.g., because it's in the ATM driver, + * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be + * handed up to some particular client, it doesn't know what that client is). * * We let our caller try to figure out what kind of traffic it is, either * by guessing based on the VPI/VCI, guessing based on the header of the @@ -354,42 +499,56 @@ iptrace_read_rec_data(FILE_T fh, guint8 *data_ptr, int packet_size, int *err) * in some fashion what sort of traffic it is, or being told by the user. */ static void -get_atm_pseudo_header(union wtap_pseudo_header *pseudo_header, guint8 *header) +fill_in_pseudo_header(int encap, const guint8 *pd, guint32 len, + union wtap_pseudo_header *pseudo_header, guint8 *header) { char if_text[9]; char *decimal; int Vpi = 0; int Vci = 0; - /* Rip apart the "x.y" text into Vpi/Vci numbers */ - memcpy(if_text, &header[20], 8); - if_text[8] = '\0'; - decimal = strchr(if_text, '.'); - if (decimal) { - *decimal = '\0'; - Vpi = strtoul(if_text, NULL, 10); - decimal++; - Vci = strtoul(decimal, NULL, 10); - } - pseudo_header->ngsniffer_atm.Vpi = Vpi; - pseudo_header->ngsniffer_atm.Vci = Vci; + switch (encap) { + + case WTAP_ENCAP_ATM_PDUS: + /* Rip apart the "x.y" text into Vpi/Vci numbers */ + memcpy(if_text, &header[20], 8); + if_text[8] = '\0'; + decimal = strchr(if_text, '.'); + if (decimal) { + *decimal = '\0'; + Vpi = strtoul(if_text, NULL, 10); + decimal++; + Vci = strtoul(decimal, NULL, 10); + } - /* - * OK, which value means "DTE->DCE" and which value means - * "DCE->DTE"? - */ - pseudo_header->ngsniffer_atm.channel = header[29]; - - /* We don't have this information */ - pseudo_header->ngsniffer_atm.cells = 0; - pseudo_header->ngsniffer_atm.aal5t_u2u = 0; - pseudo_header->ngsniffer_atm.aal5t_len = 0; - pseudo_header->ngsniffer_atm.aal5t_chksum = 0; - - /* Assume it's AAL5 traffic, but indicate that we don't know what - it is beyond that. */ - pseudo_header->ngsniffer_atm.AppTrafType = ATT_AAL5|ATT_HL_UNKNOWN; - pseudo_header->ngsniffer_atm.AppHLType = AHLT_UNKNOWN; + /* + * OK, which value means "DTE->DCE" and which value means + * "DCE->DTE"? + */ + pseudo_header->atm.channel = header[29]; + + pseudo_header->atm.vpi = Vpi; + pseudo_header->atm.vci = Vci; + + /* + * Attempt to guess from the packet data, the VPI, + * and the VCI information about the type of traffic. + */ + atm_guess_traffic_type(pd, len, pseudo_header); + + /* We don't have this information */ + pseudo_header->atm.flags = 0; + pseudo_header->atm.cells = 0; + pseudo_header->atm.aal5t_u2u = 0; + pseudo_header->atm.aal5t_len = 0; + pseudo_header->atm.aal5t_chksum = 0; + break; + + case WTAP_ENCAP_ETHERNET: + /* We assume there's no FCS in this frame. */ + pseudo_header->eth.fcs_len = 0; + break; + } } /* Given an RFC1573 (SNMP ifType) interface type, @@ -407,9 +566,9 @@ wtap_encap_ift(unsigned int ift) /* 0x4 */ WTAP_ENCAP_RAW_IP, /* IFT_X25DDN */ /* 0x5 */ WTAP_ENCAP_UNKNOWN, /* IFT_X25 */ /* 0x6 */ WTAP_ENCAP_ETHERNET, /* IFT_ETHER */ -/* 0x7 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88023 */ +/* 0x7 */ WTAP_ENCAP_ETHERNET, /* IFT_ISO88023 */ /* 0x8 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88024 */ -/* 0x9 */ WTAP_ENCAP_TR, /* IFT_ISO88025 */ +/* 0x9 */ WTAP_ENCAP_TOKEN_RING, /* IFT_ISO88025 */ /* 0xa */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88026 */ /* 0xb */ WTAP_ENCAP_UNKNOWN, /* IFT_STARLAN */ /* 0xc */ WTAP_ENCAP_RAW_IP, /* IFT_P10, IBM SP switch */ @@ -437,7 +596,7 @@ wtap_encap_ift(unsigned int ift) /* 0x22 */ WTAP_ENCAP_UNKNOWN, /* IFT_PARA */ /* 0x23 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNET */ /* 0x24 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNETPLUS */ -/* 0x25 */ WTAP_ENCAP_ATM_SNIFFER, /* IFT_ATM */ +/* 0x25 */ WTAP_ENCAP_ATM_PDUS, /* IFT_ATM */ }; #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])