static gboolean libpcap_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { struct pcaprec_ss990915_hdr hdr; guint packet_size; guint orig_size; int phdr_len; libpcap_t *libpcap; if (!libpcap_read_header(wth, fh, err, err_info, &hdr)) return FALSE; if (hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* * Probably a corrupt capture file; return an error, * so that our caller doesn't blow up trying to allocate * space for an immensely-large packet. */ *err = WTAP_ERR_BAD_FILE; if (err_info != NULL) { *err_info = g_strdup_printf("pcap: File has %u-byte packet, bigger than maximum of %u", hdr.hdr.incl_len, WTAP_MAX_PACKET_SIZE); } return FALSE; } packet_size = hdr.hdr.incl_len; orig_size = hdr.hdr.orig_len; /* * AIX appears to put 3 bytes of padding in front of FDDI * frames; strip that crap off. */ if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX && (wth->file_encap == WTAP_ENCAP_FDDI || wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) { /* * The packet size is really a record size and includes * the padding. */ packet_size -= 3; orig_size -= 3; /* * Skip the padding. */ if (!file_skip(fh, 3, err)) return FALSE; } phdr_len = pcap_process_pseudo_header(fh, wth->file_type_subtype, wth->file_encap, packet_size, TRUE, phdr, err, err_info); if (phdr_len < 0) return FALSE; /* error */ /* * Don't count any pseudo-header as part of the packet. */ orig_size -= phdr_len; packet_size -= phdr_len; phdr->rec_type = REC_TYPE_PACKET; phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; /* Update the timestamp, if not already done */ if (wth->file_encap != WTAP_ENCAP_ERF) { phdr->ts.secs = hdr.hdr.ts_sec; if (wth->file_tsprec == WTAP_TSPREC_NSEC) phdr->ts.nsecs = hdr.hdr.ts_usec; else phdr->ts.nsecs = hdr.hdr.ts_usec * 1000; } else { /* Set interface ID for ERF format */ phdr->presence_flags |= WTAP_HAS_INTERFACE_ID; phdr->interface_id = phdr->pseudo_header.erf.phdr.flags & 0x03; } phdr->caplen = packet_size; phdr->len = orig_size; /* * Read the packet data. */ if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info)) return FALSE; /* failed */ libpcap = (libpcap_t *)wth->priv; pcap_read_post_process(wth->file_type_subtype, wth->file_encap, phdr, ws_buffer_start_ptr(buf), libpcap->byte_swapped, -1); return TRUE; }
/* Read the header of the next packet. Return -1 on an I/O error, 0 on success, or a positive number if the header looks corrupt. The higher the positive number, the more things are wrong with the header; this is used by the heuristics that try to guess what type of file it is, with the type with the fewest problems being chosen. */ static int libpcap_try_header(wtap *wth, FILE_T fh, int *err, gchar **err_info, struct pcaprec_ss990915_hdr *hdr) { int ret; if (!libpcap_read_header(wth, fh, err, err_info, hdr)) return -1; ret = 0; /* start out presuming everything's OK */ switch (wth->file_type_subtype) { case WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC: case WTAP_FILE_TYPE_SUBTYPE_PCAP_AIX: /* * Nanosecond resolution; treat fractions-of-a-second * values >= 1 000 000 000 as an indication that * the header format might not be what we think it is. */ if (hdr->hdr.ts_usec >= 1000000000) ret++; break; default: /* * Microsecond resolution; treat fractions-of-a-second * values >= 1 000 000 as an indication that the header * format might not be what we think it is. */ if (hdr->hdr.ts_usec >= 1000000) ret++; break; } if (hdr->hdr.incl_len > WTAP_MAX_PACKET_SIZE) { /* * Probably either a corrupt capture file or a file * of a type different from the one we're trying. */ ret++; } if (hdr->hdr.orig_len > 64*1024*1024) { /* * In theory I guess the on-the-wire packet size can be * arbitrarily large, and it can certainly be larger than the * maximum snapshot length which bounds the snapshot size, * but any file claiming 64MB in a single packet is *probably* * corrupt, and treating them as such makes the heuristics * much more reliable. See, for example, * * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9634 * * (64MB is an arbitrary size at this point). */ ret++; } if (hdr->hdr.incl_len > wth->snapshot_length) { /* * This is not a fatal error, and packets that have one * such packet probably have thousands. For discussion, * see * https://www.wireshark.org/lists/wireshark-dev/201307/msg00076.html * and related messages. * * The packet contents will be copied to a Buffer, which * expands as necessary to hold the contents; we don't have * to worry about fixed-length buffers allocated based on * the original snapshot length. * * We just treat this as an indication that we might be * trying the wrong file type here. */ ret++; } if (hdr->hdr.incl_len > hdr->hdr.orig_len) { /* * Another hint that this might be the wrong file type. */ ret++; } return ret; }
/* Read the next packet */ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { struct pcaprec_ss990915_hdr hdr; guint packet_size; guint orig_size; int bytes_read; guint8 fddi_padding[3]; int phdr_len; libpcap_t *libpcap; bytes_read = libpcap_read_header(wth, err, err_info, &hdr); if (bytes_read == -1) { /* * We failed to read the header. */ return FALSE; } packet_size = hdr.hdr.incl_len; orig_size = hdr.hdr.orig_len; /* * AIX appears to put 3 bytes of padding in front of FDDI * frames; strip that crap off. */ if (wth->file_type == WTAP_FILE_PCAP_AIX && (wth->file_encap == WTAP_ENCAP_FDDI || wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) { /* * The packet size is really a record size and includes * the padding. */ packet_size -= 3; orig_size -= 3; /* * Read the padding. */ if (!libpcap_read_rec_data(wth->fh, fddi_padding, 3, err, err_info)) return FALSE; /* Read error */ } *data_offset = file_tell(wth->fh); libpcap = (libpcap_t *)wth->priv; phdr_len = pcap_process_pseudo_header(wth->fh, wth->file_type, wth->file_encap, packet_size, TRUE, &wth->phdr, &wth->phdr.pseudo_header, err, err_info); if (phdr_len < 0) return FALSE; /* error */ /* * Don't count any pseudo-header as part of the packet. */ orig_size -= phdr_len; packet_size -= phdr_len; buffer_assure_space(wth->frame_buffer, packet_size); if (!libpcap_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer), packet_size, err, err_info)) return FALSE; /* Read error */ wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; /* Update the Timestamp, if not already done */ if (wth->file_encap != WTAP_ENCAP_ERF) { wth->phdr.ts.secs = hdr.hdr.ts_sec; if(wth->tsprecision == WTAP_FILE_TSPREC_NSEC) { wth->phdr.ts.nsecs = hdr.hdr.ts_usec; } else { wth->phdr.ts.nsecs = hdr.hdr.ts_usec * 1000; } } else { /* Set interface ID for ERF format */ wth->phdr.presence_flags |= WTAP_HAS_INTERFACE_ID; wth->phdr.interface_id = wth->phdr.pseudo_header.erf.phdr.flags & 0x03; } wth->phdr.caplen = packet_size; wth->phdr.len = orig_size; pcap_read_post_process(wth->file_type, wth->file_encap, &wth->phdr.pseudo_header, buffer_start_ptr(wth->frame_buffer), wth->phdr.caplen, libpcap->byte_swapped, -1); return TRUE; }
/* Try to read the first two records of the capture file. */ static libpcap_try_t libpcap_try(wtap *wth, int *err) { /* * pcaprec_ss990915_hdr is the largest header type. */ struct pcaprec_ss990915_hdr first_rec_hdr, second_rec_hdr; /* * Attempt to read the first record's header. */ if (libpcap_read_header(wth, err, NULL, &first_rec_hdr) == -1) { if (*err == 0 || *err == WTAP_ERR_SHORT_READ) { /* * EOF or short read - assume the file is in this * format. * When our client tries to read the first packet * they will presumably get the same EOF or short * read. */ return THIS_FORMAT; } if (*err == WTAP_ERR_BAD_FILE) { /* * The first record is bogus, so this is probably * a corrupt file. Assume the file is in this * format. When our client tries to read the * first packet they will presumably get the * same bogus record. */ return THIS_FORMAT; } /* * Some other error, e.g. an I/O error; just give up. */ return BAD_READ; } /* * Now skip over the first record's data, under the assumption * that the header is sane. */ if (file_seek(wth->fh, first_rec_hdr.hdr.incl_len, SEEK_CUR, err) == -1) return BAD_READ; /* * Now attempt to read the second record's header. */ if (libpcap_read_header(wth, err, NULL, &second_rec_hdr) == -1) { if (*err == 0 || *err == WTAP_ERR_SHORT_READ) { /* * EOF or short read - assume the file is in this * format. * When our client tries to read the second packet * they will presumably get the same EOF or short * read. */ return THIS_FORMAT; } if (*err == WTAP_ERR_BAD_FILE) { /* * The second record is bogus; maybe it's a * Capture File From Hell, and what looks like * the "header" of the next packet is actually * random junk from the middle of a packet. * Try the next format; if we run out of formats, * it probably *is* a corrupt file. */ return OTHER_FORMAT; } /* * Some other error, e.g. an I/O error; just give up. */ return BAD_READ; } /* * OK, the first two records look OK; assume this is the * right format. */ return THIS_FORMAT; }
static gboolean libpcap_process_header(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr, int *err, gchar **err_info) { struct pcaprec_ss990915_hdr hdr; guint packet_size; guint orig_size; int bytes_read; guint8 fddi_padding[3]; int phdr_len; bytes_read = libpcap_read_header(wth, fh, err, err_info, &hdr); if (bytes_read == -1) { /* * We failed to read the header. */ return FALSE; } packet_size = hdr.hdr.incl_len; orig_size = hdr.hdr.orig_len; /* * AIX appears to put 3 bytes of padding in front of FDDI * frames; strip that crap off. */ if (wth->file_type == WTAP_FILE_PCAP_AIX && (wth->file_encap == WTAP_ENCAP_FDDI || wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) { /* * The packet size is really a record size and includes * the padding. */ packet_size -= 3; orig_size -= 3; /* * Read the padding. */ if (!libpcap_read_rec_data(fh, fddi_padding, 3, err, err_info)) return FALSE; /* Read error */ } phdr_len = pcap_process_pseudo_header(fh, wth->file_type, wth->file_encap, packet_size, TRUE, phdr, err, err_info); if (phdr_len < 0) return FALSE; /* error */ /* * Don't count any pseudo-header as part of the packet. */ orig_size -= phdr_len; packet_size -= phdr_len; phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; /* Update the timestamp, if not already done */ if (wth->file_encap != WTAP_ENCAP_ERF) { phdr->ts.secs = hdr.hdr.ts_sec; if (wth->tsprecision == WTAP_FILE_TSPREC_NSEC) phdr->ts.nsecs = hdr.hdr.ts_usec; else phdr->ts.nsecs = hdr.hdr.ts_usec * 1000; } else { /* Set interface ID for ERF format */ phdr->presence_flags |= WTAP_HAS_INTERFACE_ID; phdr->interface_id = phdr->pseudo_header.erf.phdr.flags & 0x03; } phdr->caplen = packet_size; phdr->len = orig_size; return TRUE; }
/* Read the next packet */ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { struct pcaprec_ss990915_hdr hdr; guint packet_size; guint orig_size; int bytes_read; guchar fddi_padding[3]; int phdr_len; libpcap_t *libpcap; bytes_read = libpcap_read_header(wth, err, err_info, &hdr); if (bytes_read == -1) { /* * We failed to read the header. */ return FALSE; } wth->data_offset += bytes_read; packet_size = hdr.hdr.incl_len; orig_size = hdr.hdr.orig_len; /* * AIX appears to put 3 bytes of padding in front of FDDI * frames; strip that crap off. */ if (wth->file_type == WTAP_FILE_PCAP_AIX && (wth->file_encap == WTAP_ENCAP_FDDI || wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) { /* * The packet size is really a record size and includes * the padding. */ packet_size -= 3; orig_size -= 3; wth->data_offset += 3; /* * Read the padding. */ if (!libpcap_read_rec_data(wth->fh, fddi_padding, 3, err)) return FALSE; /* Read error */ } *data_offset = wth->data_offset; libpcap = (libpcap_t *)wth->priv; phdr_len = pcap_process_pseudo_header(wth->fh, wth->file_type, wth->file_encap, libpcap->byte_swapped, packet_size, TRUE, &wth->phdr, &wth->pseudo_header, err, err_info); if (phdr_len < 0) return FALSE; /* error */ /* * Don't count any pseudo-header as part of the packet. */ orig_size -= phdr_len; packet_size -= phdr_len; wth->data_offset += phdr_len; buffer_assure_space(wth->frame_buffer, packet_size); if (!libpcap_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer), packet_size, err)) return FALSE; /* Read error */ wth->data_offset += packet_size; /* Update the Timestamp, if not already done */ if (wth->file_encap != WTAP_ENCAP_ERF) { wth->phdr.ts.secs = hdr.hdr.ts_sec; if(wth->tsprecision == WTAP_FILE_TSPREC_NSEC) { wth->phdr.ts.nsecs = hdr.hdr.ts_usec; } else { wth->phdr.ts.nsecs = hdr.hdr.ts_usec * 1000; } } wth->phdr.caplen = packet_size; wth->phdr.len = orig_size; if (wth->file_encap == WTAP_ENCAP_ATM_PDUS) { if (wth->file_type == WTAP_FILE_PCAP_NOKIA) { /* * Nokia IPSO ATM. * * Guess the traffic type based on the packet * contents. */ atm_guess_traffic_type(buffer_start_ptr(wth->frame_buffer), wth->phdr.caplen, &wth->pseudo_header); } else { /* * SunATM. * * If this is ATM LANE traffic, try to guess what * type of LANE traffic it is based on the packet * contents. */ if (wth->pseudo_header.atm.type == TRAF_LANE) { atm_guess_lane_type(buffer_start_ptr(wth->frame_buffer), wth->phdr.caplen, &wth->pseudo_header); } } } return TRUE; }