static gboolean parse_dbs_etherwatch_packet(wtap_rec *rec, FILE_T fh, Buffer* buf, int *err, gchar **err_info) { guint8 *pd; char line[DBS_ETHERWATCH_LINE_LENGTH]; int num_items_scanned; int eth_hdr_len, pkt_len, csec; int length_pos, length_from, length; struct tm tm; char mon[4] = "xxx"; gchar *p; static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; int count, line_count; /* Make sure we have enough room for a regular Ethernet packet */ ws_buffer_assure_space(buf, DBS_ETHERWATCH_MAX_ETHERNET_PACKET_LEN); pd = ws_buffer_start_ptr(buf); eth_hdr_len = 0; memset(&tm, 0, sizeof(tm)); /* Our file pointer should be on the first line containing the * summary information for a packet. Read in that line and * extract the useful information */ if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } /* Get the destination address */ p = strstr(line, DEST_MAC_PREFIX); if(!p) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: destination address not found"); return FALSE; } p += strlen(DEST_MAC_PREFIX); if(parse_hex_dump(p, &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != MAC_ADDR_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: destination address not valid"); return FALSE; } eth_hdr_len += MAC_ADDR_LENGTH; /* Get the source address */ /* * Since the first part of the line is already skipped in order to find * the start of the record we cannot index, just look for the first * 'HEX' character */ p = line; while(!g_ascii_isxdigit(*p)) { p++; } if(parse_hex_dump(p, &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != MAC_ADDR_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: source address not valid"); return FALSE; } eth_hdr_len += MAC_ADDR_LENGTH; /* Read the next line of the record header */ if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } /* Check the lines is as least as long as the length position */ if(strlen(line) < LENGTH_POS) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: line too short"); return FALSE; } num_items_scanned = sscanf(line + LENGTH_POS, "%9d byte buffer at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pkt_len, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); if (num_items_scanned != 8) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: header line not valid"); return FALSE; } if (pkt_len < 0) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: packet header has a negative packet length"); return FALSE; } /* Determine whether it is Ethernet II or IEEE 802 */ if(strncmp(&line[ETH_II_CHECK_POS], ETH_II_CHECK_STR, strlen(ETH_II_CHECK_STR)) == 0) { /* Ethernet II */ /* Get the Protocol */ if(parse_hex_dump(&line[PROTOCOL_POS], &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != PROTOCOL_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: Ethernet II protocol value not valid"); return FALSE; } eth_hdr_len += PROTOCOL_LENGTH; } else { /* IEEE 802 */ /* Remember where to put the length in the header */ length_pos = eth_hdr_len; /* Leave room in the header for the length */ eth_hdr_len += IEEE802_LEN_LEN; /* Remember how much of the header should not be added to the length */ length_from = eth_hdr_len; /* Get the DSAP + SSAP */ if(parse_hex_dump(&line[SAP_POS], &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != SAP_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 DSAP+SSAP value not valid"); return FALSE; } eth_hdr_len += SAP_LENGTH; /* Get the (first part of the) control field */ if(parse_hex_dump(&line[CTL_POS], &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != CTL_UNNUMB_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 control field first part not valid"); return FALSE; } /* Determine whether the control is numbered, and thus longer */ if((pd[eth_hdr_len] & CTL_UNNUMB_MASK) != CTL_UNNUMB_VALUE) { /* Get the rest of the control field, the first octet in the PID */ if(parse_hex_dump(&line[PID_POS], &pd[eth_hdr_len + CTL_UNNUMB_LENGTH], HEX_HDR_END, HEX_HDR_SPR) != CTL_NUMB_LENGTH - CTL_UNNUMB_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 control field second part value not valid"); return FALSE; } eth_hdr_len += CTL_NUMB_LENGTH; } else { eth_hdr_len += CTL_UNNUMB_LENGTH; } /* Determine whether it is SNAP */ if(strncmp(&line[SNAP_CHECK_POS], SNAP_CHECK_STR, strlen(SNAP_CHECK_STR)) == 0) { /* Get the PID */ if(parse_hex_dump(&line[PID_POS], &pd[eth_hdr_len], HEX_HDR_SPR, HEX_PID_END) != PID_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 PID value not valid"); return FALSE; } eth_hdr_len += PID_LENGTH; } /* Write the length in the header */ length = eth_hdr_len - length_from + pkt_len; pd[length_pos] = (length) >> 8; pd[length_pos+1] = (length) & 0xFF; } rec->rec_type = REC_TYPE_PACKET; rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; p = strstr(months, mon); if (p) tm.tm_mon = (int)(p - months) / 3; tm.tm_year -= 1900; tm.tm_isdst = -1; rec->ts.secs = mktime(&tm); rec->ts.nsecs = csec * 10000000; rec->rec_header.packet_header.caplen = eth_hdr_len + pkt_len; rec->rec_header.packet_header.len = eth_hdr_len + pkt_len; if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) { /* * 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; *err_info = g_strdup_printf("dbs_etherwatch: File has %u-byte packet, bigger than maximum of %u", rec->rec_header.packet_header.caplen, WTAP_MAX_PACKET_SIZE_STANDARD); return FALSE; } /* Make sure we have enough room, even for an oversized Ethernet packet */ ws_buffer_assure_space(buf, rec->rec_header.packet_header.caplen); pd = ws_buffer_start_ptr(buf); /* * We don't have an FCS in this frame. */ rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0; /* Parse the hex dump */ count = 0; while (count < pkt_len) { if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } if (!(line_count = parse_single_hex_dump_line(line, &pd[eth_hdr_len + count], count))) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: packet data value not valid"); return FALSE; } count += line_count; if (count > pkt_len) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: packet data value has too many bytes"); return FALSE; } } return TRUE; }
/* Take a string representing one line from a hex dump and converts the * text to binary data. We check the printed offset with the offset * we are passed to validate the record. We place the bytes in the buffer * at the specified offset. * * Returns length parsed if a good hex dump, 0 if bad. */ static guint parse_single_hex_dump_line(char* rec, guint8 *buf, int byte_offset) { int pos, i; int value; /* Check that the record is as least as long as the check offset */ for(i = 0; i < TYPE_CHECK_POS; i++) { if(rec[i] == '\0') { return 0; } } /* determine the format and thus the counter offset and hex dump length */ if(rec[TYPE_CHECK_POS] == TYPE_CHECK_BOTH) { pos = COUNT_POS_BOTH; } else { pos = COUNT_POS_HEX; } /* Check that the record is as least as long as the start position */ while(i < pos) { if(rec[i] == '\0') { return 0; } i++; } /* Get the byte_offset directly from the record */ value = 0; for(i = 0; i < COUNT_SIZE; i++) { if(!g_ascii_isspace(rec[pos])) { if(g_ascii_isdigit(rec[pos])) { value *= 10; value += rec[pos] - '0'; } else { return 0; } } pos++; } if (value != byte_offset) { return 0; } /* find the start of the hex dump */ while(rec[pos] != HEX_DUMP_START) { if(rec[pos] == '\0') { return 0; } pos++; } pos++; return parse_hex_dump(&rec[pos], buf, HEX_DUMP_SPR, HEX_DUMP_END); }
static int parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, guint8* buf, int *err, gchar **err_info) { char line[DBS_ETHERWATCH_LINE_LENGTH]; int num_items_scanned; int eth_hdr_len, pkt_len, csec; int length_pos, length_from, length; struct tm tm; char mon[4] = "xxx"; gchar *p; static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; int count, line_count; eth_hdr_len = 0; memset(&tm, 0, sizeof(tm)); /* Our file pointer should be on the first line containing the * summary information for a packet. Read in that line and * extract the useful information */ if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } /* Get the destination address */ p = strstr(line, DEST_MAC_PREFIX); if(!p) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: destination address not found"); return -1; } p += strlen(DEST_MAC_PREFIX); if(parse_hex_dump(p, &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != MAC_ADDR_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: destination address not valid"); return -1; } eth_hdr_len += MAC_ADDR_LENGTH; /* Get the source address */ /* * Since the first part of the line is already skipped in order to find * the start of the record we cannot index, just look for the first * 'HEX' character */ p = line; while(!isxdigit((guchar)*p)) { p++; } if(parse_hex_dump(p, &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != MAC_ADDR_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: source address not valid"); return -1; } eth_hdr_len += MAC_ADDR_LENGTH; /* Read the next line of the record header */ if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } /* Check the lines is as least as long as the length position */ if(strlen(line) < LENGTH_POS) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: line too short"); return -1; } num_items_scanned = sscanf(line + LENGTH_POS, "%9d byte buffer at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pkt_len, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); if (num_items_scanned != 8) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: header line not valid"); return -1; } /* Determine whether it is Ethernet II or IEEE 802 */ if(strncmp(&line[ETH_II_CHECK_POS], ETH_II_CHECK_STR, strlen(ETH_II_CHECK_STR)) == 0) { /* Ethernet II */ /* Get the Protocol */ if(parse_hex_dump(&line[PROTOCOL_POS], &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != PROTOCOL_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: Ethernet II protocol value not valid"); return -1; } eth_hdr_len += PROTOCOL_LENGTH; } else { /* IEEE 802 */ /* Remember where to put the length in the header */ length_pos = eth_hdr_len; /* Leave room in the header for the length */ eth_hdr_len += IEEE802_LEN_LEN; /* Remember how much of the header should not be added to the length */ length_from = eth_hdr_len; /* Get the DSAP + SSAP */ if(parse_hex_dump(&line[SAP_POS], &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != SAP_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 DSAP+SSAP value not valid"); return -1; } eth_hdr_len += SAP_LENGTH; /* Get the (first part of the) control field */ if(parse_hex_dump(&line[CTL_POS], &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END) != CTL_UNNUMB_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 control field first part not valid"); return -1; } /* Determine whether the control is numbered, and thus longer */ if((buf[eth_hdr_len] & CTL_UNNUMB_MASK) != CTL_UNNUMB_VALUE) { /* Get the rest of the control field, the first octet in the PID */ if(parse_hex_dump(&line[PID_POS], &buf[eth_hdr_len + CTL_UNNUMB_LENGTH], HEX_HDR_END, HEX_HDR_SPR) != CTL_NUMB_LENGTH - CTL_UNNUMB_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 control field second part value not valid"); return -1; } eth_hdr_len += CTL_NUMB_LENGTH; } else { eth_hdr_len += CTL_UNNUMB_LENGTH; } /* Determine whether it is SNAP */ if(strncmp(&line[SNAP_CHECK_POS], SNAP_CHECK_STR, strlen(SNAP_CHECK_STR)) == 0) { /* Get the PID */ if(parse_hex_dump(&line[PID_POS], &buf[eth_hdr_len], HEX_HDR_SPR, HEX_PID_END) != PID_LENGTH) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: 802.2 PID value not valid"); return -1; } eth_hdr_len += PID_LENGTH; } /* Write the length in the header */ length = eth_hdr_len - length_from + pkt_len; buf[length_pos] = (length) >> 8; buf[length_pos+1] = (length) & 0xFF; } if (wth) { wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; p = strstr(months, mon); if (p) tm.tm_mon = (int)(p - months) / 3; tm.tm_year -= 1900; tm.tm_isdst = -1; wth->phdr.ts.secs = mktime(&tm); wth->phdr.ts.nsecs = csec * 10000000; wth->phdr.caplen = eth_hdr_len + pkt_len; wth->phdr.len = eth_hdr_len + pkt_len; } /* Parse the hex dump */ count = 0; while (count < pkt_len) { if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } if (!(line_count = parse_single_hex_dump_line(line, &buf[eth_hdr_len + count], count))) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: packet data value not valid"); return -1; } count += line_count; if (count > pkt_len) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("dbs_etherwatch: packet data value has too many bytes"); return -1; } } return eth_hdr_len + pkt_len; }