X-Git-Url: http://git.samba.org/?p=metze%2Fwireshark%2Fwip.git;a=blobdiff_plain;f=wiretap%2Fdct3trace.c;h=9c7b81cfe757777b5cb026b9c886d7c523f7a2ad;hp=f3a6169abd5b3fe5b0bae004ac0006637171fb23;hb=fc52696478c7b724b89267782d8c5ce5f0168bf0;hpb=b6ff142f60309faceb422e3d3689c7406aca9361 diff --git a/wiretap/dct3trace.c b/wiretap/dct3trace.c index f3a6169abd..9c7b81cfe7 100644 --- a/wiretap/dct3trace.c +++ b/wiretap/dct3trace.c @@ -6,39 +6,22 @@ * * Duncan Salerno * - * $Id$ - * * Wiretap Library * 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. + * SPDX-License-Identifier: GPL-2.0-or-later */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include "wtap-int.h" -#include "buffer.h" #include "dct3trace.h" #include "file_wrappers.h" -#include #include #include -#include +#include +#include /* Example downlink data: @@ -70,7 +53,9 @@ static const char dct3trace_magic_line2[] = ""; static const char dct3trace_magic_record_start[] = "= '0') && (hex <= '9')) return hex - '0'; if ((hex >= 'a') && (hex <= 'f')) @@ -97,31 +81,31 @@ hc2b(unsigned char hex) } static int -hex2bin(unsigned char *out, unsigned char *in) +hex2bin(guint8 *out, guint8 *out_end, char *in) { - unsigned char *out_start = out; - unsigned char *end = in + strlen((char *)in); + guint8 *out_start = out; int is_low = 0; int c; - /* Clamp to maximum packet size */ - if (end - in > MAX_PACKET_LEN*2) /* As we're reading nibbles */ - end = in + MAX_PACKET_LEN*2; - - while (in < end) + while (*in != '\0') { - c = hc2b(in[0]); + c = hc2b(*(unsigned char *)in); if (c < 0) { in++; continue; } + if (out == out_end) + { + /* Too much data */ + return -1; + } if (is_low == 0) { - out[0] = c << 4; + *out = c << 4; is_low = 1; } else { - out[0] |= (c & 0x0f); + *out |= (c & 0x0f); is_low = 0; out++; } @@ -131,96 +115,112 @@ hex2bin(unsigned char *out, unsigned char *in) return (int)(out - out_start); } -static int -xml_get_int(int *val, const unsigned char *str, const unsigned char *pattern) +static gboolean +xml_get_int(int *val, const char *str, const char *pattern, int *err, gchar **err_info) { - const char *ptr; + const char *ptr, *endptr; char *start, *end; char buf[32]; - ptr = strstr((const char *)str, (const char *)pattern); - if (ptr == NULL) - return -1; + ptr = strstr(str, pattern); + if (ptr == NULL) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: %s not found", pattern); + return FALSE; + } + /* + * XXX - should we just skip past the pattern and check for ="? + */ start = strchr(ptr, '"'); - if (start == NULL) - return -2; + if (start == NULL) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: opening quote for %s not found", pattern); + return FALSE; + } start++; + /* + * XXX - should we just use ws_strtoi32() and check whether + * the character following the number is a "? + */ end = strchr(start, '"'); - if (end == NULL) - return -3; - if (end - start > 31) - return -4; + if (end == NULL) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: closing quote for %s not found", pattern); + return FALSE; + } + if (end - start > 31) { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: %s value is too long", pattern); + return FALSE; + } memcpy(buf, start, end - start); buf[end - start] = '\0'; - *val = atoi(buf); - return 0; + /* + * XXX - should we allow negative numbers in all cases? Or are + * there cases where the number is unsigned? + */ + if (!ws_strtoi32(buf, &endptr, val)) { + *err = WTAP_ERR_BAD_FILE; + if (errno == ERANGE) { + if (*val < 0) + *err_info = g_strdup_printf("dct3trace: %s value is too small, minimum is %d", pattern, *val); + else + *err_info = g_strdup_printf("dct3trace: %s value is too large, maximum is %d", pattern, *val); + } else + *err_info = g_strdup_printf("dct3trace: %s value \"%s\" not a number", pattern, buf); + return FALSE; + } + if (*endptr != '\0') { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: %s value \"%s\" not a number", pattern, buf); + return FALSE; + } + return TRUE; } -/* Look through the first part of a file to see if this is - * a DCT3 trace file. - * - * Returns TRUE if it is, FALSE if it isn't or if we get an I/O error; - * if we get an I/O error, "*err" will be set to a non-zero value - * and "*err_info" will be set to null or an additional error string. - */ -static gboolean dct3trace_check_file_type(wtap *wth, int *err, gchar **err_info) +wtap_open_return_val dct3trace_open(wtap *wth, int *err, gchar **err_info) { char line1[64], line2[64]; - if (file_gets(line1, sizeof(line1), wth->fh) != NULL && - file_gets(line2, sizeof(line2), wth->fh) != NULL) - { - /* Don't compare line endings */ - if( strncmp(dct3trace_magic_line1, line1, strlen(dct3trace_magic_line1)) == 0 && - strncmp(dct3trace_magic_line2, line2, strlen(dct3trace_magic_line2)) == 0) - { - return TRUE; - } - } - /* EOF or error. */ - else + /* Look for Gammu DCT3 trace header */ + if (file_gets(line1, sizeof(line1), wth->fh) == NULL || + file_gets(line2, sizeof(line2), wth->fh) == NULL) { - if (file_eof(wth->fh)) - *err = 0; - else - *err = file_error(wth->fh, err_info); + *err = file_error(wth->fh, err_info); + if (*err != 0 && *err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; } - return FALSE; -} - - -int dct3trace_open(wtap *wth, int *err, gchar **err_info) -{ - /* Look for Gammu DCT3 trace header */ - if (!dct3trace_check_file_type(wth, err, err_info)) + /* Don't compare line endings */ + if( strncmp(dct3trace_magic_line1, line1, strlen(dct3trace_magic_line1)) != 0 || + strncmp(dct3trace_magic_line2, line2, strlen(dct3trace_magic_line2)) != 0) { - if (*err == 0) - return 0; - else - return -1; + return WTAP_OPEN_NOT_MINE; } - wth->data_offset = 0; wth->file_encap = WTAP_ENCAP_GSM_UM; - wth->file_type = WTAP_FILE_DCT3TRACE; + wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_DCT3TRACE; wth->snapshot_length = 0; /* not known */ wth->subtype_read = dct3trace_read; wth->subtype_seek_read = dct3trace_seek_read; - wth->tsprecision = WTAP_FILE_TSPREC_SEC; + wth->file_tsprec = WTAP_TSPREC_SEC; - return 1; + return WTAP_OPEN_MINE; } -static gboolean dct3trace_get_packet(FILE_T fh, union wtap_pseudo_header *pseudo_header, - unsigned char *buf, int *len, int *err, gchar **err_info) +static gboolean dct3trace_get_packet(FILE_T fh, wtap_rec *rec, + Buffer *buf, int *err, gchar **err_info) { - unsigned char line[1024]; + char line[1024]; + guint8 databuf[MAX_PACKET_LEN], *bufp; gboolean have_data = FALSE; + int len = 0; + bufp = &databuf[0]; while (file_gets(line, sizeof(line), fh) != NULL) { if( memcmp(dct3trace_magic_end, line, strlen(dct3trace_magic_end)) == 0 ) @@ -234,71 +234,89 @@ static gboolean dct3trace_get_packet(FILE_T fh, union wtap_pseudo_header *pseudo /* Return on end of record */ if( have_data ) { + /* We've got a full packet! */ + rec->rec_type = REC_TYPE_PACKET; + rec->presence_flags = 0; /* no time stamp, no separate "on the wire" length */ + rec->ts.secs = 0; + rec->ts.nsecs = 0; + rec->rec_header.packet_header.caplen = len; + rec->rec_header.packet_header.len = len; + *err = 0; + + /* Make sure we have enough room for the packet */ + ws_buffer_assure_space(buf, rec->rec_header.packet_header.caplen); + memcpy( ws_buffer_start_ptr(buf), databuf, rec->rec_header.packet_header.caplen ); + return TRUE; } else { /* If not got any data return error */ *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("dct3trace: record without data"); + *err_info = g_strdup("dct3trace: record without data"); return FALSE; } } else if( memcmp(dct3trace_magic_record_start, line, strlen(dct3trace_magic_record_start)) == 0 ) { /* Parse L1 header */ - int channel, tmp, ret = 0; + int channel, tmp; char *ptr; - pseudo_header->gsm_um.uplink = !strstr(line, "direction=\"down\""); - ret |= xml_get_int(&channel, line, "logicalchannel"); + rec->rec_header.packet_header.pseudo_header.gsm_um.uplink = !strstr(line, "direction=\"down\""); + if (!xml_get_int(&channel, line, "logicalchannel", err, err_info)) + return FALSE; /* Parse downlink only fields */ - if( !pseudo_header->gsm_um.uplink ) + if( !rec->rec_header.packet_header.pseudo_header.gsm_um.uplink ) { - ret |= xml_get_int(&tmp, line, "physicalchannel"); - pseudo_header->gsm_um.arfcn = tmp; - ret |= xml_get_int(&tmp, line, "sequence"); - pseudo_header->gsm_um.tdma_frame = tmp; - ret |= xml_get_int(&tmp, line, "bsic"); - pseudo_header->gsm_um.bsic = tmp; - ret |= xml_get_int(&tmp, line, "error"); - pseudo_header->gsm_um.error = tmp; - ret |= xml_get_int(&tmp, line, "timeshift"); - pseudo_header->gsm_um.timeshift = tmp; - } - - if( ret != 0 ) - { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("dct3trace: record missing mandatory attributes"); - return FALSE; + if (!xml_get_int(&tmp, line, "physicalchannel", err, err_info)) + return FALSE; + rec->rec_header.packet_header.pseudo_header.gsm_um.arfcn = tmp; + if (!xml_get_int(&tmp, line, "sequence", err, err_info)) + return FALSE; + rec->rec_header.packet_header.pseudo_header.gsm_um.tdma_frame = tmp; + if (!xml_get_int(&tmp, line, "bsic", err, err_info)) + return FALSE; + rec->rec_header.packet_header.pseudo_header.gsm_um.bsic = tmp; + if (!xml_get_int(&tmp, line, "error", err, err_info)) + return FALSE; + rec->rec_header.packet_header.pseudo_header.gsm_um.error = tmp; + if (!xml_get_int(&tmp, line, "timeshift", err, err_info)) + return FALSE; + rec->rec_header.packet_header.pseudo_header.gsm_um.timeshift = tmp; } switch( channel ) { - case 128: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_SDCCH; break; - case 112: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_SACCH; break; - case 176: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_FACCH; break; - case 96: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_CCCH; break; - case 80: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_BCCH; break; - default: pseudo_header->gsm_um.channel = GSM_UM_CHANNEL_UNKNOWN; break; + case 128: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_SDCCH; break; + case 112: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_SACCH; break; + case 176: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_FACCH; break; + case 96: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_CCCH; break; + case 80: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_BCCH; break; + default: rec->rec_header.packet_header.pseudo_header.gsm_um.channel = GSM_UM_CHANNEL_UNKNOWN; break; } - /* Read data (if have it) into buf */ + /* Read data (if have it) into databuf */ ptr = strstr(line, "data=\""); if( ptr ) { have_data = TRUE; /* If has data... */ - *len = hex2bin(buf, ptr+6); + len = hex2bin(bufp, &databuf[MAX_PACKET_LEN], ptr+6); + if (len == -1) + { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: record length %d too long", rec->rec_header.packet_header.caplen); + return FALSE; + } } } else if( !have_data && memcmp(dct3trace_magic_l2_start, line, strlen(dct3trace_magic_l2_start)) == 0 ) { /* For uplink packets we might not get the raw L1, so have to recreate it from the L2 */ /* Parse L2 header if didn't get data from L1 */ - int data_len = 0; + int data_len; char *ptr = strstr(line, "data=\""); if( !ptr ) @@ -308,24 +326,34 @@ static gboolean dct3trace_get_packet(FILE_T fh, union wtap_pseudo_header *pseudo have_data = TRUE; - if( pseudo_header->gsm_um.channel == GSM_UM_CHANNEL_SACCH || pseudo_header->gsm_um.channel == GSM_UM_CHANNEL_FACCH || pseudo_header->gsm_um.channel == GSM_UM_CHANNEL_SDCCH ) + /* + * We know we have no data already, so we know + * we have enough room for the header. + */ + if( rec->rec_header.packet_header.pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_SACCH || rec->rec_header.packet_header.pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_FACCH || rec->rec_header.packet_header.pseudo_header.gsm_um.channel == GSM_UM_CHANNEL_SDCCH ) { /* Add LAPDm B header */ - memset(buf, 0x1, 2); - *len = 3; + memset(bufp, 0x1, 2); + len = 3; } else { /* Add LAPDm Bbis header */ - *len = 1; + len = 1; } - buf += *len; + bufp += len; - data_len = hex2bin(buf, ptr+6); - *len += data_len; + data_len = hex2bin(bufp, &databuf[MAX_PACKET_LEN], ptr+6); + if (data_len == -1) + { + *err = WTAP_ERR_BAD_FILE; + *err_info = g_strdup_printf("dct3trace: record length %d too long", rec->rec_header.packet_header.caplen); + return FALSE; + } + len += data_len; /* Add LAPDm length byte */ - *(buf - 1) = data_len << 2 | 0x1; + *(bufp - 1) = data_len << 2 | 0x1; } } @@ -342,65 +370,34 @@ static gboolean dct3trace_get_packet(FILE_T fh, union wtap_pseudo_header *pseudo static gboolean dct3trace_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset) { - guint64 offset = file_tell(wth->fh); - int buf_len; - unsigned char buf[MAX_PACKET_LEN]; + *data_offset = file_tell(wth->fh); - if( !dct3trace_get_packet(wth->fh, &wth->pseudo_header, buf, &buf_len, err, err_info) ) - { - return FALSE; - } - - /* We've got a full packet! */ - wth->phdr.presence_flags = 0; /* no time stamp, no separate "on the wire" length */ - wth->phdr.ts.secs = 0; - wth->phdr.ts.nsecs = 0; - wth->phdr.caplen = buf_len; - wth->phdr.len = buf_len; - - /* Make sure we have enough room for the packet */ - buffer_assure_space(wth->frame_buffer, buf_len); - memcpy( buffer_start_ptr(wth->frame_buffer), buf, buf_len ); - - wth->data_offset = *data_offset = offset; - - return TRUE; + return dct3trace_get_packet(wth->fh, &wth->rec, wth->rec_data, + err, err_info); } /* Used to read packets in random-access fashion */ -static gboolean dct3trace_seek_read (wtap *wth, gint64 seek_off, - union wtap_pseudo_header *pseudo_header, guint8 *pd, int len, - int *err, gchar **err_info) +static gboolean dct3trace_seek_read(wtap *wth, gint64 seek_off, + wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) { - int buf_len; - unsigned char buf[MAX_PACKET_LEN]; - if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) { return FALSE; } - if( !dct3trace_get_packet(wth->random_fh, pseudo_header, buf, &buf_len, err, err_info) ) - { - return FALSE; - } - - if( len != buf_len && len != -1 ) - { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("dct3trace: requested length %d doesn't match record length %d", - len, buf_len); - return FALSE; - } - - if( buf_len > MAX_PACKET_LEN) - { - *err = WTAP_ERR_BAD_FILE; - *err_info = g_strdup_printf("dct3trace: record length %d too long", buf_len); - return FALSE; - } - - memcpy( pd, buf, buf_len ); - return TRUE; + return dct3trace_get_packet(wth->random_fh, rec, buf, err, err_info); } + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + * + * vi: set shiftwidth=8 tabstop=8 noexpandtab: + * :indentSize=8:tabSize=8:noTabs=false: + */