示例#1
0
static stream_t open_dst(stream_addr_t* addr, const caphead_t cp, const char* comment){
	/* default to stdout */
	if( !stream_addr_is_set(addr) ){
		if ( isatty(STDOUT_FILENO) ){
			fprintf(stderr, "%s: Cannot output to a terminal, either specify a file using `-o FILENAME' or\n"
			        "          redirect output.\n", program_name);
			return NULL;
		}

		/* stdout is not a terminal so user probably want to use redirection */
		stream_addr_str(addr, "/dev/stdout", 0);
	}

	if ( !quiet ){
		fprintf(stderr, "%s: Opening file stream: %s\n", program_name, stream_addr_ntoa(addr));
	}

	int ret;
	stream_t st = NULL;
	if ( (ret=stream_create(&st, addr, cp->nic, cp->mampid, comment)) != 0 ){
		fprintf(stderr, "%s: stream_create failed with code %d: %s.\n", program_name, ret, caputils_error_string(ret));
		return NULL;
	}

	return st;
}
示例#2
0
int main(int argc, char **argv){
	int ret;

	/* validate arguments */
	if ( argc != 2 ){
		fprintf(stderr, "usage: %s FILENAME\n", argv[0]);
		return 1;
	}

	/* load tracefile address */
	const char* filename = argv[1];
	stream_addr_t addr = STREAM_ADDR_INITIALIZER;
	stream_addr_str(&addr, filename, 0);

	/* open stream */
	stream_t stream;
	if ( (ret=stream_open(&stream, &addr, NULL, 0)) != 0 ){
		fprintf(stderr, "%s: %s\n", filename, caputils_error_string(ret));
		return ret;
	}

	/* read packets */
	while ( stream_read_cb(stream, handle_packet, NULL, NULL) == 0 );

	/* close stream */
	stream_close(stream);

	return 0;
}
示例#3
0
static void flush_senders(){
	/* get current timestamp */
	struct timespec now;
	clock_gettime(CLOCK_REALTIME, &now);

	for ( int i = 0; i < MAX_FILTERS; i++ ){
		struct destination* dst = &MAsd[i];
		const size_t payload_size = dst->buffer.end - dst->buffer.begin;

		if ( payload_size > 0 ){
			const int need_flush = dst->state != BUSY && payload_size > 0;

			/* calculate time since last send. If it was long ago (longer than
			 * MAX_PACKET_AGE) the send buffer is flushed even if it doesn't contain
			 * enough payload for a full packet. */
			signed long int sec = (now.tv_sec - dst->last_sent.tv_sec) * 1000;
			signed long int msec = (now.tv_nsec - dst->last_sent.tv_nsec);
			msec /= 1000000; /* please keep this division a separate statement. It ensures
			                  * that the subtraction above is stored as a signed value. If
			                  * the division is put together the subtraction will be
			                  * calculated as unsigned (tv_psec is stored as unsigned),
			                  * then divided and only then  converted to signed int. */
			const signed long int age = sec + msec;
			const int old_age = age >= MAX_PACKET_AGE;

			if ( need_flush || old_age ){
				send_packet(dst);
				dst->last_sent = now;
			}
		}

		/* stop destinations flagged for termination */
		if ( dst->state == STOP ){
			int ret;
			logmsg(verbose, SENDER, "Closing stream %d\n", dst->index);
			if ( (ret=stream_close(dst->stream)) != 0 ){
				logmsg(stderr, SENDER, "stream_close() returned 0x%08x: %s\n", ret, caputils_error_string(ret));
			}
			dst->stream = NULL;
			dst->state = IDLE;
		}
	}
}
示例#4
0
static int check(const char* cmdline, int expect_fail){
	int ret;

	/* try to execute */
	ret = system(cmdline);
	if ( ret != 0 && !expect_fail ){
		fprintf(stderr, "capdump_argv: command exited with code %d: \"%s\"\n", WEXITSTATUS(ret), cmdline);
		return 0;
	} else if ( ret == 0 && expect_fail ){
		fprintf(stderr, "capdump_argv: command exited with code 0 but expected to fail: \"%s\"\n", cmdline);
		return 0;
	} else if ( ret != 0 && expect_fail ){
		return 1;
	}

	stream_t st;
	stream_addr_t addr;
	stream_addr_str(&addr, "test-temp.cap", 0);

	/* validate output */
	if ( (ret=stream_open(&st, &addr, NULL, 0)) != 0 ){
		fprintf(stderr, "capdump_argv: command did not create a valid trace: \"%s\"\n", cmdline);
		fprintf(stderr, "capdump_argv: stream_open(..) returned %d: %s\n", ret, caputils_error_string(ret));
		return 0;
	}

	caphead_t cp;
	while ( stream_read(st, &cp, NULL, NULL) == 0 ); /* do nothing */

	const stream_stat_t* stat = stream_get_stat(st);
	if ( stat->read != 1 ){
		fprintf(stderr, "capdump_argv: command created and incorrect trace: \"%s\"\n", cmdline);
		fprintf(stderr, "capdump_argv: expected 1 packet, got %"PRIu64".\n", stat->read);
		stream_close(st);
		unlink("test-temp.cap");
		return 0;
	}
	stream_close(st);
	unlink("test-temp.cap");

	return 1;
}
示例#5
0
int main (int argc, char **argv){
	/* extract program name from path. e.g. /path/to/MArCd -> MArCd */
	const char* separator = strrchr(argv[0], '/');
	if ( separator ){
		program_name = separator + 1;
	} else {
		program_name = argv[0];
	}

  /* setup capture header */
  struct cap_header cp;
  strncpy(cp.nic, "CONV", CAPHEAD_NICLEN);
  gethostname(cp.mampid, 8);

  /* defaults */
  char* comments = strdup("converted from pcap with pcap2cap-" CAPUTILS_VERSION);
  stream_addr_t dst = STREAM_ADDR_INITIALIZER;

  int op;
  int option_index;
  while ( (op = getopt_long  (argc, argv, shortopts, longopts, &option_index)) != -1 ){
    switch (op){
    case 'c':
      comments = strdup(optarg);
      break;

    case 'm':
      strncpy(cp.mampid, optarg, 8);
      break;

    case 'i': /* --iface */
      strncpy(cp.nic, optarg, CAPHEAD_NICLEN);
      cp.nic[CAPHEAD_NICLEN-1] = 0; /* force null-terminator */
      break;

    case 'l':
      caplen = atoi(optarg);
      break;

    case 'o':
      stream_addr_str(&dst, optarg, 0);
      break;

    case 'q': /* --quiet */
	    quiet = 1;
	    break;

    case 'h':
	    show_usage();
      return 0;
      break;
    default:
      printf ("?? getopt returned character code 0%o ??\n", op);
    }
  }

  /* open input/output */
  pcap_t* pcap = open_src(argc, argv, &cp);
  stream_t st = open_dst(&dst, &cp, comments);
  if ( !(pcap && st) ){
	  return 1; /* error already shown */
  }

  /* comment is no longer needed */
  free(comments);
  comments = NULL;

  /* setup signal handler so it can handle ctrl-c etc with proper closing of streams */
  signal(SIGINT, sighandler);

  const u_char* packet;
  struct pcap_pkthdr pcapHeader;
  unsigned long long pktCount = 0;
  while ( (packet=pcap_next(pcap, &pcapHeader)) && run ){
    cp.ts.tv_sec  = pcapHeader.ts.tv_sec;  /* Copy and convert the timestamp provided by PCAP, assumes _usec. If nsec will be present adjust! */
    cp.ts.tv_psec = pcapHeader.ts.tv_usec * 1e6;
    cp.len = pcapHeader.len; /* The Wire-lenght of the frame */
    cp.caplen = min(pcapHeader.caplen, caplen);

    // Let the user know that we are alive, good when processing large files.
    if ( !quiet && pktCount++ % 1000 == 0 ) {
      fprintf(stderr, ".");
      fflush(stderr);
    }

    // Save a copy of the frame to the new file.
    int ret;
    if ( (ret=stream_write_separate(st, &cp, packet, cp.caplen)) != 0 ) {
	    fprintf(stderr, "stream_write(..) returned %d: %s\n", ret, caputils_error_string(ret));
    }
  }

  /* Release resources */
  stream_close(st);
  stream_addr_reset(&dst);
  pcap_close(pcap);

  if ( !quiet ){
	  fprintf(stderr, "\n%s: There was a total of %lld packets converted.\n", program_name, pktCount);
  }

  return 0;
}
示例#6
0
int main(int argc, char **argv){
	/* extract program name from path. e.g. /path/to/MArCd -> MArCd */
	const char* separator = strrchr(argv[0], '/');
	if ( separator ){
		program_name = separator + 1;
	} else {
		program_name = argv[0];
	}

	struct filter filter;
	if ( filter_from_argv(&argc, argv, &filter) != 0 ){
		return 0; /* error already shown */
	}

	int op, option_index = -1;
	while ( (op = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1 ){
		switch (op){
		case 0:   /* long opt */
		case '?': /* unknown opt */
			break;

		case '1':
		case '2':
		case '3':
		case '4':
		{
			const unsigned int mask = (7<<FORMAT_LAYER_BIT);
			flags &= ~mask; /* reset all layer bits */
			flags |= (op-'0')<<FORMAT_LAYER_BIT;
			break;
		}

		case 'd': /* --calender */
			flags |= FORMAT_DATE_STR | FORMAT_DATE_UTC;
			break;

		case 'D': /* --localtime */
			flags |= FORMAT_DATE_STR | FORMAT_DATE_LOCALTIME;
			break;

		case 'a': /* --absolute */
			flags &= ~FORMAT_REL_TIMESTAMP;
			break;

		case 'r': /* --relative */
			flags |= FORMAT_REL_TIMESTAMP;
			break;

		case 'H': /* --headers */
			flags |= FORMAT_HEADER;
			break;

		case 'p': /* --packets */
			max_packets = atoi(optarg);
			break;

		case 'c': /* --packets */
			max_matched_packets = atoi(optarg);
			break;

		case 't': /* --timeout */
		{
			int tmp = atoi(optarg);
			timeout.tv_sec  = tmp / 1000;
			timeout.tv_usec = tmp % 1000 * 1000;
		}
		break;

		case 'x': /* --hexdump */
			flags |= FORMAT_HEXDUMP;
			break;

		case 'i': /* --iface */
			iface = optarg;
			break;

		case ARGUMENT_VERSION: /* --version */
			show_version();
			return 0;

		case 'h': /* --help */
			show_usage();
			return 0;

		default:
			fprintf (stderr, "%s: argument '-%c' declared but not handled\n", argv[0], op);
		}
	}

	int ret;

	/* Open stream(s) */
	struct stream* stream;
	if ( (ret=stream_from_getopt(&stream, argv, optind, argc, iface, "-", program_name, 0)) != 0 ) {
		return ret; /* Error already shown */
	}
	const stream_stat_t* stat = stream_get_stat(stream);
	stream_print_info(stream, stderr);

	/* handle C-c */
	signal(SIGINT, handle_sigint);

	/* setup formatter */
	struct format format;
	format_setup(&format, flags);

	uint64_t matched = 0;
	while ( keep_running ) {
		/* A short timeout is used to allow the application to "breathe", i.e
		 * terminate if SIGINT was received. */
		struct timeval tv = timeout;

		/* Read the next packet */
		cap_head* cp;
		ret = stream_read(stream, &cp, NULL, &tv);
		if ( ret == EAGAIN ){
			continue; /* timeout */
		} else if ( ret != 0 ){
			break; /* shutdown or error */
		}

		/* identify connection even if filter doesn't match so id will be
		 * deterministic when changing the filter */
		connection_id(cp);

		if ( filter_match(&filter, cp->payload, cp) ){
			format_pkg(stdout, &format, cp);
			matched++;
		} else {
			format_ignore(stdout, &format, cp);
		}

		if ( max_packets > 0 && stat->matched >= max_packets) {
			/* Read enough pkts lets break. */
			break;
		}
		if ( max_matched_packets > 0 && matched >= max_matched_packets) {
			/* Read enough pkts lets break. */
			break;
		}
	}

	/* if ret == -1 the stream was closed properly (e.g EOF or TCP shutdown)
	 * In addition EINTR should not give any errors because it is implied when the
	 * user presses C-c */
	if ( ret > 0 && ret != EINTR ){
		fprintf(stderr, "stream_read() returned 0x%08X: %s\n", ret, caputils_error_string(ret));
	}

	/* Write stats */
	fprintf(stderr, "%"PRIu64" packets read.\n", stat->read);
	fprintf(stderr, "%"PRIu64" packets matched filter.\n", matched);

	/* Release resources */
	stream_close(stream);
	filter_close(&filter);

	return 0;
}