/* Converts ASCII hex dump to binary data. Returns the capture length. If any error is encountered, -1 is returned. */ static int parse_cosine_hex_dump(FILE_T fh, int pkt_len, guint8* buf, int *err, gchar **err_info) { gchar line[COSINE_LINE_LENGTH]; int i, hex_lines, n, caplen = 0; /* Calculate the number of hex dump lines, each * containing 16 bytes of data */ hex_lines = pkt_len / 16 + ((pkt_len % 16) ? 1 : 0); for (i = 0; i < hex_lines; i++) { if (file_gets(line, COSINE_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return -1; } if (empty_line(line)) { break; } if ((n = parse_single_hex_dump_line(line, buf, i*16)) == -1) { *err = WTAP_ERR_BAD_RECORD; *err_info = g_strdup("cosine: hex dump line doesn't have 16 numbers"); return -1; } caplen += n; } return caplen; }
/* Converts ASCII hex dump to binary data. Returns TRUE on success, FALSE if any error is encountered. */ static gboolean parse_cosine_hex_dump(FILE_T fh, struct wtap_pkthdr *phdr, int pkt_len, Buffer* buf, int *err, gchar **err_info) { guint8 *pd; gchar line[COSINE_LINE_LENGTH]; int i, hex_lines, n, caplen = 0; /* Make sure we have enough room for the packet */ buffer_assure_space(buf, COSINE_MAX_PACKET_LEN); pd = buffer_start_ptr(buf); /* Calculate the number of hex dump lines, each * containing 16 bytes of data */ hex_lines = pkt_len / 16 + ((pkt_len % 16) ? 1 : 0); for (i = 0; i < hex_lines; i++) { if (file_gets(line, COSINE_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } if (empty_line(line)) { break; } if ((n = parse_single_hex_dump_line(line, pd, i*16)) == -1) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("cosine: hex dump line doesn't have 16 numbers"); return FALSE; } caplen += n; } phdr->caplen = caplen; return TRUE; }
/* Converts ASCII hex dump to binary data, and fills in some struct wtap_pkthdr fields. Returns TRUE on success and FALSE on any error. */ static gboolean parse_netscreen_hex_dump(FILE_T fh, int pkt_len, const char *cap_int, const char *cap_dst, struct wtap_pkthdr *phdr, Buffer* buf, int *err, gchar **err_info) { guint8 *pd; gchar line[NETSCREEN_LINE_LENGTH]; gchar *p; int n, i = 0, offset = 0; gchar dststr[13]; /* Make sure we have enough room for the packet */ buffer_assure_space(buf, NETSCREEN_MAX_PACKET_LEN); pd = buffer_start_ptr(buf); while(1) { /* The last packet is not delimited by an empty line, but by EOF * So accept EOF as a valid delimiter too */ if (file_gets(line, NETSCREEN_LINE_LENGTH, fh) == NULL) { break; } /* * Skip blanks. * The number of blanks is not fixed - for wireless * interfaces, there may be 14 extra spaces before * the hex data. */ for (p = &line[0]; isspace((guchar)*p); p++) ; /* packets are delimited with empty lines */ if (*p == '\0') { break; } n = parse_single_hex_dump_line(p, pd, offset); /* the smallest packet has a length of 6 bytes, if * the first hex-data is less then check whether * it is a info-line and act accordingly */ if (offset == 0 && n < 6) { if (info_line(line)) { if (++i <= NETSCREEN_MAX_INFOLINES) { continue; } } else { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("netscreen: cannot parse hex-data"); return FALSE; } } /* If there is no more data and the line was not empty, * then there must be an error in the file */ if(n == -1) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("netscreen: cannot parse hex-data"); return FALSE; } /* Adjust the offset to the data that was just added to the buffer */ offset += n; /* If there was more hex-data than was announced in the len=x * header, then then there must be an error in the file */ if(offset > pkt_len) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("netscreen: too much hex-data"); return FALSE; } } /* * Determine the encapsulation type, based on the * first 4 characters of the interface name * * XXX convert this to a 'case' structure when adding more * (non-ethernet) interfacetypes */ if (strncmp(cap_int, "adsl", 4) == 0) { /* The ADSL interface can be bridged with or without * PPP encapsulation. Check whether the first six bytes * of the hex data are the same as the destination mac * address in the header. If they are, assume ethernet * LinkLayer or else PPP */ g_snprintf(dststr, 13, "%02x%02x%02x%02x%02x%02x", pd[0], pd[1], pd[2], pd[3], pd[4], pd[5]); if (strncmp(dststr, cap_dst, 12) == 0) phdr->pkt_encap = WTAP_ENCAP_ETHERNET; else phdr->pkt_encap = WTAP_ENCAP_PPP; } else if (strncmp(cap_int, "seri", 4) == 0) phdr->pkt_encap = WTAP_ENCAP_PPP; else phdr->pkt_encap = WTAP_ENCAP_ETHERNET; phdr->caplen = offset; return TRUE; }
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; }
/* Parses a packet record. */ static gboolean parse_vms_packet(FILE_T fh, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info) { char line[VMS_LINE_LENGTH + 1]; int num_items_scanned; guint32 pkt_len = 0; int pktnum; int csec = 101; struct tm tm; char mon[4] = {'J', 'A', 'N', 0}; gchar *p; const gchar *endp; static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; guint32 i; int offset = 0; guint8 *pd; tm.tm_year = 1970; tm.tm_mon = 0; tm.tm_mday = 1; tm.tm_hour = 1; tm.tm_min = 1; tm.tm_sec = 1; /* Skip lines until one starts with a hex number */ do { if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if ((*err == 0) && (csec != 101)) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; if ((csec == 101) && (p = strstr(line, "packet ")) != NULL && (! strstr(line, "could not save "))) { /* Find text in line starting with "packet ". */ /* First look for the Format 1 type sequencing */ num_items_scanned = sscanf(p, "packet %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pktnum, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); /* Next look for the Format 2 type sequencing */ if (num_items_scanned != 8) { num_items_scanned = sscanf(p, "packet seq # = %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pktnum, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); } /* if unknown format then exit with error */ /* We will need to add code to handle new format */ if (num_items_scanned != 8) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("vms: header line not valid"); return FALSE; } } if ( (! pkt_len) && (p = strstr(line, "Length"))) { p += sizeof("Length "); while (*p && ! g_ascii_isdigit(*p)) p++; if ( !*p ) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("vms: Length field not valid"); return FALSE; } if (!ws_strtou32(p, &endp, &pkt_len) || (*endp != '\0' && !g_ascii_isspace(*endp))) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("vms: Length field '%s' not valid", p); return FALSE; } break; } } while (! isdumpline(line)); if (pkt_len > 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("vms: File has %u-byte packet, bigger than maximum of %u", pkt_len, WTAP_MAX_PACKET_SIZE_STANDARD); return FALSE; } p = strstr(months, mon); if (p) tm.tm_mon = (int) (p - months) / 3; tm.tm_year -= 1900; tm.tm_isdst = -1; rec->rec_type = REC_TYPE_PACKET; rec->presence_flags = WTAP_HAS_TS; rec->ts.secs = mktime(&tm); rec->ts.nsecs = csec * 10000000; rec->rec_header.packet_header.caplen = pkt_len; rec->rec_header.packet_header.len = pkt_len; /* Make sure we have enough room for the packet */ ws_buffer_assure_space(buf, pkt_len); pd = ws_buffer_start_ptr(buf); /* Convert the ASCII hex dump to binary data */ for (i = 0; i < pkt_len; i += 16) { if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; if (i == 0) { while (! isdumpline(line)) { /* advance to start of hex data */ if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; } while (line[offset] && !g_ascii_isxdigit(line[offset])) offset++; } if (!parse_single_hex_dump_line(line, pd, i, offset, pkt_len - i)) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("vms: hex dump not valid"); return FALSE; } } /* Avoid TCPIPTRACE-W-BUFFERSFUL, TCPIPtrace could not save n packets. * errors. * * XXX - when we support packet drop report information in the * Wiretap API, we should parse those lines and return "n" as * a packet drop count. */ if (!file_gets(line, VMS_LINE_LENGTH, fh)) { *err = file_error(fh, err_info); if (*err == 0) { /* There is no next line, so there's no "TCPIPtrace could not * save n packets" line; not an error. */ return TRUE; } return FALSE; } return TRUE; }
/* Parses a packet record header. There are two possible formats: 1) output to a control blade with date and time 2002-5-10,20:1:31.4: l2-tx (FR:3/7/1:1), Length:18, Pro:0, Off:0, Pri:0, RM:0, Err:0 [0x4000, 0x0] 2) output to PE without date and time l2-tx (FR:3/7/1:1), Length:18, Pro:0, Off:0, Pri:0, RM:0, Err:0 [0x4000, 0x0] */ static gboolean parse_cosine_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, char *line, int *err, gchar **err_info) { union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header; int num_items_scanned; int yy, mm, dd, hr, min, sec, csec, pkt_len; int pro, off, pri, rm, error; guint code1, code2; char if_name[COSINE_MAX_IF_NAME_LEN] = "", direction[6] = ""; struct tm tm; guint8 *pd; int i, hex_lines, n, caplen = 0; if (sscanf(line, "%4d-%2d-%2d,%2d:%2d:%2d.%9d:", &yy, &mm, &dd, &hr, &min, &sec, &csec) == 7) { /* appears to be output to a control blade */ num_items_scanned = sscanf(line, "%4d-%2d-%2d,%2d:%2d:%2d.%9d: %5s (%127[A-Za-z0-9/:]), Length:%9d, Pro:%9d, Off:%9d, Pri:%9d, RM:%9d, Err:%9d [%8x, %8x]", &yy, &mm, &dd, &hr, &min, &sec, &csec, direction, if_name, &pkt_len, &pro, &off, &pri, &rm, &error, &code1, &code2); if (num_items_scanned != 17) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("cosine: purported control blade line doesn't have code values"); return FALSE; } } else { /* appears to be output to PE */ num_items_scanned = sscanf(line, "%5s (%127[A-Za-z0-9/:]), Length:%9d, Pro:%9d, Off:%9d, Pri:%9d, RM:%9d, Err:%9d [%8x, %8x]", direction, if_name, &pkt_len, &pro, &off, &pri, &rm, &error, &code1, &code2); if (num_items_scanned != 10) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("cosine: header line is neither control blade nor PE output"); return FALSE; } yy = mm = dd = hr = min = sec = csec = 0; } if (pkt_len < 0) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("cosine: packet header has a negative packet length"); return FALSE; } if (pkt_len > WTAP_MAX_PACKET_SIZE) { /* * Probably a corrupt capture file; don't blow up trying * to allocate space for an immensely-large packet. */ *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("cosine: File has %u-byte packet, bigger than maximum of %u", pkt_len, WTAP_MAX_PACKET_SIZE); return FALSE; } phdr->rec_type = REC_TYPE_PACKET; phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN; tm.tm_year = yy - 1900; tm.tm_mon = mm - 1; tm.tm_mday = dd; tm.tm_hour = hr; tm.tm_min = min; tm.tm_sec = sec; tm.tm_isdst = -1; phdr->ts.secs = mktime(&tm); phdr->ts.nsecs = csec * 10000000; phdr->len = pkt_len; /* XXX need to handle other encapsulations like Cisco HDLC, Frame Relay and ATM */ if (strncmp(if_name, "TEST:", 5) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_TEST; } else if (strncmp(if_name, "PPoATM:", 7) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_PPoATM; } else if (strncmp(if_name, "PPoFR:", 6) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_PPoFR; } else if (strncmp(if_name, "ATM:", 4) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_ATM; } else if (strncmp(if_name, "FR:", 3) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_FR; } else if (strncmp(if_name, "HDLC:", 5) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_HDLC; } else if (strncmp(if_name, "PPP:", 4) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_PPP; } else if (strncmp(if_name, "ETH:", 4) == 0) { pseudo_header->cosine.encap = COSINE_ENCAP_ETH; } else { pseudo_header->cosine.encap = COSINE_ENCAP_UNKNOWN; } if (strncmp(direction, "l2-tx", 5) == 0) { pseudo_header->cosine.direction = COSINE_DIR_TX; } else if (strncmp(direction, "l2-rx", 5) == 0) { pseudo_header->cosine.direction = COSINE_DIR_RX; } g_strlcpy(pseudo_header->cosine.if_name, if_name, COSINE_MAX_IF_NAME_LEN); pseudo_header->cosine.pro = pro; pseudo_header->cosine.off = off; pseudo_header->cosine.pri = pri; pseudo_header->cosine.rm = rm; pseudo_header->cosine.err = error; /* Make sure we have enough room for the packet */ ws_buffer_assure_space(buf, pkt_len); pd = ws_buffer_start_ptr(buf); /* Calculate the number of hex dump lines, each * containing 16 bytes of data */ hex_lines = pkt_len / 16 + ((pkt_len % 16) ? 1 : 0); for (i = 0; i < hex_lines; i++) { if (file_gets(line, COSINE_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } if (empty_line(line)) { break; } if ((n = parse_single_hex_dump_line(line, pd, i*16)) == -1) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup("cosine: hex dump line doesn't have 16 numbers"); return FALSE; } caplen += n; } phdr->caplen = caplen; return TRUE; }
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; }
/* Parses a packet record. */ static gboolean parse_vms_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info) { char line[VMS_LINE_LENGTH + 1]; int num_items_scanned; int pkt_len = 0; int pktnum; int csec = 101; struct tm tm; char mon[4] = {'J', 'A', 'N', 0}; gchar *p; static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC"; int i; int offset = 0; guint8 *pd; tm.tm_year = 1970; tm.tm_mon = 0; tm.tm_mday = 1; tm.tm_hour = 1; tm.tm_min = 1; tm.tm_sec = 1; /* Skip lines until one starts with a hex number */ do { if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if ((*err == 0) && (csec != 101)) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; if ((csec == 101) && (p = strstr(line, "packet ")) != NULL && (! strstr(line, "could not save "))) { /* Find text in line starting with "packet ". */ /* First look for the Format 1 type sequencing */ num_items_scanned = sscanf(p, "packet %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pktnum, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); /* Next look for the Format 2 type sequencing */ if (num_items_scanned != 8) { num_items_scanned = sscanf(p, "packet seq # = %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d", &pktnum, &tm.tm_mday, mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &csec); } /* if unknown format then exit with error */ /* We will need to add code to handle new format */ if (num_items_scanned != 8) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("vms: header line not valid"); return FALSE; } } if ( (! pkt_len) && (p = strstr(line, "Length"))) { p += sizeof("Length "); while (*p && ! isdigit((guchar)*p)) p++; if ( !*p ) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("vms: Length field not valid"); return FALSE; } pkt_len = atoi(p); break; } } while (! isdumpline(line)); p = strstr(months, mon); if (p) tm.tm_mon = (int) (p - months) / 3; tm.tm_year -= 1900; tm.tm_isdst = -1; phdr->presence_flags = WTAP_HAS_TS; phdr->ts.secs = mktime(&tm); phdr->ts.nsecs = csec * 10000000; phdr->caplen = pkt_len; phdr->len = pkt_len; /* Make sure we have enough room for the packet */ buffer_assure_space(buf, pkt_len); pd = buffer_start_ptr(buf); /* Convert the ASCII hex dump to binary data */ for (i = 0; i < pkt_len; i += 16) { if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; if (i == 0) { while (! isdumpline(line)) { /* advance to start of hex data */ if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) { *err = file_error(fh, err_info); if (*err == 0) { *err = WTAP_ERR_SHORT_READ; } return FALSE; } line[VMS_LINE_LENGTH] = '\0'; } while (line[offset] && !isxdigit((guchar)line[offset])) offset++; } if (!parse_single_hex_dump_line(line, pd, i, offset, pkt_len - i)) { *err = WTAP_ERR_BAD_FILE; *err_info = g_strdup_printf("vms: hex dump not valid"); return FALSE; } } /* Avoid TCPIPTRACE-W-BUFFERSFUL, TCPIPtrace could not save n packets. * errors. * * XXX - when we support packet drop report information in the * Wiretap API, we should parse those lines and return "n" as * a packet drop count. */ if (!file_gets(line, VMS_LINE_LENGTH, fh)) { *err = file_error(fh, err_info); if (*err == 0) { /* There is no next line, so there's no "TCPIPtrace could not * save n packets" line; not an error. */ return TRUE; } return FALSE; } return TRUE; }