コード例 #1
0
ファイル: netsniff-ng.c プロジェクト: dcode/netsniff-ng
static int next_multi_pcap_file(struct mode *mode, int fd)
{
	int ret;
	char tmp[512];

	pcap_ops[mode->pcap]->fsync_pcap(fd);
	if (pcap_ops[mode->pcap]->prepare_close_pcap)
		pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_WRITE);
	close(fd);

	memset(&tmp, 0, sizeof(tmp));
	snprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
	tmp[sizeof(tmp) - 1] = 0;

	fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
			   S_IRUSR | S_IWUSR);
	ret = pcap_ops[mode->pcap]->push_file_header(fd);
	if (ret)
		panic("error writing pcap header!\n");
	if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
		ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
		if (ret)
			panic("error prepare writing pcap!\n");
	}

	return fd;
}
コード例 #2
0
ファイル: netsniff-ng.c プロジェクト: dcode/netsniff-ng
static int begin_multi_pcap_file(struct mode *mode)
{
	int fd, ret;
	char tmp[512];

	if (!pcap_ops[mode->pcap])
		panic("pcap group not supported!\n");
	if (mode->device_out[strlen(mode->device_out) - 1] == '/')
		mode->device_out[strlen(mode->device_out) - 1] = 0;

	memset(&tmp, 0, sizeof(tmp));
	snprintf(tmp, sizeof(tmp), "%s/%lu.pcap", mode->device_out, time(0));
	tmp[sizeof(tmp) - 1] = 0;

	fd = open_or_die_m(tmp, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
			   S_IRUSR | S_IWUSR);
	ret = pcap_ops[mode->pcap]->push_file_header(fd);
	if (ret)
		panic("error writing pcap header!\n");
	if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
		ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
		if (ret)
			panic("error prepare writing pcap!\n");
	}

	interval = mode->dump_interval;
	itimer.it_interval.tv_sec = interval;
	itimer.it_interval.tv_usec = 0;
	itimer.it_value.tv_sec = interval;
	itimer.it_value.tv_usec = 0;
	setitimer(ITIMER_REAL, &itimer, NULL);

	return fd;
}
コード例 #3
0
ファイル: netsniff-ng.c プロジェクト: imclab/netsniff-ng
static int next_multi_pcap_file(struct ctx *ctx, int fd)
{
	int ret;
	char fname[512];

	__pcap_io->fsync_pcap(fd);

	if (__pcap_io->prepare_close_pcap)
		__pcap_io->prepare_close_pcap(fd, PCAP_MODE_WR);

	close(fd);

	slprintf(fname, sizeof(fname), "%s/%s%lu.pcap", ctx->device_out,
		 ctx->prefix ? : "dump-", time(0));

	fd = open_or_die_m(fname, O_RDWR | O_CREAT | O_TRUNC |
			   O_LARGEFILE, DEFFILEMODE);

	ret = __pcap_io->push_fhdr_pcap(fd, ctx->magic, ctx->link_type);
	if (ret)
		panic("Error writing pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_WR, true);
		if (ret)
			panic("Error prepare writing pcap!\n");
	}

	return fd;
}
コード例 #4
0
ファイル: curvetun.c プロジェクト: kartikm/netsniff-ng
static void write_username(char *home)
{
	int fd, ret;
	char path[PATH_MAX];
	char user[512];

	memset(path, 0, sizeof(path));
	slprintf(path, sizeof(path), "%s/%s", home, FILE_USERNAM);

	printf("Username: [%s] ", getenv("USER"));
	fflush(stdout);

	memset(user, 0, sizeof(user));
	if (fgets(user, sizeof(user), stdin) == NULL)
		panic("Could not read from stdin!\n");
	user[sizeof(user) - 1] = 0;
	user[strlen(user) - 1] = 0; /* omit last \n */
	if (strlen(user) == 0)
		strlcpy(user, getenv("USER"), sizeof(user));

	fd = open_or_die_m(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

	ret = write(fd, user, strlen(user));
	if (ret != strlen(user))
		panic("Could not write username!\n");

	close(fd);

	printf("Username written to %s!\n", path);
}
コード例 #5
0
ファイル: netsniff-ng.c プロジェクト: imclab/netsniff-ng
static int begin_single_pcap_file(struct ctx *ctx)
{
	int fd, ret;

	bug_on(!__pcap_io);

	if (!strncmp("-", ctx->device_out, strlen("-"))) {
		fd = dup_or_die(fileno(stdout));
		close(fileno(stdout));
		if (ctx->pcap == PCAP_OPS_MM)
			ctx->pcap = PCAP_OPS_SG;
	} else {
		fd = open_or_die_m(ctx->device_out,
				   O_RDWR | O_CREAT | O_TRUNC |
				   O_LARGEFILE, DEFFILEMODE);
	}

	ret = __pcap_io->push_fhdr_pcap(fd, ctx->magic, ctx->link_type);
	if (ret)
		panic("Error writing pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_WR, true);
		if (ret)
			panic("Error prepare writing pcap!\n");
	}

	return fd;
}
コード例 #6
0
ファイル: trafgen.c プロジェクト: imclab/netsniff-ng
static struct cpu_stats *setup_shared_var(unsigned long cpus)
{
	int fd;
	char zbuff[cpus * sizeof(struct cpu_stats)], file[256];
	struct cpu_stats *buff;

	fmemset(zbuff, 0, sizeof(zbuff));
	slprintf(file, sizeof(file), ".tmp_mmap.%u", (unsigned int) rand());

	fd = creat(file, S_IRUSR | S_IWUSR);
	bug_on(fd < 0);
	close(fd);

	fd = open_or_die_m(file, O_RDWR | O_CREAT | O_TRUNC,
			   S_IRUSR | S_IWUSR);
	write_or_die(fd, zbuff, sizeof(zbuff));

	buff = (void *) mmap(0, sizeof(zbuff), PROT_READ | PROT_WRITE,
			     MAP_SHARED, fd, 0);
	if (buff == (void *) -1)
		panic("Cannot setup shared variable!\n");

	close(fd);
	unlink(file);

	memset(buff, 0, sizeof(zbuff));

	return buff;
}
コード例 #7
0
ファイル: netsniff-ng.c プロジェクト: hosttor/netsniff-ng
static int begin_multi_pcap_file(struct ctx *ctx)
{
	int fd, ret;
	char fname[256];

	bug_on(!__pcap_io);

	if (ctx->device_out[strlen(ctx->device_out) - 1] == '/')
		ctx->device_out[strlen(ctx->device_out) - 1] = 0;

	slprintf(fname, sizeof(fname), "%s/%s%lu.pcap", ctx->device_out,
		 ctx->prefix ? : "dump-", time(NULL));

	fd = open_or_die_m(fname, O_RDWR | O_CREAT | O_TRUNC |
			   O_LARGEFILE, DEFFILEMODE);

	ret = __pcap_io->push_fhdr_pcap(fd, ctx->magic, ctx->link_type);
	if (ret)
		panic("Error writing pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_WR, true);
		if (ret)
			panic("Error prepare writing pcap!\n");
	}

	reset_interval(ctx);

	return fd;
}
コード例 #8
0
ファイル: trafgen.c プロジェクト: nckx/netsniff-ng
static struct cpu_stats *setup_shared_var(unsigned int cpus)
{
	int fd;
	size_t len = cpus * sizeof(struct cpu_stats);
	char *zbuff, file[256];
	struct cpu_stats *buff;

	zbuff = xzmalloc(len);
	slprintf(file, sizeof(file), ".tmp_mmap.%u", (unsigned int) rand());

	fd = creat(file, S_IRUSR | S_IWUSR);
	bug_on(fd < 0);
	close(fd);

	fd = open_or_die_m(file, O_RDWR | O_CREAT | O_TRUNC,
			   S_IRUSR | S_IWUSR);
	write_or_die(fd, zbuff, len);
	xfree(zbuff);

	buff = mmap(NULL, len, PROT_READ | PROT_WRITE,
		    MAP_SHARED, fd, 0);
	if (buff == MAP_FAILED)
		panic("Cannot setup shared variable!\n");

	close(fd);
	unlink(file);

	memset(buff, 0, len);
	return buff;
}
コード例 #9
0
ファイル: netsniff-ng.c プロジェクト: dcode/netsniff-ng
static int begin_single_pcap_file(struct mode *mode)
{
	int fd, ret;

	if (!pcap_ops[mode->pcap])
		panic("pcap group not supported!\n");
	fd = open_or_die_m(mode->device_out,
			   O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE,
			   S_IRUSR | S_IWUSR);
	ret = pcap_ops[mode->pcap]->push_file_header(fd);
	if (ret)
		panic("error writing pcap header!\n");
	if (pcap_ops[mode->pcap]->prepare_writing_pcap) {
		ret = pcap_ops[mode->pcap]->prepare_writing_pcap(fd);
		if (ret)
			panic("error prepare writing pcap!\n");
	}

	return fd;
}
コード例 #10
0
ファイル: netsniff-ng.c プロジェクト: electronjoe/netsniff-ng
static int begin_multi_pcap_file(struct ctx *ctx)
{
	int fd, ret;
	char fname[256];

	bug_on(!__pcap_io);

	if (ctx->device_out[strlen(ctx->device_out) - 1] == '/')
		ctx->device_out[strlen(ctx->device_out) - 1] = 0;

	slprintf(fname, sizeof(fname), "%s/%s%lu.pcap", ctx->device_out,
		 ctx->prefix ? : "dump-", time(0));

	fd = open_or_die_m(fname, O_RDWR | O_CREAT | O_TRUNC |
			   O_LARGEFILE, DEFFILEMODE);

	ret = __pcap_io->push_fhdr_pcap(fd, ctx->magic, ctx->link_type);
	if (ret)
		panic("Error writing pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_WR, ctx->jumbo);
		if (ret)
			panic("Error prepare writing pcap!\n");
	}

	if (ctx->dump_mode == DUMP_INTERVAL_TIME) {
		interval = ctx->dump_interval;

		set_itimer_interval_value(&itimer, interval, 0);
		setitimer(ITIMER_REAL, &itimer, NULL);
	} else {
		interval = 0;
	}

	return fd;
}
コード例 #11
0
ファイル: ioops.c プロジェクト: hhatto/netsniff-ng
void create_or_die(const char *file, mode_t mode)
{
	int fd = open_or_die_m(file, O_WRONLY | O_CREAT, mode);
	close(fd);
}
コード例 #12
0
ファイル: netsniff-ng.c プロジェクト: imclab/netsniff-ng
static void read_pcap(struct ctx *ctx)
{
	__label__ out;
	uint8_t *out;
	int ret, fd, fdo = 0;
	unsigned long trunced = 0;
	size_t out_len;
	pcap_pkthdr_t phdr;
	struct sock_fprog bpf_ops;
	struct frame_map fm;
	struct timeval start, end, diff;
	struct sockaddr_ll sll;

	bug_on(!__pcap_io);

	if (!strncmp("-", ctx->device_in, strlen("-"))) {
		fd = dup_or_die(fileno(stdin));
		close(fileno(stdin));
		if (ctx->pcap == PCAP_OPS_MM)
			ctx->pcap = PCAP_OPS_SG;
	} else {
		fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
	}

	if (__pcap_io->init_once_pcap)
		__pcap_io->init_once_pcap();

	ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type);
	if (ret)
		panic("Error reading pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo);
		if (ret)
			panic("Error prepare reading pcap!\n");
	}

	fmemset(&fm, 0, sizeof(fm));
	fmemset(&bpf_ops, 0, sizeof(bpf_ops));

	bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type);
	if (ctx->dump_bpf)
		bpf_dump_all(&bpf_ops);

	dissector_init_all(ctx->print_mode);

	out_len = round_up(1024 * 1024, PAGE_SIZE);
	out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE);

	if (ctx->device_out) {
		if (!strncmp("-", ctx->device_out, strlen("-"))) {
			fdo = dup_or_die(fileno(stdout));
			close(fileno(stdout));
		} else {
			fdo = open_or_die_m(ctx->device_out, O_RDWR | O_CREAT |
					    O_TRUNC | O_LARGEFILE, DEFFILEMODE);
		}
	}

	drop_privileges(ctx->enforce, ctx->uid, ctx->gid);

	printf("Running! Hang up with ^C!\n\n");
	fflush(stdout);

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0)) {
		do {
			ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic,
						   out, out_len);
			if (unlikely(ret < 0))
				goto out;

			if (unlikely(pcap_get_length(&phdr, ctx->magic) == 0)) {
				trunced++;
				continue;
			}

			if (unlikely(pcap_get_length(&phdr, ctx->magic) > out_len)) {
				pcap_set_length(&phdr, ctx->magic, out_len);
				trunced++;
			}
		} while (ctx->filter &&
			 !bpf_run_filter(&bpf_ops, out,
					 pcap_get_length(&phdr, ctx->magic)));

		pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &fm.tp_h, &sll);

		ctx->tx_bytes += fm.tp_h.tp_len;
		ctx->tx_packets++;

		show_frame_hdr(&fm, ctx->print_mode);

		dissector_entry_point(out, fm.tp_h.tp_snaplen,
				      ctx->link_type, ctx->print_mode);

		if (ctx->device_out)
			translate_pcap_to_txf(fdo, out, fm.tp_h.tp_snaplen);

		if (frame_count_max != 0) {
			if (ctx->tx_packets >= frame_count_max) {
				sigint = 1;
				break;
			}
		}
	}

	out:

	bug_on(gettimeofday(&end, NULL));
	timersub(&end, &start, &diff);

	bpf_release(&bpf_ops);

	dissector_cleanup_all();

	if (__pcap_io->prepare_close_pcap)
		__pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD);

	xfree(out);

	fflush(stdout);
	printf("\n");
	printf("\r%12lu packets outgoing\n", ctx->tx_packets);
	printf("\r%12lu packets truncated in file\n", trunced);
	printf("\r%12lu bytes outgoing\n", ctx->tx_bytes);
	printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);

	if (!strncmp("-", ctx->device_in, strlen("-")))
		dup2(fd, fileno(stdin));
	close(fd);

	if (ctx->device_out) {
		if (!strncmp("-", ctx->device_out, strlen("-")))
			dup2(fdo, fileno(stdout));
		close(fdo);
	}
}
コード例 #13
0
ファイル: netsniff-ng.c プロジェクト: hosttor/netsniff-ng
static void read_pcap(struct ctx *ctx)
{
	uint8_t *out;
	int ret, fd, fdo = 0;
	unsigned long trunced = 0;
	size_t out_len;
	pcap_pkthdr_t phdr;
	struct sock_fprog bpf_ops;
	struct frame_map fm;
	struct timeval start, end, diff;
	bool is_out_pcap = ctx->device_out && strstr(ctx->device_out, ".pcap");
	const struct pcap_file_ops *pcap_out_ops = pcap_ops[PCAP_OPS_RW];

	bug_on(!__pcap_io);

	if (!strncmp("-", ctx->device_in, strlen("-"))) {
		fd = dup_or_die(fileno(stdin));
		close(fileno(stdin));
		if (ctx->pcap == PCAP_OPS_MM)
			ctx->pcap = PCAP_OPS_SG;
	} else {
		/* O_NOATIME requires privileges, in case we don't have
		 * them, retry without them at a minor cost of updating
		 * atime in case the fs has been mounted as such.
		 */
		fd = open(ctx->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
		if (fd < 0 && errno == EPERM)
			fd = open_or_die(ctx->device_in, O_RDONLY | O_LARGEFILE);
		if (fd < 0)
			panic("Cannot open file %s! %s.\n", ctx->device_in,
			      strerror(errno));
	}

	if (__pcap_io->init_once_pcap)
		__pcap_io->init_once_pcap(false);

	ret = __pcap_io->pull_fhdr_pcap(fd, &ctx->magic, &ctx->link_type);
	if (ret)
		panic("Error reading pcap header!\n");

	if (__pcap_io->prepare_access_pcap) {
		ret = __pcap_io->prepare_access_pcap(fd, PCAP_MODE_RD, ctx->jumbo);
		if (ret)
			panic("Error prepare reading pcap!\n");
	}

	fmemset(&fm, 0, sizeof(fm));

	bpf_parse_rules(ctx->filter, &bpf_ops, ctx->link_type);
	if (ctx->dump_bpf)
		bpf_dump_all(&bpf_ops);

	dissector_init_all(ctx->print_mode);

	out_len = round_up(1024 * 1024, RUNTIME_PAGE_SIZE);
	out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE);

	if (ctx->device_out) {
		if (!strncmp("-", ctx->device_out, strlen("-"))) {
			fdo = dup_or_die(fileno(stdout));
			close(fileno(stdout));
		} else {
			fdo = open_or_die_m(ctx->device_out, O_RDWR | O_CREAT |
					    O_TRUNC | O_LARGEFILE, DEFFILEMODE);
		}
	}

	if (is_out_pcap) {
		ret = pcap_out_ops->push_fhdr_pcap(fdo, ctx->magic,
						   ctx->link_type);
		if (ret)
			panic("Error writing pcap header!\n");
	}

	drop_privileges(ctx->enforce, ctx->uid, ctx->gid);

	printf("Running! Hang up with ^C!\n\n");
	fflush(stdout);

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0)) {
		do {
			ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic,
						   out, out_len);
			if (unlikely(ret < 0))
				goto out;

			if (unlikely(pcap_get_length(&phdr, ctx->magic) == 0)) {
				trunced++;
				continue;
			}

			if (unlikely(pcap_get_length(&phdr, ctx->magic) > out_len)) {
				pcap_set_length(&phdr, ctx->magic, out_len);
				trunced++;
			}
		} while (ctx->filter &&
			 !bpf_run_filter(&bpf_ops, out,
					 pcap_get_length(&phdr, ctx->magic)));

		pcap_pkthdr_to_tpacket_hdr(&phdr, ctx->magic, &fm.tp_h, &fm.s_ll);

		ctx->tx_bytes += fm.tp_h.tp_len;
		ctx->tx_packets++;

		show_frame_hdr(out, fm.tp_h.tp_snaplen, ctx->link_type, &fm,
			       ctx->print_mode, ctx->tx_packets);

		dissector_entry_point(out, fm.tp_h.tp_snaplen,
				      ctx->link_type, ctx->print_mode,
				      &fm.s_ll);

		if (is_out_pcap) {
			size_t pcap_len = pcap_get_length(&phdr, ctx->magic);
			int wlen = pcap_out_ops->write_pcap(fdo, &phdr,
							    ctx->magic, out,
							    pcap_len);
			if (unlikely(wlen != (int)pcap_get_total_length(&phdr, ctx->magic)))
				panic("Error writing to pcap!\n");
		} else if (ctx->device_out) {
			translate_pcap_to_txf(fdo, out, fm.tp_h.tp_snaplen);
		}

		if (frame_count_max != 0) {
			if (ctx->tx_packets >= frame_count_max) {
				sigint = 1;
				break;
			}
		}
	}

out:
	bug_on(gettimeofday(&end, NULL));
	timersub(&end, &start, &diff);

	bpf_release(&bpf_ops);

	dissector_cleanup_all();

	if (__pcap_io->prepare_close_pcap)
		__pcap_io->prepare_close_pcap(fd, PCAP_MODE_RD);

	xfree(out);

	fflush(stdout);
	printf("\n");
	printf("\r%12lu packets outgoing\n", ctx->tx_packets);
	printf("\r%12lu packets truncated in file\n", trunced);
	printf("\r%12lu bytes outgoing\n", ctx->tx_bytes);
	printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);

	if (!strncmp("-", ctx->device_in, strlen("-")))
		dup2(fd, fileno(stdin));
	close(fd);

	if (ctx->device_out) {
		if (!strncmp("-", ctx->device_out, strlen("-")))
			dup2(fdo, fileno(stdout));
		close(fdo);
	}
}
コード例 #14
0
ファイル: netsniff-ng.c プロジェクト: molotof/netsniff-ng
static void enter_mode_read_pcap(struct mode *mode)
{
	int ret, fd, fdo = 0;
	struct pcap_pkthdr phdr;
	struct sock_fprog bpf_ops;
	struct tx_stats stats;
	struct frame_map fm;
	uint8_t *out;
	size_t out_len;
	unsigned long trunced = 0;
	struct timeval start, end, diff;

	if (!pcap_ops[mode->pcap])
		panic("pcap group not supported!\n");
	fd = open_or_die(mode->device_in, O_RDONLY | O_LARGEFILE | O_NOATIME);
	ret = pcap_ops[mode->pcap]->pull_file_header(fd, &mode->link_type);
	if (ret)
		panic("error reading pcap header!\n");
	if (pcap_ops[mode->pcap]->prepare_reading_pcap) {
		ret = pcap_ops[mode->pcap]->prepare_reading_pcap(fd);
		if (ret)
			panic("error prepare reading pcap!\n");
	}

	fmemset(&fm, 0, sizeof(fm));
	fmemset(&bpf_ops, 0, sizeof(bpf_ops));
	fmemset(&stats, 0, sizeof(stats));

	bpf_parse_rules(mode->filter, &bpf_ops);
	dissector_init_all(mode->print_mode);

	out_len = 64 * 1024;
	out = xmalloc_aligned(out_len, CO_CACHE_LINE_SIZE);

	printf("BPF:\n");
	bpf_dump_all(&bpf_ops);
	printf("MD: RD %s ", pcap_ops[mode->pcap]->name);
#ifdef _LARGEFILE64_SOURCE
	printf("lf64 ");
#endif 
	ioprio_print();
	printf("\n");

	if (mode->device_out) {
		fdo = open_or_die_m(mode->device_out, O_RDWR | O_CREAT |
				    O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR);
	}

	gettimeofday(&start, NULL);

	while (likely(sigint == 0)) {
		do {
			memset(&phdr, 0, sizeof(phdr));
			ret = pcap_ops[mode->pcap]->read_pcap_pkt(fd, &phdr,
					out, out_len);
			if (unlikely(ret < 0))
				goto out;
			if (unlikely(phdr.len == 0)) {
				trunced++;
				continue;
			}
			if (unlikely(phdr.len > out_len)) {
				phdr.len = out_len;
				trunced++;
			}
		} while (mode->filter &&
			 !bpf_run_filter(&bpf_ops, out, phdr.len));

		pcap_pkthdr_to_tpacket_hdr(&phdr, &fm.tp_h);

		stats.tx_bytes += fm.tp_h.tp_len;
		stats.tx_packets++;

		show_frame_hdr(&fm, mode->print_mode, RING_MODE_EGRESS);
		dissector_entry_point(out, fm.tp_h.tp_snaplen,
				      mode->link_type, mode->print_mode);

		if (mode->device_out) {
			int i = 0;
			char bout[80];
			slprintf(bout, sizeof(bout), "{\n  ");
			write_or_die(fdo, bout, strlen(bout));

			while (i < fm.tp_h.tp_snaplen) {
				slprintf(bout, sizeof(bout), "0x%02x, ", out[i]);
				write_or_die(fdo, bout, strlen(bout));
				i++;
				if (i % 10 == 0) {
					slprintf(bout, sizeof(bout), "\n", out[i]);
					write_or_die(fdo, bout, strlen(bout));
					if (i < fm.tp_h.tp_snaplen) {
						slprintf(bout, sizeof(bout), "  ", out[i]);
						write_or_die(fdo, bout, strlen(bout));
					}
				}
			}
			if (i % 10 != 0) {
				slprintf(bout, sizeof(bout), "\n");
				write_or_die(fdo, bout, strlen(bout));
			}
			slprintf(bout, sizeof(bout), "}\n\n");
			write_or_die(fdo, bout, strlen(bout));
		}

		if (frame_cnt_max != 0 &&
		    stats.tx_packets >= frame_cnt_max) {
			sigint = 1;
			break;
		}
	}
out:
	gettimeofday(&end, NULL);
	diff = tv_subtract(end, start);

	fflush(stdout);
	printf("\n");
	printf("\r%12lu frames outgoing\n", stats.tx_packets);
	printf("\r%12lu frames truncated (larger than mtu)\n", trunced);
	printf("\r%12lu bytes outgoing\n", stats.tx_bytes);
	printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);

	xfree(out);

	bpf_release(&bpf_ops);
	dissector_cleanup_all();
	if (pcap_ops[mode->pcap]->prepare_close_pcap)
		pcap_ops[mode->pcap]->prepare_close_pcap(fd, PCAP_MODE_READ);
	close(fd);

	if (mode->device_out)
		close(fdo);
}