diff options
author | Guy Harris <guy@alum.mit.edu> | 2013-05-17 00:00:13 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2013-05-17 00:00:13 +0000 |
commit | b5561ed4f0c371426469beda6fb572ecd8b0351e (patch) | |
tree | 06cd5722298e05f31dcb0017abedb51a23ea9b92 /wiretap/daintree-sna.c | |
parent | 754ccf4f7f129b511deae46aaaab8cb7fe9ddc6f (diff) |
Move the header-processing code into a common daintree_sna_scan_header()
routine.
Rename daintree_sna_hex_char() to daintree_sna_process_hex_data() (to
more clearly indicate what it does - it doesn't process a single
character, it processes a whole bunch of them), and have it do some
error checking and fill in the length field in the wtap_pkthdr.
svn path=/trunk/; revision=49356
Diffstat (limited to 'wiretap/daintree-sna.c')
-rw-r--r-- | wiretap/daintree-sna.c | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/wiretap/daintree-sna.c b/wiretap/daintree-sna.c index 8fdfdb71de..444461b1aa 100644 --- a/wiretap/daintree-sna.c +++ b/wiretap/daintree-sna.c @@ -11,7 +11,7 @@ * * Started with packetlogger.c as a template, but little packetlogger code * remains. Borrowed many snippets from dbs-etherwatch.c, the - * daintree_sna_hex_char function having the largest chunk. + * daintree_sna_process_hex_data function having the largest chunk. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -87,7 +87,11 @@ static gboolean daintree_sna_seek_read(wtap *wth, gint64 seek_off, guint8 *pd, int len, int *err, gchar **err_info); -static guint daintree_sna_hex_char(guchar *str, int *err); +static gboolean daintree_sna_scan_header(struct wtap_pkthdr *phdr, + char *readLine, char *readData, int *err, gchar **err_info); + +static gboolean daintree_sna_process_hex_data(struct wtap_pkthdr *phdr, + guchar *str, int *err, gchar **err_info); /* Open a file and determine if it's a Daintree file */ int daintree_sna_open(wtap *wth, int *err, gchar **err_info) @@ -138,7 +142,6 @@ static gboolean daintree_sna_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { char readLine[DAINTREE_MAX_LINE_SIZE]; - guint64 seconds; char readData[READDATA_BUF_SIZE]; *data_offset = file_tell(wth->fh); @@ -152,60 +155,27 @@ daintree_sna_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) } } while (readLine[0] == COMMENT_LINE); - wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; - /* parse one line of capture data */ - if (sscanf(readLine, "%*s %18" G_GINT64_MODIFIER "u.%9d %9u %" READDATA_MAX_FIELD_SIZE "s", - &seconds, &wth->phdr.ts.nsecs, &wth->phdr.len, readData) != 4) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("daintree_sna: invalid read record"); + if (!daintree_sna_scan_header(&wth->phdr, readLine, readData, + err, err_info)) return FALSE; - } - /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */ - if (wth->phdr.len <= FCS_LENGTH) { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("daintree_sna: packet length <= %u bytes, no frame data present", - FCS_LENGTH); - return FALSE; - } - wth->phdr.len -= FCS_LENGTH; - - wth->phdr.ts.secs = (time_t) seconds; - wth->phdr.ts.nsecs *= 1000; /* convert mS to nS */ - - /* convert packet data from ASCII string to hex, sanity-check its length against what we assume is the - * packet length field, write data to frame buffer */ - if ((wth->phdr.caplen = daintree_sna_hex_char(readData, err)) > FCS_LENGTH) { - /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */ - wth->phdr.caplen -= FCS_LENGTH; - if (wth->phdr.caplen <= wth->phdr.len) { - buffer_assure_space(wth->frame_buffer, wth->phdr.caplen); - memcpy(buffer_start_ptr(wth->frame_buffer), readData, wth->phdr.caplen); - } else { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("daintree_sna: capture length (%u) > packet length (%u)", - wth->phdr.caplen, wth->phdr.len); - return FALSE; - } - } else { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("daintree_sna: invalid packet data"); + /* process packet data */ + if (!daintree_sna_process_hex_data(&wth->phdr, readData, err, err_info)) return FALSE; - } - + buffer_assure_space(wth->frame_buffer, wth->phdr.caplen); + memcpy(buffer_start_ptr(wth->frame_buffer), readData, wth->phdr.caplen); return TRUE; } /* Read the capture file randomly * Wireshark opens the capture file for random access when displaying user-selected packets */ static gboolean -daintree_sna_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr _U_, +daintree_sna_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr, guint8 *pd, int len, int *err, gchar **err_info) { char readLine[DAINTREE_MAX_LINE_SIZE]; - guint pkt_len; char readData[READDATA_BUF_SIZE]; if(file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) @@ -220,37 +190,60 @@ daintree_sna_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr _U_, } } while (readLine[0] == COMMENT_LINE); - /* ignore all but packet data, since the sequential read pass stored everything else */ - if (sscanf(readLine, "%*s %*u.%*u %*u %" READDATA_MAX_FIELD_SIZE "s", readData) != 1) { + /* parse one line of capture data */ + if (!daintree_sna_scan_header(phdr, readLine, readData, err, err_info)) + return FALSE; + + /* process packet data */ + if (!daintree_sna_process_hex_data(phdr, readData, err, err_info)) + return FALSE; + if (phdr->caplen != (guint32)len) { *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("daintree_sna: corrupted seek record"); + *err_info = g_strdup("daintree-sna: corrupted frame"); return FALSE; } + memcpy(pd, readData, phdr->caplen); + return TRUE; +} - /* convert packet data from ASCII hex string to guchar */ - if ((pkt_len = daintree_sna_hex_char(readData, err)) <= FCS_LENGTH) { +/* Scan a header line and fill in a struct wtap_pkthdr */ +static gboolean +daintree_sna_scan_header(struct wtap_pkthdr *phdr, char *readLine, + char *readData, int *err, gchar **err_info) +{ + guint64 seconds; + int useconds; + + phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; + + if (sscanf(readLine, "%*s %18" G_GINT64_MODIFIER "u.%9d %9u %" READDATA_MAX_FIELD_SIZE "s", + &seconds, &useconds, &phdr->len, readData) != 4) { *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("daintree_sna: corrupted packet data"); + *err_info = g_strdup("daintree_sna: invalid read record"); return FALSE; } - pkt_len -= FCS_LENGTH; /* remove padded bytes that Daintree stores instead of FCS */ - - if (pkt_len == (guint) len) { - /* move to frame buffer for dissection */ - memcpy(pd, readData, pkt_len); - } else { + /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */ + if (phdr->len <= FCS_LENGTH) { *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup("daintree-sna: corrupted frame"); + *err_info = g_strdup_printf("daintree_sna: packet length <= %u bytes, no frame data present", + FCS_LENGTH); return FALSE; - } + } + phdr->len -= FCS_LENGTH; + + phdr->ts.secs = (time_t) seconds; + phdr->ts.nsecs = useconds * 1000; /* convert mS to nS */ return TRUE; } -/* Convert an ASCII hex string to guint8 */ -static guint -daintree_sna_hex_char(guchar *str, int *err _U_) { +/* Convert packet data from ASCII hex string to binary in place, + * sanity-check its length against what we assume is the packet length field */ +static gboolean +daintree_sna_process_hex_data(struct wtap_pkthdr *phdr, guchar *str, int *err, + gchar **err_info) +{ guint bytes; guint8 *p; @@ -258,8 +251,12 @@ daintree_sna_hex_char(guchar *str, int *err _U_) { bytes = 0; /* convert hex string to guint8 */ while(*str) { - if (!isxdigit((guchar)*str)) return 0; /* most significant nibble */ + if (!isxdigit((guchar)*str)) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("daintree_sna: non-hex digit in hex data"); + return FALSE; + } if(isdigit((guchar)*str)) { *p = (*str - '0') << 4; } else { @@ -267,8 +264,12 @@ daintree_sna_hex_char(guchar *str, int *err _U_) { } str++; - if (!isxdigit((guchar)*str)) return 0; /* least significant nibble */ + if (!isxdigit((guchar)*str)) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup("daintree_sna: non-hex digit in hex data"); + return FALSE; + } if(isdigit((guchar)*str)) { *p += *str - '0'; } else { @@ -281,5 +282,21 @@ daintree_sna_hex_char(guchar *str, int *err _U_) { bytes++; } - return bytes; + /* Daintree doesn't store the FCS, but pads end of packet with 0xffff, which we toss */ + if (bytes <= FCS_LENGTH) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("daintree_sna: Only %u bytes of packet data", + bytes); + return FALSE; + } + bytes -= FCS_LENGTH; + if (bytes > phdr->len) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("daintree_sna: capture length (%u) > packet length (%u)", + bytes, phdr->len); + return FALSE; + } + + phdr->caplen = bytes; + return TRUE; } |