Esempio n. 1
0
int write_to_pcap(PacketFrame * frame)
{
    int res = 0;

    if(NULL == frame || NULL == frame->m_fp) return -1;

    if(0 == ftell(frame->m_fp)) {
        write_pcap_header(frame->m_fp);
    }

    res = write_packet_header(frame);
    res = write_packet_data(frame);

    return res;
}
Esempio n. 2
0
/* here we search through all the frag we have collected to see if
   one fits */
static int
check_fragments( int idx, tcp_stream_chunk *sc, guint32 acknowledged ) {
  tcp_frag *prev = NULL;
  tcp_frag *current;
  guint32 lowest_seq;
  gchar *dummy_str;

  current = frags[idx];
  if( current ) {
    lowest_seq = current->seq;
    while( current ) {
      if( (glong)(lowest_seq - current->seq) > 0 ) {
        lowest_seq = current->seq;
      }

      if( current->seq < seq[idx] ) {
        guint32 newseq;
        /* this sequence number seems dated, but
           check the end to make sure it has no more
           info than we have already seen */
        newseq = current->seq + current->len;
        if( newseq > seq[idx] ) {
          guint32 new_pos;

          /* this one has more than we have seen. let's get the
             payload that we have not seen. This happens when 
             part of this frame has been retransmitted */

          new_pos = seq[idx] - current->seq;

          if ( current->data_len > new_pos ) {
            sc->dlen = current->data_len - new_pos;
            write_packet_data( idx, sc, current->data + new_pos );
          }

          seq[idx] += (current->len - new_pos);
        } 

        /* Remove the fragment from the list as the "new" part of it
         * has been processed or its data has been seen already in 
         * another packet. */
        if( prev ) {
          prev->next = current->next;
        } else {
          frags[idx] = current->next;
        }
        g_free( current->data );
        g_free( current );
        return 1;
      }

      if( current->seq == seq[idx] ) {
        /* this fragment fits the stream */
        if( current->data ) {
          sc->dlen = current->data_len;
          write_packet_data( idx, sc, current->data );
        }
        seq[idx] += current->len;
        if( prev ) {
          prev->next = current->next;
        } else {
          frags[idx] = current->next;
        }
        g_free( current->data );
        g_free( current );
        return 1;
      }
      prev = current;
      current = current->next;
    }
    if( (glong)(acknowledged - lowest_seq) > 0 ) {
      /* There are frames missing in the capture file that were seen
       * by the receiving host. Add dummy stream chunk with the data
       * "[xxx bytes missing in capture file]".
       */
      dummy_str = g_strdup_printf("[%d bytes missing in capture file]",
                        (int)(lowest_seq - seq[idx]) );
      sc->dlen = (guint32) strlen(dummy_str);
      write_packet_data( idx, sc, dummy_str );
      g_free(dummy_str);
      seq[idx] = lowest_seq;
      return 1;
    }
  } 
  return 0;
}
Esempio n. 3
0
void
reassemble_tcp( guint32 tcp_stream, guint32 sequence, guint32 acknowledgement,
                guint32 length, const char* data, guint32 data_length, 
                int synflag, address *net_src, address *net_dst, 
                guint srcport, guint dstport) {
  guint8 srcx[MAX_IPADDR_LEN], dstx[MAX_IPADDR_LEN];
  int src_index, j, first = 0, len;
  guint32 newseq;
  tcp_frag *tmp_frag;
  tcp_stream_chunk sc;

  src_index = -1;

  /* First, check if this packet should be processed. */
  if (find_tcp_index) {
    if ((port[0] == srcport && port[1] == dstport &&
         ADDRESSES_EQUAL(&tcp_addr[0], net_src) &&
         ADDRESSES_EQUAL(&tcp_addr[1], net_dst))
        ||
        (port[1] == srcport && port[0] == dstport &&
         ADDRESSES_EQUAL(&tcp_addr[1], net_src) &&
         ADDRESSES_EQUAL(&tcp_addr[0], net_dst))) {
      find_tcp_index = FALSE;
      tcp_stream_to_follow = tcp_stream;
    }
    else {
      return;
    }
  }
  else if ( tcp_stream != tcp_stream_to_follow )
    return;

  if ((net_src->type != AT_IPv4 && net_src->type != AT_IPv6) ||
      (net_dst->type != AT_IPv4 && net_dst->type != AT_IPv6))
    return;

  if (net_src->type == AT_IPv4)
    len = 4;
  else
    len = 16;

  memcpy(srcx, net_src->data, len);
  memcpy(dstx, net_dst->data, len);

  /* follow_tcp_index() needs to learn address/port pairs */
  if (find_tcp_addr) {
    find_tcp_addr = FALSE;
    memcpy(ip_address[0], net_src->data, net_src->len);
    port[0] = srcport;
    memcpy(ip_address[1], net_dst->data, net_dst->len);
    port[1] = dstport;
  }

  /* Check to see if we have seen this source IP and port before.
     (Yes, we have to check both source IP and port; the connection
     might be between two different ports on the same machine.) */
  for( j=0; j<2; j++ ) {
    if (memcmp(src_addr[j], srcx, len) == 0 && src_port[j] == srcport ) {
      src_index = j;
    }
  }
  /* we didn't find it if src_index == -1 */
  if( src_index < 0 ) {
    /* assign it to a src_index and get going */
    for( j=0; j<2; j++ ) {
      if( src_port[j] == 0 ) {
	memcpy(src_addr[j], srcx, len);
	src_port[j] = srcport;
	src_index = j;
	first = 1;
	break;
      }
    }
  }
  if( src_index < 0 ) {
    fprintf( stderr, "ERROR in reassemble_tcp: Too many addresses!\n");
    return;
  }

  if( data_length < length ) {
    incomplete_tcp_stream = TRUE;
  }

  /* Before adding data for this flow to the data_out_file, check whether
   * this frame acks fragments that were already seen. This happens when
   * frames are not in the capture file, but were actually seen by the 
   * receiving host (Fixes bug 592).
   */
  if( frags[1-src_index] ) {
    memcpy(sc.src_addr, dstx, len);
    sc.src_port = dstport;
    sc.dlen     = 0;        /* Will be filled in in check_fragments */
    while ( check_fragments( 1-src_index, &sc, acknowledgement ) )
      ;
  }

  /* Initialize our stream chunk.  This data gets written to disk. */
  memcpy(sc.src_addr, srcx, len);
  sc.src_port = srcport;
  sc.dlen     = data_length;

  /* now that we have filed away the srcs, lets get the sequence number stuff
     figured out */
  if( first ) {
    /* this is the first time we have seen this src's sequence number */
    seq[src_index] = sequence + length;
    if( synflag ) {
      seq[src_index]++;
    }
    /* write out the packet data */
    write_packet_data( src_index, &sc, data );
    return;
  }
  /* if we are here, we have already seen this src, let's
     try and figure out if this packet is in the right place */
  if( sequence < seq[src_index] ) {
    /* this sequence number seems dated, but
       check the end to make sure it has no more
       info than we have already seen */
    newseq = sequence + length;
    if( newseq > seq[src_index] ) {
      guint32 new_len;

      /* this one has more than we have seen. let's get the
	 payload that we have not seen. */

      new_len = seq[src_index] - sequence;

      if ( data_length <= new_len ) {
	data = NULL;
	data_length = 0;
	incomplete_tcp_stream = TRUE;
      } else {
	data += new_len;
	data_length -= new_len;
      }
      sc.dlen = data_length;
      sequence = seq[src_index];
      length = newseq - seq[src_index];

      /* this will now appear to be right on time :) */
    }
  }
  if ( sequence == seq[src_index] ) {
    /* right on time */
    seq[src_index] += length;
    if( synflag ) seq[src_index]++;
    if( data ) {
      write_packet_data( src_index, &sc, data );
    }
    /* done with the packet, see if it caused a fragment to fit */
    while( check_fragments( src_index, &sc, 0 ) )
      ;
  }
  else {
    /* out of order packet */
    if(data_length > 0 && ((glong)(sequence - seq[src_index]) > 0) ) {
      tmp_frag = (tcp_frag *)g_malloc( sizeof( tcp_frag ) );
      tmp_frag->data = (gchar *)g_malloc( data_length );
      tmp_frag->seq = sequence;
      tmp_frag->len = length;
      tmp_frag->data_len = data_length;
      memcpy( tmp_frag->data, data, data_length );
      if( frags[src_index] ) {
	tmp_frag->next = frags[src_index];
      } else {
	tmp_frag->next = NULL;
      }
      frags[src_index] = tmp_frag;
    }
  }
} /* end reassemble_tcp */
Esempio n. 4
0
/*
 * Opens an .xml file with Trace data formated according to 3GPP TS 32.423 and converts it to
 * an "Exported PDU type file with the entire xml file as the first "packet" appending the
 * raw messages as subsequent packages to be dissected by wireshark.
 */
static wtap_open_return_val
create_temp_pcapng_file(wtap *wth, int *err, gchar **err_info, nettrace_3gpp_32_423_file_info_t *file_info)
{
	int import_file_fd;
	wtap_dumper* wdh_exp_pdu;
	int   exp_pdu_file_err;

	/* pcapng defs */
	wtapng_section_t            *shb_hdr;
	wtapng_iface_descriptions_t *idb_inf;
	wtapng_if_descr_t            int_data;
	GString                     *os_info_str;
	char                        *appname;
	gint64 file_size;
	int packet_size;
	guint8 *packet_buf;
	int wrt_err;
	gchar *wrt_err_info;
	struct wtap_pkthdr phdr;

	gboolean do_random = FALSE;
	char *curr_pos, *next_pos;

	import_file_fd = create_tempfile(&(file_info->tmpname), "Wireshark_PDU_");

	/* Now open a file and dump to it */
	/* Create data for SHB  */
	os_info_str = g_string_new("");
	get_os_version_info(os_info_str);

	appname = g_strdup_printf("Wireshark %s", get_ws_vcs_version_info());

	shb_hdr = g_new(wtapng_section_t, 1);
	shb_hdr->section_length = -1;
	/* options */
	shb_hdr->opt_comment = g_strdup_printf("File converted to Exported PDU format during opening");
	/*
	* UTF-8 string containing the description of the hardware used to create
	* this section.
	*/
	shb_hdr->shb_hardware = NULL;
	/*
	* UTF-8 string containing the name of the operating system used to create
	* this section.
	*/
	shb_hdr->shb_os = g_string_free(os_info_str, FALSE);
	/*
	* UTF-8 string containing the name of the application used to create
	* this section.
	*/
	shb_hdr->shb_user_appl = appname;

	/* Create fake IDB info */
	idb_inf = g_new(wtapng_iface_descriptions_t, 1);
	idb_inf->interface_data = g_array_new(FALSE, FALSE, sizeof(wtapng_if_descr_t));

	/* create the fake interface data */
	int_data.wtap_encap = WTAP_ENCAP_WIRESHARK_UPPER_PDU;
	int_data.time_units_per_second = 1000000; /* default microsecond resolution */
	int_data.link_type = wtap_wtap_encap_to_pcap_encap(WTAP_ENCAP_WIRESHARK_UPPER_PDU);
	int_data.snap_len = WTAP_MAX_PACKET_SIZE;
	int_data.if_name = g_strdup("Fake IF");
	int_data.opt_comment = NULL;
	int_data.if_description = NULL;
	int_data.if_speed = 0;
	int_data.if_tsresol = 6;
	int_data.if_filter_str = NULL;
	int_data.bpf_filter_len = 0;
	int_data.if_filter_bpf_bytes = NULL;
	int_data.if_os = NULL;
	int_data.if_fcslen = -1;
	int_data.num_stat_entries = 0;          /* Number of ISB:s */
	int_data.interface_statistics = NULL;

	g_array_append_val(idb_inf->interface_data, int_data);

	wdh_exp_pdu = wtap_dump_fdopen_ng(import_file_fd, WTAP_FILE_TYPE_SUBTYPE_PCAPNG, WTAP_ENCAP_WIRESHARK_UPPER_PDU,
					  WTAP_MAX_PACKET_SIZE, FALSE, shb_hdr, idb_inf, NULL, &exp_pdu_file_err);
	if (wdh_exp_pdu == NULL) {
		return WTAP_OPEN_ERROR;
	}

	g_free(shb_hdr);
	g_free(appname);

	/* OK we've opend a new pcap-ng file and written the headers, time to do the packets, strt by finding the file size */

	if ((file_size = wtap_file_size(wth, err)) == -1)
		return WTAP_OPEN_ERROR;

	if (file_size > MAX_FILE_SIZE) {
		/*
		* Don't blow up trying to allocate space for an
		* immensely-large file.
		*/
		*err = WTAP_ERR_BAD_FILE;
		*err_info = g_strdup_printf("mime_file: File has %" G_GINT64_MODIFIER "d-byte packet, bigger than maximum of %u",
			file_size, MAX_FILE_SIZE);
		return WTAP_OPEN_ERROR;
	}
	packet_size = (int)file_size;
	/* Allocate the packet buffer
	* (the whole file + Exported PDU tag "protocol" and
	* the string "xml" + 1 filler to end on 4 byte boundary for the tag
	* + End of options 4 bytes
	*/
	/* XXX add the length of exported bdu tag(s) here */
	packet_buf = (guint8 *)g_malloc(packet_size + 12);

	packet_buf[0] = 0;
	packet_buf[1] = 12; /* EXP_PDU_TAG_PROTO_NAME */
	packet_buf[2] = 0;
	packet_buf[3] = 4;
	packet_buf[4] = 0x78; /* "x" */
	packet_buf[5] = 0x6d; /* "m" */
	packet_buf[6] = 0x6c; /* "l" */
	packet_buf[7] = 0;
	/* End of options */
	packet_buf[8] = 0;
	packet_buf[9] = 0;
	packet_buf[10] = 0;
	packet_buf[11] = 0;


	if (!wtap_read_bytes(wth->fh, packet_buf + 12, packet_size, &wrt_err, &wrt_err_info)){
		return WTAP_OPEN_ERROR;
	}

	/* Create the packet header */
	memset(&phdr, 0, sizeof(struct wtap_pkthdr));
	phdr.rec_type = REC_TYPE_PACKET;
	phdr.presence_flags = 0; /* yes, we have no bananas^Wtime stamp */

	phdr.caplen = packet_size + 12;
	phdr.len = packet_size + 12;

	phdr.ts.secs = 0;
	phdr.ts.nsecs = 0;

	/* XXX: report errors! */
	if (!wtap_dump(wdh_exp_pdu, &phdr, packet_buf, &wrt_err, &wrt_err_info)) {
		switch (wrt_err) {

		case WTAP_ERR_UNWRITABLE_REC_DATA:
			g_free(wrt_err_info);
			break;

		default:
			break;
		}
		g_free(packet_buf);
		return WTAP_OPEN_ERROR;
	}

	/* Advance *packet_buf to point at the raw file data */
	curr_pos = packet_buf + 12;
	/* Lets add the raw messages as packets after the main "packet" with the whole file */
	while ((curr_pos = strstr(curr_pos, "<msg")) != NULL){
		wtap_open_return_val temp_val;

		curr_pos = curr_pos + 4;
		next_pos = strstr(curr_pos, "</msg>");
		if (!next_pos){
			/* Somethings wrong, bail out */
			break;
		}
		next_pos = next_pos + 6;
		/* Do we have a raw msg?) */
		curr_pos = strstr(curr_pos, "<rawMsg");
		if (!curr_pos){
			/* No rawMsg, continue */
			curr_pos = next_pos;
			continue;
		}
		curr_pos = curr_pos + 7;
		/* Add the raw msg*/
		temp_val = write_packet_data(wdh_exp_pdu, &phdr, &wrt_err, &wrt_err_info, curr_pos);
		if (temp_val != WTAP_OPEN_MINE){
			g_free(packet_buf);
			return temp_val;
		}
		curr_pos = next_pos;
	}

	/* Close the written file*/
	if (!wtap_dump_close(wdh_exp_pdu, err)){
		g_free(packet_buf);
		return WTAP_OPEN_ERROR;
	}

	g_free(packet_buf);
	/* Now open the file for reading */

	/* Find out if random read was requested */
	if (wth->random_fh){
		do_random = TRUE;
	}
	file_info->wth_tmp_file =
		wtap_open_offline(file_info->tmpname, WTAP_TYPE_AUTO, err, err_info, do_random);

	if (!file_info->wth_tmp_file){
		return WTAP_OPEN_ERROR;
	}

	return WTAP_OPEN_MINE;
}