Exemple #1
0
/* store the contents of this packet to its place in its file */
void store_packet(flow_t flow, const u_char *data, u_int32_t length,
		  u_int32_t seq)
{
  flow_state_t *state;
  tcp_seq offset;
  long fpos;

  /* see if we have state about this flow; if not, create it */
  if ((state = find_flow_state(flow)) == NULL) {
    state = create_flow_state(flow, seq);
  }

  /* if we're done collecting for this flow, return now */
  if (IS_SET(state->flags, FLOW_FINISHED))
    return;

  /* calculate the offset into this flow -- should handle seq num
   * wrapping correctly because tcp_seq is the right size */
  offset = seq - state->isn;

  /* I want to guard against receiving a packet with a sequence number
   * slightly less than what we consider the ISN to be; the max
   * (though admittedly non-scaled) window of 64K should be enough */
  if (offset >= 0xffff0000) {
    DEBUG(2) ("dropped packet with seq < isn on %s", flow_filename(flow));
    return;
  }

  /* reject this packet if it falls entirely outside of the range of
   * bytes we want to receive for the flow */
  if (bytes_per_flow && (offset > bytes_per_flow))
    return;

  /* if we don't have a file open for this flow, try to open it.
   * return if the open fails.  Note that we don't have to explicitly
   * save the return value because open_file() puts the file pointer
   * into the structure for us. */
  if (state->fp == NULL) {
    if (open_file(state) == NULL) {
      return;
    }
  }

  /* We are go for launch!  Everything's ready for us to do a write. */

  /* reduce length if it goes beyond the number of bytes per flow */
  if (bytes_per_flow && (offset + length > bytes_per_flow)) {
    SET_BIT(state->flags, FLOW_FINISHED);
    length = bytes_per_flow - offset;
  }

  /* if we're not at the correct point in the file, seek there */
  if (offset != state->pos) {
    fpos = offset;
    FSETPOS(state->fp, &fpos);
  }

  /* write the data into the file */
  DEBUG(25) ("%s: writing %ld bytes @%ld", flow_filename(state->flow),
	  (long) length, (long) offset);

  if (fwrite(data, length, 1, state->fp) != 1) {
    /* sigh... this should be a nice, plain DEBUG statement that
     * passes strerrror() as an argument, but SunOS 4.1.3 doesn't seem
     * to have strerror. */
    if (debug_level >= 1) {
      DEBUG(1) ("write to %s failed: ", flow_filename(state->flow));
      perror("");
    }
  }
  fflush(state->fp);

  /* remember the position for next time */
  state->pos = offset + length;

  if (IS_SET(state->flags, FLOW_FINISHED)) {
    DEBUG(5) ("%s: stopping capture", flow_filename(state->flow));
    close_file(state);
  }
}
Exemple #2
0
void process_tcp(const u_char *data, u_int32_t length, u_int32_t src,
		 u_int32_t dst)
{
  struct tcphdr *tcp_header = (struct tcphdr *) data;
  flow_t this_flow;
  u_int tcp_header_len;
  tcp_seq seq;
  flow_state_t *state;

  if (length < sizeof(struct tcphdr)) {
    DEBUG(6) ("received truncated TCP segment!");
    return;
  }

  /* calculate the total length of the TCP header including options */
  tcp_header_len = tcp_header->th_off * 4;

  /* fill in the flow_t structure with info that identifies this flow */
  this_flow.src = src;
  this_flow.dst = dst;
  this_flow.sport = ntohs(tcp_header->th_sport);
  this_flow.dport = ntohs(tcp_header->th_dport);
  seq = ntohl(tcp_header->th_seq);

  /* recalculate the beginning of data and its length, moving past the
   * TCP header */
  data += tcp_header_len;
  length -= tcp_header_len;

  /* see if we have state about this flow; if not, create it */
  if ((state = find_flow_state(this_flow)) == NULL) {
    state = create_flow_state(this_flow, seq);
  }

  /* Handle empty packets */
  if (length == 0) {
    /* examine TCP flags for initial TCP handshake segments:
     * - SYN means that the flow is a client -> server flow
     * - SYN/ACK means that the flow is a server -> client flow. */
    if ((state->isn - seq) == 0) {
      if (IS_SET(tcp_header->th_flags, TH_SYN)
	  && IS_SET(tcp_header->th_flags, TH_ACK)) {
	SET_BIT(state->flags, FLOW_DIR_SC);
	DEBUG(50) ("packet is handshake SYN/ACK");
	/* If the SYN flag is set the first data byte is offset by one,
	   account for it (note: if we're here we have just created
	   state, so it's safe to change isn). */
	state->isn++;
      } else if (IS_SET(tcp_header->th_flags, TH_SYN)) {
	SET_BIT(state->flags, FLOW_DIR_CS);
	DEBUG(50) ("packet is handshake SYN");
	state->isn++;
      }
    }
    DEBUG(50) ("got TCP segment with no data");
    return;
  }

  /* strip nonprintable characters if necessary */
  if (strip_nonprint)
    data = do_strip_nonprint(data, length);

  /* store or print the output */
  if (console_only) {
    print_packet(this_flow, state, data, length);
  } else {
    store_packet(this_flow, state, data, length, seq,
		 IS_SET(tcp_header->th_flags, TH_SYN));
  }
}