Beispiel #1
0
/* print the contents of this packet to the console */
void print_packet(flow_t flow, const u_char *data, u_int32_t length)
{
  printf("%s: ", flow_filename(flow));
  fwrite(data, length, 1, stdout);
  putchar('\n');
  fflush(stdout);
}
Beispiel #2
0
/* print the contents of this packet to the console */
void print_packet(flow_t flow, flow_state_t *state, const u_char *data,
		  u_int32_t length)
{
  int current_color = 0;

  /* Colors: green, blue, red */
  char *color[3] = { "\033[0;32m", "\033[0;34m", "\033[0;31m" };

  if (use_color) {
    if (IS_SET(state->flags, FLOW_DIR_CS))
      current_color = 1;
    else if (IS_SET(state->flags, FLOW_DIR_SC))
      current_color = 2;
    printf("%s", color[current_color]);
  }

  if (suppress_header == 0)
    printf("%s: ", flow_filename(flow));

  fwrite(data, length, 1, stdout);

  if (use_color)
    printf("\033[0m");

  putchar('\n');
  fflush(stdout);
}
Beispiel #3
0
/* Closes the file belonging to a flow -- returns 1 if a file was
 * actually closed, 0 otherwise (if it was already closed) */
int close_file(flow_state_t *flow_state)
{
  if (flow_state->fp == NULL)
    return 0;

  DEBUG(5) ("%s: closing file", flow_filename(flow_state->flow));
  /* close the file and remember that it's closed */
  fclose(flow_state->fp);
  flow_state->fp = NULL;
  flow_state->pos = 0;
  return 1;
}
Beispiel #4
0
/* Sort FDs in the fd_table according to the comparison function (see
 * comment above) */
void sort_fds()
{
  qsort(fd_ring, max_fds, sizeof(struct flow_state_t *), flow_state_compare);

#if 0
  /* code to dump the table - for debugging */
  {
    int i;

    for(i = 0; i < max_fds; i++) {
      if (fd_ring[i] == NULL)
	continue;
      else
	fprintf(stderr, "fd_slot %d: %s (lasttime=%d)\n", i,
		flow_filename(fd_ring[i]->flow), fd_ring[i]->last_access);
    }
  }
#endif
}
Beispiel #5
0
/* Create a new flow state structure, initialize its contents, and add
 * it to its hash bucket.  It is prepended to the hash bucket because
 * 1) doing so is fast (requiring constant time regardless of bucket
 * size; and 2) it'll tend to make lookups faster for more recently
 * added state, which will probably be more often used state.
 *
 * Returns a pointer to the new state. */
flow_state_t *create_flow_state(flow_t flow, tcp_seq isn)
{
  /* create space for the new state */
  flow_state_t *new_flow = MALLOC(flow_state_t, 1);

  /* determine where in the hash this goes */
  int index = HASH_FLOW(flow);

  /* link it in to the hash bucket at the beginning */
  new_flow->next = flow_hash[index];
  flow_hash[index] = new_flow;

  /* initialize contents of the state structure */
  new_flow->flow = flow;
  new_flow->isn = isn;
  new_flow->fp = NULL;
  new_flow->pos = 0;
  new_flow->flags = 0;
  new_flow->last_access = current_time++;

  DEBUG(5) ("%s: new flow", flow_filename(flow));

  return new_flow;
}
Beispiel #6
0
FILE *open_file(flow_state_t *flow_state)
{
  char *filename = flow_filename(flow_state->flow);
  int done;

  /* This shouldn't be called if the file is already open */
  if (flow_state->fp) {
    DEBUG(20) ("huh -- trying to open already open file!");
    return flow_state->fp;
  }

  /* Now try and open the file */
  do {
    if (attempt_fopen(flow_state, filename) != NULL) {
      /* open succeeded... great */
      done = 1;
    } else {
      if (errno == ENFILE || errno == EMFILE) {
	/* open failed because too many files are open... close one
           and try again */
	contract_fd_ring();
	DEBUG(5) ("too many open files -- contracting FD ring to %d", max_fds);
	done = 0;
      } else {
	/* open failed for some other reason... give up */
	done = 1;
      }
    }
  } while (!done);

  /* If the file isn't open at this point, there's a problem */
  if (flow_state->fp == NULL) {
    /* we had some problem opening the file -- set FINISHED so we
     * don't keep trying over and over again to reopen it */
    SET_BIT(flow_state->flags, FLOW_FINISHED);
    perror(filename);
    return NULL;
  }

  /* Now we decide which FD slot we use, and close the file that's
   * there (if any).  Note that even if flow_state is not NULL, its
   * associated file pointer may already be closed.  Note well that we
   * DO NOT free the state that we find in our slot; the state stays
   * around forever (pointed to by the hash table).  This table only
   * keeps a pointer to state structures that have open files so that
   * we can close them later.
   *
   * We are putting the close after the open so that we don't bother
   * closing files if the open fails.  (For this, we pay a price of
   * needing to keep a spare, idle FD around.) */

  if (++next_slot == max_fds) {
    /* take this opportunity to sort from oldest to newest --
     * optimally we'd like to do this before every close, but that
     * might take too long. */
    sort_fds();
    next_slot = 0;
  }

  /* close the next one in line */
  if (fd_ring[next_slot] != NULL)
    close_file(fd_ring[next_slot]);

  /* put ourslves in its place */
  fd_ring[next_slot] = flow_state;

  /* set flags and remember where in the file we are */
  SET_BIT(flow_state->flags, FLOW_FILE_EXISTS);
  FGETPOS(flow_state->fp, &(flow_state->pos));

  return flow_state->fp;
}
Beispiel #7
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);
  }
}