/* Returns TRUE if packet data copied, FALSE if error occurred or EOF (no more records). */ static gboolean collate(pppdump_t* state, FILE_T fh, int *err, gchar **err_info, guint8 *pd, int *num_bytes, direction_enum *direction, pkt_id *pid, gint64 num_bytes_to_skip) { int id; pkt_t *pkt = NULL; int byte0, byte1; int n, num_written = 0; gint64 start_offset; guint32 time_long; guint8 time_short; /* * Process any data left over in the current record when doing * sequential processing. */ if (state->num_bytes > 0) { g_assert(num_bytes_to_skip == 0); pkt = state->pkt; num_written = process_data(state, fh, pkt, state->num_bytes, pd, err, err_info, pid); if (num_written < 0) { return FALSE; } else if (num_written > 0) { *num_bytes = num_written; *direction = pkt->dir; return TRUE; } /* if 0 bytes written, keep processing */ } else { /* * We didn't have any data left over, so the packet will * start at the beginning of a record. */ if (pid) pid->num_bytes_to_skip = 0; } /* * That didn't get all the data for this packet, so process * subsequent records. */ start_offset = state->offset; while ((id = file_getc(fh)) != EOF) { state->offset++; switch (id) { case PPPD_SENT_DATA: case PPPD_RECV_DATA: pkt = id == PPPD_SENT_DATA ? &state->spkt : &state->rpkt; /* * Save the offset of the beginning of * the current record. */ pkt->cd_offset = state->offset - 1; /* * Get the length of the record. */ byte0 = file_getc(fh); if (byte0 == EOF) goto done; state->offset++; byte1 = file_getc(fh); if (byte1 == EOF) goto done; state->offset++; n = (byte0 << 8) | byte1; if (pkt->id_offset == 0) { /* * We don't have the initial data * offset for this packet, which * means this is the first * data record for that packet. * Save the offset of the * beginning of that record and * the offset of the first data * byte in the packet, which is * the first data byte in the * record. */ pkt->id_offset = pkt->cd_offset; pkt->sd_offset = state->offset; } if (n == 0) continue; g_assert(num_bytes_to_skip < n); while (num_bytes_to_skip) { if (file_getc(fh) == EOF) goto done; state->offset++; num_bytes_to_skip--; n--; } num_written = process_data(state, fh, pkt, n, pd, err, err_info, pid); if (num_written < 0) { return FALSE; } else if (num_written > 0) { *num_bytes = num_written; *direction = pkt->dir; return TRUE; } /* if 0 bytes written, keep looping */ break; case PPPD_SEND_DELIM: case PPPD_RECV_DELIM: /* What can we do? */ break; case PPPD_RESET_TIME: wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err, err_info); state->offset += sizeof(guint32); state->timestamp = pntohl(&time_long); state->tenths = 0; break; case PPPD_TIME_STEP_LONG: wtap_file_read_unknown_bytes(&time_long, sizeof(guint32), fh, err, err_info); state->offset += sizeof(guint32); state->tenths += pntohl(&time_long); if (state->tenths >= 10) { state->timestamp += state->tenths / 10; state->tenths = state->tenths % 10; } break; case PPPD_TIME_STEP_SHORT: wtap_file_read_unknown_bytes(&time_short, sizeof(guint8), fh, err, err_info); state->offset += sizeof(guint8); state->tenths += time_short; if (state->tenths >= 10) { state->timestamp += state->tenths / 10; state->tenths = state->tenths % 10; } break; default: /* XXX - bad file */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("pppdump: bad ID byte 0x%02x", id); return FALSE; } } done: *err = file_error(fh, err_info); if (*err == 0) { if (state->offset != start_offset) { /* * We read at least one byte, so we were working * on a record; an EOF means that record was * cut short. */ *err = WTAP_ERR_SHORT_READ; } } return FALSE; }
int airopeek9_open(wtap *wth, int *err, gchar **err_info) { airopeek_section_header_t ap_hdr; int ret; guint32 fileVersion; guint32 mediaType; guint32 mediaSubType = 0; int file_encap; static const int airopeek9_encap[] = { WTAP_ENCAP_ETHERNET, WTAP_ENCAP_IEEE_802_11_WITH_RADIO, WTAP_ENCAP_IEEE_802_11_WITH_RADIO, WTAP_ENCAP_IEEE_802_11_WITH_RADIO }; #define NUM_AIROPEEK9_ENCAPS (sizeof airopeek9_encap / sizeof airopeek9_encap[0]) airopeek9_t *airopeek9; wtap_file_read_unknown_bytes(&ap_hdr, sizeof(ap_hdr), wth->fh, err); if (memcmp (ap_hdr.section_id, "\177ver", sizeof(ap_hdr.section_id)) != 0) return 0; /* doesn't begin with a "\177ver" section */ /* * XXX - we should get the length of the "\177ver" section, check * that it's followed by a little-endian 0x00000200, and then, * when reading the XML, make sure we don't go past the end of * that section, and skip to the end of that section when * we have the file version (and possibly check to make sure all * tags are properly opened and closed). */ ret = wtap_file_read_pattern (wth, "<FileVersion>", err); if (ret != 1) { /* 0 means EOF, which means "not a valid AiroPeek V9 file"; -1 means error, and "err" has been set. */ return ret; } ret = wtap_file_read_number (wth, &fileVersion, err); if (ret != 1) { /* 0 means EOF, which means "not a valid AiroPeek V9 file"; -1 means error, and "err" has been set. */ return ret; } /* If we got this far, we assume it's an AiroPeek V9 file. */ if (fileVersion != 9) { /* We only support version 9. */ *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup_printf("airopeekv9: version %u unsupported", fileVersion); return -1; } /* * XXX - once we've skipped the "\177ver" section, we should * check for a "sess" section and fail if we don't see it. * Then we should get the length of the "sess" section, check * that it's followed by a little-endian 0x00000200, and then, * when reading the XML, make sure we don't go past the end of * that section, and skip to the end of the section when * we have the file version (and possibly check to make sure all * tags are properly opened and closed). */ ret = wtap_file_read_pattern (wth, "<MediaType>", err); if (ret == -1) return -1; if (ret == 0) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup("airopeekv9: <MediaType> tag not found"); return -1; } /* XXX - this appears to be 0 in both the EtherPeek and AiroPeek files we've seen; should we require it to be 0? */ ret = wtap_file_read_number (wth, &mediaType, err); if (ret == -1) return -1; if (ret == 0) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup("airopeekv9: <MediaType> value not found"); return -1; } ret = wtap_file_read_pattern (wth, "<MediaSubType>", err); if (ret == -1) return -1; if (ret == 0) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup("airopeekv9: <MediaSubType> tag not found"); return -1; } ret = wtap_file_read_number (wth, &mediaSubType, err); if (ret == -1) return -1; if (ret == 0) { *err = WTAP_ERR_UNSUPPORTED; *err_info = g_strdup("airopeekv9: <MediaSubType> value not found"); return -1; } if (mediaSubType >= NUM_AIROPEEK9_ENCAPS || airopeek9_encap[mediaSubType] == WTAP_ENCAP_UNKNOWN) { *err = WTAP_ERR_UNSUPPORTED_ENCAP; *err_info = g_strdup_printf("airopeekv9: network type %u unknown or unsupported", mediaSubType); return -1; } ret = wtap_file_read_pattern (wth, "pkts", err); if (ret == -1) return -1; if (ret == 0) { *err = WTAP_ERR_SHORT_READ; return -1; } /* skip 8 zero bytes */ if (file_seek (wth->fh, 8L, SEEK_CUR, err) == -1) return 0; /* * This is an EtherPeek or AiroPeek V9 file. */ wth->data_offset = file_tell (wth->fh); file_encap = airopeek9_encap[mediaSubType]; wth->file_type = WTAP_FILE_AIROPEEK_V9; wth->file_encap = file_encap; wth->subtype_read = airopeekv9_read; wth->subtype_seek_read = airopeekv9_seek_read; wth->tsprecision = WTAP_FILE_TSPREC_NSEC; airopeek9 = (airopeek9_t *)g_malloc(sizeof(airopeek9_t)); wth->priv = (void *)airopeek9; switch (mediaSubType) { case AIROPEEK_V9_NST_ETHERNET: case AIROPEEK_V9_NST_802_11: case AIROPEEK_V9_NST_802_11_2: airopeek9->has_fcs = FALSE; break; case AIROPEEK_V9_NST_802_11_WITH_FCS: airopeek9->has_fcs = TRUE; break; } wth->snapshot_length = 0; /* not available in header */ return 1; }
int pppdump_open(wtap *wth, int *err, gchar **err_info) { guint8 buffer[6]; /* Looking for: 0x07 t3 t2 t1 t0 ID */ pppdump_t *state; /* There is no file header, only packet records. Fortunately for us, * timestamp records are separated from packet records, so we should * find an "initial time stamp" (i.e., a "reset time" record, or * record type 0x07) at the beginning of the file. We'll check for * that, plus a valid record following the 0x07 and the four bytes * representing the timestamp. */ wtap_file_read_unknown_bytes(buffer, sizeof(buffer), wth->fh, err, err_info); if (buffer[0] == PPPD_RESET_TIME && (buffer[5] == PPPD_SENT_DATA || buffer[5] == PPPD_RECV_DATA || buffer[5] == PPPD_TIME_STEP_LONG || buffer[5] == PPPD_TIME_STEP_SHORT || buffer[5] == PPPD_RESET_TIME)) { goto my_file_type; } else { return 0; } my_file_type: if (file_seek(wth->fh, 5, SEEK_SET, err) == -1) return -1; state = (pppdump_t *)g_malloc(sizeof(pppdump_t)); wth->priv = (void *)state; state->timestamp = pntohl(&buffer[1]); state->tenths = 0; init_state(state); state->offset = 5; wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR; wth->file_type = WTAP_FILE_PPPDUMP; wth->snapshot_length = PPPD_BUF_SIZE; /* just guessing */ wth->subtype_read = pppdump_read; wth->subtype_seek_read = pppdump_seek_read; wth->subtype_close = pppdump_close; wth->tsprecision = WTAP_FILE_TSPREC_DSEC; state->seek_state = g_new(pppdump_t,1); /* If we have a random stream open, we're going to be reading the file randomly; set up a GPtrArray of pointers to information about how to retrieve the data for each packet. */ if (wth->random_fh != NULL) state->pids = g_ptr_array_new(); else state->pids = NULL; state->pkt_cnt = 0; return 1; }
int etherpeek_open(wtap *wth, int *err, gchar **err_info) { etherpeek_header_t ep_hdr; struct timeval reference_time; int file_encap; etherpeek_t *etherpeek; /* EtherPeek files do not start with a magic value large enough * to be unique; hence we use the following algorithm to determine * the type of an unknown file: * - populate the master header and reject file if there is no match * - populate the secondary header and check that the reserved space * is zero, and check some other fields; this isn't perfect, * and we may have to add more checks at some point. */ g_assert(sizeof(ep_hdr.master) == ETHERPEEK_MASTER_HDR_SIZE); wtap_file_read_unknown_bytes( &ep_hdr.master, sizeof(ep_hdr.master), wth->fh, err, err_info); /* * It appears that EtherHelp (a free application from WildPackets * that did blind capture, saving to a file, so that you could * give the resulting file to somebody with EtherPeek) saved * captures in EtherPeek format except that it ORed the 0x80 * bit on in the version number. * * We therefore strip off the 0x80 bit in the version number. * Perhaps there's some reason to care whether the capture * came from EtherHelp; if we discover one, we should check * that bit. */ ep_hdr.master.version &= ~0x80; /* switch on the file version */ switch (ep_hdr.master.version) { case 5: case 6: case 7: /* get the secondary header */ g_assert(sizeof(ep_hdr.secondary.v567) == ETHERPEEK_V567_HDR_SIZE); wtap_file_read_unknown_bytes( &ep_hdr.secondary.v567, sizeof(ep_hdr.secondary.v567), wth->fh, err, err_info); if ((0 != ep_hdr.secondary.v567.reserved[0]) || (0 != ep_hdr.secondary.v567.reserved[1]) || (0 != ep_hdr.secondary.v567.reserved[2])) { /* still unknown */ return 0; } /* * Check the mediaType and physMedium fields. * We assume it's not an EtherPeek/TokenPeek/AiroPeek * file if these aren't values we know, rather than * reporting them as invalid *Peek files, as, given * the lack of a magic number, we need all the checks * we can get. */ ep_hdr.secondary.v567.mediaType = g_ntohl(ep_hdr.secondary.v567.mediaType); ep_hdr.secondary.v567.physMedium = g_ntohl(ep_hdr.secondary.v567.physMedium); switch (ep_hdr.secondary.v567.physMedium) { case 0: /* * "Native" format, presumably meaning * Ethernet or Token Ring. */ switch (ep_hdr.secondary.v567.mediaType) { case 0: file_encap = WTAP_ENCAP_ETHERNET; break; case 1: file_encap = WTAP_ENCAP_TOKEN_RING; break; default: /* * Assume this isn't a *Peek file. */ return 0; } break; case 1: switch (ep_hdr.secondary.v567.mediaType) { case 0: /* * 802.11, with a private header giving * some radio information. Presumably * this is from AiroPeek. */ file_encap = WTAP_ENCAP_IEEE_802_11_AIROPEEK; break; default: /* * Assume this isn't a *Peek file. */ return 0; } break; default: /* * Assume this isn't a *Peek file. */ return 0; } /* * Assume this is a V5, V6 or V7 *Peek file, and byte * swap the rest of the fields in the secondary header. * * XXX - we could check the file length if the file were * uncompressed, but it might be compressed. */ ep_hdr.secondary.v567.filelength = g_ntohl(ep_hdr.secondary.v567.filelength); ep_hdr.secondary.v567.numPackets = g_ntohl(ep_hdr.secondary.v567.numPackets); ep_hdr.secondary.v567.timeDate = g_ntohl(ep_hdr.secondary.v567.timeDate); ep_hdr.secondary.v567.timeStart = g_ntohl(ep_hdr.secondary.v567.timeStart); ep_hdr.secondary.v567.timeStop = g_ntohl(ep_hdr.secondary.v567.timeStop); ep_hdr.secondary.v567.appVers = g_ntohl(ep_hdr.secondary.v567.appVers); ep_hdr.secondary.v567.linkSpeed = g_ntohl(ep_hdr.secondary.v567.linkSpeed); /* Get the reference time as a "struct timeval" */ reference_time.tv_sec = ep_hdr.secondary.v567.timeDate - mac2unix; reference_time.tv_usec = 0; break; default: /* * Assume this isn't a *Peek file. */ return 0; } /* * This is an EtherPeek (or TokenPeek or AiroPeek?) file. * * At this point we have recognised the file type and have populated * the whole ep_hdr structure in host byte order. */ etherpeek = (etherpeek_t *)g_malloc(sizeof(etherpeek_t)); wth->priv = (void *)etherpeek; etherpeek->reference_time = reference_time; switch (ep_hdr.master.version) { case 5: case 6: wth->file_type = WTAP_FILE_ETHERPEEK_V56; /* * XXX - can we get the file encapsulation from the * header in the same way we do for V7 files? */ wth->file_encap = WTAP_ENCAP_PER_PACKET; wth->subtype_read = etherpeek_read_v56; wth->subtype_seek_read = etherpeek_seek_read_v56; break; case 7: wth->file_type = WTAP_FILE_ETHERPEEK_V7; wth->file_encap = file_encap; wth->subtype_read = etherpeek_read_v7; wth->subtype_seek_read = etherpeek_seek_read_v7; break; default: /* this is impossible */ g_assert_not_reached(); } wth->snapshot_length = 0; /* not available in header */ wth->tsprecision = WTAP_FILE_TSPREC_USEC; return 1; }