diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-01-02 02:18:04 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-01-02 02:18:04 +0000 |
commit | ce4d667efe586f78ddab0708412cffe10bd9af01 (patch) | |
tree | 6d0a228e190b9d594f3e9d41174d12047103a7ad /wiretap/ngsniffer.c | |
parent | abda7cd1af7500fa6f2ad0ddbe2be9addafccc9e (diff) | |
download | wireshark-ce4d667efe586f78ddab0708412cffe10bd9af01.tar.gz |
Process the packet header and data in common code, shared by the read
and seek-read routines.
svn path=/trunk/; revision=54548
Diffstat (limited to 'wiretap/ngsniffer.c')
-rw-r--r-- | wiretap/ngsniffer.c | 543 |
1 files changed, 246 insertions, 297 deletions
diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c index c41da046f5..64ba7e3232 100644 --- a/wiretap/ngsniffer.c +++ b/wiretap/ngsniffer.c @@ -516,22 +516,15 @@ static gboolean ngsniffer_read(wtap *wth, int *err, gchar **err_info, static gboolean ngsniffer_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, Buffer *buf, int packet_size, int *err, gchar **err_info); -static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random, - guint16 *typep, guint16 *lengthp, int *err, gchar **err_info); -static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random, - struct frame2_rec *frame2, int *err, gchar **err_info); +static int ngsniffer_process_record(wtap *wth, gboolean is_random, + guint *padding, struct wtap_pkthdr *phdr, Buffer *buf, int *err, + gchar **err_info); static void set_pseudo_header_frame2(wtap *wth, union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2); -static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random, - struct frame4_rec *frame4, int *err, gchar **err_info); static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header, struct frame4_rec *frame4); -static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random, - struct frame6_rec *frame6, int *err, gchar **err_info); static void set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header, struct frame6_rec *frame6); -static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random, - Buffer *buf, unsigned int length, int *err, gchar **err_info); static int infer_pkt_encap(const guint8 *pd, int len); static int fix_pseudo_header(int encap, Buffer *buf, int len, union wtap_pseudo_header *pseudo_header); @@ -1068,13 +1061,7 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { ngsniffer_t *ngsniffer; int ret; - guint16 type, length; - struct frame2_rec frame2; - struct frame4_rec frame4; - struct frame6_rec frame6; - guint16 time_low, time_med, true_size, size; - guint8 time_high, time_day; - guint64 t, tsecs, tpsecs; + guint padding; ngsniffer = (ngsniffer_t *)wth->priv; for (;;) { @@ -1085,107 +1072,33 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) *data_offset = ngsniffer->seq.uncomp_offset; /* - * Read the record header. + * Process the record. */ - ret = ngsniffer_read_rec_header(wth, FALSE, &type, &length, - err, err_info); - if (ret <= 0) { - /* Read error or EOF */ + ret = ngsniffer_process_record(wth, FALSE, &padding, + &wth->phdr, wth->frame_buffer, err, err_info); + if (ret < 0) { + /* Read error or short read */ return FALSE; } - switch (type) { + /* + * ret is the record type. + */ + switch (ret) { case REC_FRAME2: - if (ngsniffer->network == NETWORK_ATM) { - /* - * We shouldn't get a frame2 record in - * an ATM capture. - */ - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file"); - return FALSE; - } - - /* Read the f_frame2_struct */ - if (!ngsniffer_read_frame2(wth, FALSE, &frame2, err, - err_info)) { - /* Read error */ - return FALSE; - } - time_low = pletoh16(&frame2.time_low); - time_med = pletoh16(&frame2.time_med); - time_high = frame2.time_high; - time_day = frame2.time_day; - size = pletoh16(&frame2.size); - true_size = pletoh16(&frame2.true_size); - - length -= sizeof frame2; /* we already read that much */ - - set_pseudo_header_frame2(wth, &wth->phdr.pseudo_header, - &frame2); - goto found; - case REC_FRAME4: - if (ngsniffer->network != NETWORK_ATM) { - /* - * We shouldn't get a frame2 record in - * a non-ATM capture. - */ - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file"); - return FALSE; - } - - /* Read the f_frame4_struct */ - if (!ngsniffer_read_frame4(wth, FALSE, &frame4, err, - err_info)) { - /* Read error */ - return FALSE; - } - time_low = pletoh16(&frame4.time_low); - time_med = pletoh16(&frame4.time_med); - time_high = frame4.time_high; - time_day = frame4.time_day; - size = pletoh16(&frame4.size); - true_size = pletoh16(&frame4.true_size); - + case REC_FRAME6: /* - * XXX - it looks as if some version 4 captures have - * a bogus record length, based on the assumption - * that the record is a frame2 record. + * Packet record. + * Skip any extra data in the record. */ - if (ngsniffer->maj_vers >= 5) - length -= sizeof frame4; /* we already read that much */ - else { - if (ngsniffer->min_vers >= 95) - length -= sizeof frame2; - else - length -= sizeof frame4; + if (padding != 0) { + if (!ng_file_skip_seq(wth, padding, err, + err_info)) + return FALSE; } - - set_pseudo_header_frame4(&wth->phdr.pseudo_header, &frame4); - goto found; - - case REC_FRAME6: - /* Read the f_frame6_struct */ - if (!ngsniffer_read_frame6(wth, FALSE, &frame6, err, - err_info)) { - /* Read error */ - return FALSE; - } - time_low = pletoh16(&frame6.time_low); - time_med = pletoh16(&frame6.time_med); - time_high = frame6.time_high; - time_day = frame6.time_day; - size = pletoh16(&frame6.size); - true_size = pletoh16(&frame6.true_size); - - length -= sizeof frame6; /* we already read that much */ - - set_pseudo_header_frame6(wth, &wth->phdr.pseudo_header, - &frame6); - goto found; + return TRUE; case REC_EOF: /* @@ -1195,212 +1108,300 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) return FALSE; default: - break; /* unknown type, skip it */ + /* + * Well, we don't know what it is, or we know what + * it is but can't handle it. Skip past the data + * portion, the length of which is in padding, + * and keep looping. + */ + if (padding != 0) { + if (!ng_file_skip_seq(wth, padding, err, + err_info)) + return FALSE; + } + break; } - - /* - * Well, we don't know what it is, or we know what - * it is but can't handle it. Skip past the data - * portion, and keep looping. - */ - if (!ng_file_skip_seq(wth, length, err, err_info)) - return FALSE; - } - -found: - /* - * OK, is the frame data size greater than than what's left of the - * record? - */ - if (size > length) { - /* - * Yes - treat this as an error. - */ - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("ngsniffer: Record length is less than packet size"); - return FALSE; } +} - wth->phdr.presence_flags = true_size ? WTAP_HAS_TS|WTAP_HAS_CAP_LEN : WTAP_HAS_TS; - wth->phdr.len = true_size ? true_size : size; - wth->phdr.caplen = size; - - /* - * Read the packet data. - */ - if (!ngsniffer_read_rec_data(wth, FALSE, wth->frame_buffer, length, - err, err_info)) - return FALSE; /* Read error */ - - wth->phdr.pkt_encap = fix_pseudo_header(wth->file_encap, wth->frame_buffer, length, - &wth->phdr.pseudo_header); +static gboolean +ngsniffer_seek_read(wtap *wth, gint64 seek_off, + struct wtap_pkthdr *phdr, Buffer *buf, int packet_size _U_, + int *err, gchar **err_info) +{ + int ret; - /* - * 40-bit time stamp, in units of timeunit picoseconds. - */ - t = (((guint64)time_high)<<32) | (((guint64)time_med) << 16) | time_low; + if (!ng_file_seek_rand(wth, seek_off, err, err_info)) + return FALSE; - /* - * timeunit is always < 2^(64-40), so t * timeunit fits in 64 - * bits. That gives a 64-bit time stamp, in units of - * picoseconds. - */ - t *= ngsniffer->timeunit; + ret = ngsniffer_process_record(wth, TRUE, NULL, phdr, buf, err, err_info); + if (ret < 0) { + /* Read error or short read */ + return FALSE; + } /* - * Convert to seconds and picoseconds. + * ret is the record type. */ - tsecs = t/G_GUINT64_CONSTANT(1000000000000); - tpsecs = t - tsecs*G_GUINT64_CONSTANT(1000000000000); + switch (ret) { - /* - * Add in the time_day value (86400 seconds/day). - */ - tsecs += time_day*86400; + case REC_FRAME2: + case REC_FRAME4: + case REC_FRAME6: + /* Packet record */ + break; - /* - * Add in the capture start time. - */ - tsecs += ngsniffer->start; + default: + /* + * "Can't happen". + */ + g_assert_not_reached(); + return FALSE; + } - wth->phdr.ts.secs = (time_t)tsecs; - wth->phdr.ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */ return TRUE; } -static gboolean -ngsniffer_seek_read(wtap *wth, gint64 seek_off, - struct wtap_pkthdr *phdr, Buffer *buf, int packet_size, - int *err, gchar **err_info) +/* + * Returns -1 on error, REC_EOF on end-of-file, record type on success. + * If padding is non-null, sets *padding to the amount of padding at + * the end of the record. + */ +static int +ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding, + struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { - union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header; - int ret; + ngsniffer_t *ngsniffer; + gint64 bytes_read; + char record_type[2]; + char record_length[4]; /* only 1st 2 bytes are length */ guint16 type, length; struct frame2_rec frame2; struct frame4_rec frame4; struct frame6_rec frame6; + guint16 time_low, time_med, true_size, size; + guint8 time_high, time_day; + guint64 t, tsecs, tpsecs; - if (!ng_file_seek_rand(wth, seek_off, err, err_info)) - return FALSE; - - ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, err, + /* + * Read the record header. + */ + bytes_read = ng_file_read(record_type, 2, wth, is_random, err, err_info); - if (ret <= 0) { - /* Read error or EOF */ - if (ret == 0) { - /* EOF means "short read" in random-access mode */ + if (bytes_read != 2) { + if (*err != 0) + return -1; + if (bytes_read != 0) { *err = WTAP_ERR_SHORT_READ; + return -1; } - return FALSE; + return REC_EOF; + } + bytes_read = ng_file_read(record_length, 4, wth, is_random, err, + err_info); + if (bytes_read != 4) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return -1; } + type = pletoh16(record_type); + length = pletoh16(record_length); + + ngsniffer = (ngsniffer_t *)wth->priv; switch (type) { case REC_FRAME2: + if (ngsniffer->network == NETWORK_ATM) { + /* + * We shouldn't get a frame2 record in + * an ATM capture. + */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file"); + return -1; + } + /* Read the f_frame2_struct */ - if (!ngsniffer_read_frame2(wth, TRUE, &frame2, err, err_info)) { - /* Read error */ - return FALSE; + bytes_read = ng_file_read(&frame2, (unsigned int)sizeof frame2, + wth, is_random, err, err_info); + if (bytes_read != sizeof frame2) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return -1; } + time_low = pletoh16(&frame2.time_low); + time_med = pletoh16(&frame2.time_med); + time_high = frame2.time_high; + time_day = frame2.time_day; + size = pletoh16(&frame2.size); + true_size = pletoh16(&frame2.true_size); length -= sizeof frame2; /* we already read that much */ - set_pseudo_header_frame2(wth, pseudo_header, &frame2); + set_pseudo_header_frame2(wth, &phdr->pseudo_header, &frame2); break; case REC_FRAME4: + if (ngsniffer->network != NETWORK_ATM) { + /* + * We shouldn't get a frame2 record in + * a non-ATM capture. + */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file"); + return -1; + } + /* Read the f_frame4_struct */ - if (!ngsniffer_read_frame4(wth, TRUE, &frame4, err, err_info)) { - /* Read error */ - return FALSE; + bytes_read = ng_file_read(&frame4, (unsigned int)sizeof frame4, + wth, is_random, err, err_info); + if (bytes_read != sizeof frame4) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return -1; } + time_low = pletoh16(&frame4.time_low); + time_med = pletoh16(&frame4.time_med); + time_high = frame4.time_high; + time_day = frame4.time_day; + size = pletoh16(&frame4.size); + true_size = pletoh16(&frame4.true_size); - length -= sizeof frame4; /* we already read that much */ + /* + * XXX - it looks as if some version 4 captures have + * a bogus record length, based on the assumption + * that the record is a frame2 record. + */ + if (ngsniffer->maj_vers >= 5) + length -= sizeof frame4; /* we already read that much */ + else { + if (ngsniffer->min_vers >= 95) + length -= sizeof frame2; + else + length -= sizeof frame4; + } - set_pseudo_header_frame4(pseudo_header, &frame4); + set_pseudo_header_frame4(&phdr->pseudo_header, &frame4); break; case REC_FRAME6: /* Read the f_frame6_struct */ - if (!ngsniffer_read_frame6(wth, TRUE, &frame6, err, err_info)) { - /* Read error */ - return FALSE; + bytes_read = ng_file_read(&frame6, (unsigned int)sizeof frame6, + wth, is_random, err, err_info); + if (bytes_read != sizeof frame6) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return -1; } + time_low = pletoh16(&frame6.time_low); + time_med = pletoh16(&frame6.time_med); + time_high = frame6.time_high; + time_day = frame6.time_day; + size = pletoh16(&frame6.size); + true_size = pletoh16(&frame6.true_size); length -= sizeof frame6; /* we already read that much */ - set_pseudo_header_frame6(wth, pseudo_header, &frame6); + set_pseudo_header_frame6(wth, &phdr->pseudo_header, &frame6); break; + case REC_EOF: + /* + * End of file. Return an EOF indication. + */ + *err = 0; /* EOF, not error */ + return REC_EOF; + default: /* - * "Can't happen". + * Unknown record type, or type that's not an EOF or + * a packet record. */ - g_assert_not_reached(); - return FALSE; + if (padding != NULL) { + /* + * Treat the entire record as padding, so we + * skip it. + */ + *padding = length; + } + return type; /* unknown type */ } /* - * Got the pseudo-header (if any), now get the data. + * This is a packet record. + * + * Is the frame data size greater than than what's left of the + * record? */ - if (!ngsniffer_read_rec_data(wth, TRUE, buf, packet_size, err, err_info)) - return FALSE; - - fix_pseudo_header(wth->file_encap, buf, packet_size, pseudo_header); + if (size > length) { + /* + * Yes - treat this as an error. + */ + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("ngsniffer: Record length is less than packet size"); + return -1; + } - return TRUE; -} + if (padding != NULL) { + /* + * Padding, if the frame data size is less than what's + * left of the record. + */ + *padding = length - size; + } -static int -ngsniffer_read_rec_header(wtap *wth, gboolean is_random, guint16 *typep, - guint16 *lengthp, int *err, gchar **err_info) -{ - gint64 bytes_read; - char record_type[2]; - char record_length[4]; /* only 1st 2 bytes are length */ + phdr->presence_flags = true_size ? WTAP_HAS_TS|WTAP_HAS_CAP_LEN : WTAP_HAS_TS; + phdr->len = true_size ? true_size : size; + phdr->caplen = size; /* - * Read the record header. + * Read the packet data. */ - bytes_read = ng_file_read(record_type, 2, wth, is_random, err, - err_info); - if (bytes_read != 2) { - if (*err != 0) - return -1; - if (bytes_read != 0) { - *err = WTAP_ERR_SHORT_READ; - return -1; - } - return 0; - } - bytes_read = ng_file_read(record_length, 4, wth, is_random, err, - err_info); - if (bytes_read != 4) { + buffer_assure_space(buf, size); + bytes_read = ng_file_read(buffer_start_ptr(buf), size, wth, + is_random, err, err_info); + if (bytes_read != (gint64) size) { if (*err == 0) *err = WTAP_ERR_SHORT_READ; return -1; } - *typep = pletoh16(record_type); - *lengthp = pletoh16(record_length); - return 1; /* success */ -} + phdr->pkt_encap = fix_pseudo_header(wth->file_encap, + buf, length, &phdr->pseudo_header); -static gboolean -ngsniffer_read_frame2(wtap *wth, gboolean is_random, struct frame2_rec *frame2, - int *err, gchar **err_info) -{ - gint64 bytes_read; + /* + * 40-bit time stamp, in units of timeunit picoseconds. + */ + t = (((guint64)time_high)<<32) | (((guint64)time_med) << 16) | time_low; - /* Read the f_frame2_struct */ - bytes_read = ng_file_read(frame2, (unsigned int)sizeof *frame2, wth, - is_random, err, err_info); - if (bytes_read != sizeof *frame2) { - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - return TRUE; + /* + * timeunit is always < 2^(64-40), so t * timeunit fits in 64 + * bits. That gives a 64-bit time stamp, in units of + * picoseconds. + */ + t *= ngsniffer->timeunit; + + /* + * Convert to seconds and picoseconds. + */ + tsecs = t/G_GUINT64_CONSTANT(1000000000000); + tpsecs = t - tsecs*G_GUINT64_CONSTANT(1000000000000); + + /* + * Add in the time_day value (86400 seconds/day). + */ + tsecs += time_day*86400; + + /* + * Add in the capture start time. + */ + tsecs += ngsniffer->start; + + phdr->ts.secs = (time_t)tsecs; + phdr->ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */ + + return type; /* success */ } static void @@ -1496,23 +1497,6 @@ set_pseudo_header_frame2(wtap *wth, union wtap_pseudo_header *pseudo_header, } } -static gboolean -ngsniffer_read_frame4(wtap *wth, gboolean is_random, struct frame4_rec *frame4, - int *err, gchar **err_info) -{ - gint64 bytes_read; - - /* Read the f_frame4_struct */ - bytes_read = ng_file_read(frame4, (unsigned int)sizeof *frame4, wth, - is_random, err, err_info); - if (bytes_read != sizeof *frame4) { - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - return TRUE; -} - static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header, struct frame4_rec *frame4) @@ -1767,23 +1751,6 @@ set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header, pseudo_header->atm.aal5t_chksum = pntoh32(&frame4->atm_info.Trailer.aal5t_chksum); } -static gboolean -ngsniffer_read_frame6(wtap *wth, gboolean is_random, struct frame6_rec *frame6, - int *err, gchar **err_info) -{ - gint64 bytes_read; - - /* Read the f_frame6_struct */ - bytes_read = ng_file_read(frame6, (unsigned int)sizeof *frame6, wth, - is_random, err, err_info); - if (bytes_read != sizeof *frame6) { - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - return TRUE; -} - static void set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header, struct frame6_rec *frame6 _U_) @@ -1799,24 +1766,6 @@ set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header, } } -static gboolean -ngsniffer_read_rec_data(wtap *wth, gboolean is_random, Buffer *buf, - unsigned int length, int *err, gchar **err_info) -{ - gint64 bytes_read; - - buffer_assure_space(buf, length); - bytes_read = ng_file_read(buffer_start_ptr(buf), length, wth, - is_random, err, err_info); - - if (bytes_read != (gint64) length) { - if (*err == 0) - *err = WTAP_ERR_SHORT_READ; - return FALSE; - } - return TRUE; -} - /* * OK, this capture is from an "Internetwork analyzer", and we either * didn't see a type 7 record or it had a network type such as NET_HDLC |