Exemple #1
0
void tprintf(char *msg, ...)
{
    ssize_t ret;
    ssize_t avail;
    va_list vl;

    spinlock_lock(&buffer_lock);

    avail = sizeof(buffer) - buffer_use;
    bug_on(avail < 0);

    va_start(vl, msg);
    ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
    va_end(vl);

    if (ret < 0)
        panic("vsnprintf screwed up in tprintf!\n");
    if ((size_t) ret > sizeof(buffer))
        panic("No mem in tprintf left!\n");
    if (ret >= avail) {
        __tprintf_flush();

        avail = sizeof(buffer) - buffer_use;
        bug_on(avail < 0);

        va_start(vl, msg);
        ret = vsnprintf(buffer + buffer_use, avail, msg, vl);
        va_end(vl);

        if (ret < 0)
            panic("vsnprintf screwed up in tprintf!\n");
    }

    buffer_use += ret;

    spinlock_unlock(&buffer_lock);
}
Exemple #2
0
/* Starts the parsing process.
 *
 * Returns 0 on success; a negative enum errcode otherwise.
 * Returns -err_pt_lib if the pt encoder could not be initialized.
 * Returns -err_file_write if the .pt or .exp file could not be fully
 * written.
 */
int p_start(struct parser *p)
{
	int errcode;

	if (bug_on(!p))
		return -err_internal;

	errcode = yasm_parse(p->y);
	if (errcode < 0)
		return errcode;

	for (;;) {
		int bytes_written;
		struct pt_encoder *e;

		errcode = yasm_next_pt_directive(p->y, p->pd);
		if (errcode < 0)
			break;

		e = pt_alloc_encoder(p->conf);
		if (!e) {
			fprintf(stderr, "pt_alloc_encoder failed\n");
			errcode = -err_pt_lib;
			break;
		}

		bytes_written = p_process(p, e);
		if (bytes_written == -stop_process) {
			errcode = p_gen_expfile(p);
			break;
		}
		if (bytes_written < 0) {
			errcode = bytes_written;
			break;
		}
		if (fwrite(p->conf->begin, 1, bytes_written, p->ptfile)
		    != (size_t)bytes_written) {
			fprintf(stderr, "write %s failed", p->ptfilename);
			errcode = -err_file_write;
			break;
		}
	}

	/* If there is no directive left, there's nothing more to do.  */
	if (errcode == -err_no_directive)
		return 0;

	return errcode;
}
Exemple #3
0
int parse_tnt(uint64_t *tnt, uint8_t *size, char *payload)
{
	char c;

	if (bug_on(!size))
		return -err_internal;

	if (bug_on(!tnt))
		return -err_internal;

	*size = 0;
	*tnt = 0ull;

	if (!payload)
		return 0;

	while (*payload != '\0') {
		c = *payload;
		payload++;
		if (isspace(c) || c == '.')
			continue;
		*size += 1;
		*tnt <<= 1;
		switch (c) {
		case 'n':
			break;
		case 't':
			*tnt |= 1;
			break;
		default:
			return -err_parse_unknown_char;
		}
	}

	return 0;
}
Exemple #4
0
int l_append(struct label *l, const char *name, uint64_t addr)
{
    int errcode;

    if (bug_on(!l))
        return -err_internal;

    if (bug_on(!name))
        return -err_internal;

    /* skip to the last label.  */
    while (l->next)
        l = l->next;

    /* append a new label.  */
    l->next = l_alloc();
    if (!l->next)
        return -err_no_mem;

    /* save the name.  */
    l->next->name = duplicate_str(name);
    if (!l->next->name) {
        errcode = -err_no_mem;
        goto error;
    }

    /* save the address.  */
    l->next->addr = addr;

    return 0;
error:
    free(l->next->name);
    free(l->next);
    l->next = NULL;
    return errcode;
}
Exemple #5
0
int
dlist_delete(Dlist *dl, Dlist_data *dd)
{
  if (dl == NULL || dd == NULL)
    return 0;
#ifdef DEBUG
  bug_on(__dlist_dlist(dd) != dl);
#endif

  if (!dlist_detach(dl, dd))
    return 0;

  destroy_dlist_data(dd);
  free(dd);

  return 1;
}
Exemple #6
0
int parse_uint64(uint64_t *x, char *payload)
{
	int errcode;

	if (bug_on(!x))
		return -err_internal;

	payload = strtok(payload, " ,");
	if (!payload)
		return -err_parse_no_args;

	errcode = str_to_uint64(payload, x);
	if (errcode < 0)
		return errcode;

	return 0;
}
Exemple #7
0
Dlist_data *
dlist_insert_object(Dlist *dl, Dlist_data *inserted, void *d, Dlist_data_destructor dddest)
{
  Dlist_data *dd;

#ifdef DEBUG
  bug_on(__dlist_dlist(inserted) != dl);
#endif

  dd = dlist_data_create(dl);
  if (unlikely(dd == NULL))
    return NULL;
  dlist_data(dd) = d;
  __dlist_data_destructor(dd) = dddest;

  dlist_attach(dl, dd, inserted);

  return dd;
}
Exemple #8
0
int yasm_next_line(struct yasm *y, char *dest, size_t destlen)
{
	int errcode;

	if (!destlen)
		return 0;

	if (bug_on(!dest))
		return -err_internal;

	errcode = yasm_advance_next_line(y);
	if (errcode < 0)
		return errcode;

	strncpy(dest, y->st_asm->line, destlen);
	dest[destlen-1] = '\0';

	return 0;
}
Exemple #9
0
int parse_tma(uint16_t *ctc, uint16_t *fc, char *payload)
{
	char *endptr;
	long int i;

	if (bug_on(!ctc || !fc))
		return -err_internal;

	payload = strtok(payload, ",");
	if (!payload || *payload == '\0')
		return -err_parse_no_args;

	i = strtol(payload, &endptr, 0);
	if (payload == endptr || *endptr != '\0')
		return -err_parse_int;

	if (i > 0xffffl)
		return -err_parse_int_too_big;

	*ctc = (uint16_t)i;

	payload = strtok(NULL, " ,");
	if (!payload)
		return -err_parse_no_args;

	i = strtol(payload, &endptr, 0);
	if (payload == endptr || *endptr != '\0')
		return -err_parse_int;

	if (i > 0xffffl)
		return -err_parse_int_too_big;

	*fc = (uint16_t)i;

	/* no more tokens left.  */
	payload = strtok(NULL, " ");
	if (payload)
		return -err_parse_trailing_tokens;

	return 0;
}
Exemple #10
0
int parse_uint8(uint8_t *x, char *payload)
{
	char *endptr;
	long int i;

	if (bug_on(!x))
		return -err_internal;

	payload = strtok(payload, " ,");
	if (!payload)
		return -err_parse_no_args;

	i = strtol(payload, &endptr, 0);
	if (payload == endptr || *endptr != '\0')
		return -err_parse_int;

	if (i > 0xff)
		return -err_parse_int_too_big;

	*x = (uint8_t)i;

	return 0;
}
Exemple #11
0
int yasm_parse(struct yasm *y)
{
	int errcode;
	const struct text *t;

	if (bug_on(!y))
		return -err_internal;

	errcode = yasm_run(y);
	if (errcode < 0)
		goto error;

	errcode = fl_gettext(y->fl, &t, y->lstfile);
	if (errcode < 0)
		goto error;

	errcode = parse_yasm_labels(y->l, t);
	if (errcode < 0)
		goto error;

error:
	return errcode;
}
Exemple #12
0
static int xmit_packet_precheck(struct ctx *ctx, unsigned int cpu)
{
	unsigned int i;
	unsigned long plen_total, orig = ctx->num;
	size_t mtu, total_len = 0;

	bug_on(plen != dlen);

	for (i = 0; i < plen; ++i)
		total_len += packets[i].len;

	__set_state_cf(cpu, plen, total_len, CPU_STATS_STATE_CFG);
	plen_total = __wait_and_sum_others(ctx, cpu);

	if (orig > 0) {
		ctx->num = (unsigned long) round((1.0 * plen / plen_total) * orig);

		__set_state_cd(cpu, ctx->num, CPU_STATS_STATE_CHK |
			       CPU_STATS_STATE_CFG);
		__correct_global_delta(ctx, cpu, orig);
	}

	if (plen == 0) {
		__set_state(cpu, CPU_STATS_STATE_RES);
		return 0;
	}

	for (mtu = device_mtu(ctx->device), i = 0; i < plen; ++i) {
		if (packets[i].len > mtu + PKT_MIN_LEN)
			panic("Device MTU < than packet%d's size!\n", i);
		if (packets[i].len <= PKT_MIN_LEN)
			panic("Packet%d's size must be > %d bytes!\n",
					i, PKT_MIN_LEN);
	}

	return 0;
}
Exemple #13
0
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, true);
		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;
}
Exemple #14
0
static void xmit_slowpath_or_die(struct ctx *ctx, int cpu, unsigned long orig_num)
{
	int ret, icmp_sock = -1;
	unsigned long num = 1, i = 0;
	struct timeval start, end, diff;
	unsigned long long tx_bytes = 0, tx_packets = 0;
	struct packet_dyn *pktd;
	struct sockaddr_ll saddr = {
		.sll_family = PF_PACKET,
		.sll_halen = ETH_ALEN,
		.sll_ifindex = device_ifindex(ctx->device),
	};

	if (ctx->num > 0)
		num = ctx->num;
	if (ctx->num == 0 && orig_num > 0)
		num = 0;

	if (ctx->smoke_test)
		icmp_sock = xmit_smoke_setup(ctx);

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

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0) && likely(num > 0) && likely(plen > 0)) {
		pktd = &packet_dyn[i];
		if (pktd->clen + pktd->rlen + pktd->slen) {
			apply_counter(i);
			apply_randomizer(i);
			apply_csum16(i);
		}
retry:
		ret = sendto(sock, packets[i].payload, packets[i].len, 0,
			     (struct sockaddr *) &saddr, sizeof(saddr));
		if (unlikely(ret < 0)) {
			if (errno == ENOBUFS) {
				sched_yield();
				goto retry;
			}

			panic("Sendto error: %s!\n", strerror(errno));
		}

		tx_bytes += packets[i].len;
		tx_packets++;

		if (ctx->smoke_test) {
			ret = xmit_smoke_probe(icmp_sock, ctx);
			if (unlikely(ret < 0)) {
				printf("%sSmoke test alert:%s\n", colorize_start(bold), colorize_end());
				printf("  Remote host seems to be unresponsive to ICMP probes!\n");
				printf("  Last instance was packet%lu, seed:%u, trafgen snippet:\n\n",
				       i, seed);

				dump_trafgen_snippet(packets[i].payload, packets[i].len);
				break;
			}
		}

		if (!ctx->rand) {
			i++;
			if (i >= plen)
				i = 0;
		} else
			i = rand() % plen;

		if (ctx->num > 0)
			num--;

		if (ctx->gap > 0)
			usleep(ctx->gap);
	}

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

	if (ctx->smoke_test)
		close(icmp_sock);

	stats[cpu].tx_packets = tx_packets;
	stats[cpu].tx_bytes = tx_bytes;
	stats[cpu].tv_sec = diff.tv_sec;
	stats[cpu].tv_usec = diff.tv_usec;

	stats[cpu].state |= CPU_STATS_STATE_RES;
}

static void xmit_fastpath_or_die(struct ctx *ctx, int cpu, unsigned long orig_num)
{
	int ifindex = device_ifindex(ctx->device);
	uint8_t *out = NULL;
	unsigned int it = 0;
	unsigned long num = 1, i = 0, size;
	struct ring tx_ring;
	struct frame_map *hdr;
	struct timeval start, end, diff;
	struct packet_dyn *pktd;
	unsigned long long tx_bytes = 0, tx_packets = 0;

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

	size = ring_size(ctx->device, ctx->reserve_size);

	set_sock_prio(sock, 512);
	set_packet_loss_discard(sock);

	setup_tx_ring_layout(sock, &tx_ring, size, ctx->jumbo_support);
	create_tx_ring(sock, &tx_ring, ctx->verbose);
	mmap_tx_ring(sock, &tx_ring);
	alloc_tx_ring_frames(sock, &tx_ring);
	bind_tx_ring(sock, &tx_ring, ifindex);

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

	if (ctx->kpull)
		interval = ctx->kpull;
	if (ctx->num > 0)
		num = ctx->num;
	if (ctx->num == 0 && orig_num > 0)
		num = 0;

	set_itimer_interval_value(&itimer, 0, interval);
	setitimer(ITIMER_REAL, &itimer, NULL); 

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0) && likely(num > 0) && likely(plen > 0)) {
		while (user_may_pull_from_tx(tx_ring.frames[it].iov_base) && likely(num > 0)) {
			hdr = tx_ring.frames[it].iov_base;
			out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);

			hdr->tp_h.tp_snaplen = packets[i].len;
			hdr->tp_h.tp_len = packets[i].len;

			pktd = &packet_dyn[i];
			if (pktd->clen + pktd->rlen + pktd->slen) {
				apply_counter(i);
				apply_randomizer(i);
				apply_csum16(i);
			}

			fmemcpy(out, packets[i].payload, packets[i].len);

			tx_bytes += packets[i].len;
			tx_packets++;

			if (!ctx->rand) {
				i++;
				if (i >= plen)
					i = 0;
			} else
				i = rand() % plen;

			kernel_may_pull_from_tx(&hdr->tp_h);

			it++;
			if (it >= tx_ring.layout.tp_frame_nr)
				it = 0;

			if (ctx->num > 0)
				num--;

			if (unlikely(sigint == 1))
				break;
		}
	}

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

	timer_purge();

	destroy_tx_ring(sock, &tx_ring);

	stats[cpu].tx_packets = tx_packets;
	stats[cpu].tx_bytes = tx_bytes;
	stats[cpu].tv_sec = diff.tv_sec;
	stats[cpu].tv_usec = diff.tv_usec;

	stats[cpu].state |= CPU_STATS_STATE_RES;
}
Exemple #15
0
struct yasm *yasm_alloc(const char *pttfile)
{
	char *tmp;
	size_t n;
	struct yasm *y;

	if (bug_on(!pttfile))
		return NULL;

	y = calloc(1, sizeof(*y));
	if (!y)
		return NULL;

	y->fl = fl_alloc();
	if (!y->fl)
		goto error;

	y->st_asm = st_alloc();
	if (!y->st_asm)
		goto error;

	y->fileroot = duplicate_str(pttfile);
	if (!y->fileroot)
		goto error;

	y->pttfile = duplicate_str(pttfile);
	if (!y->pttfile)
		goto error;

	tmp = strrchr(y->fileroot, '.');
	if (tmp)
		*tmp = '\0';

	tmp = strrchr(y->fileroot, path_separator);
	if (tmp) {
		tmp += 1;
		memmove(y->fileroot, tmp, strlen(tmp)+1);
	}

	y->binfile = malloc(strlen(y->fileroot)+strlen(bin_suffix)+1);
	if (!y->binfile)
		goto error;

	y->lstfile = malloc(strlen(y->fileroot)+strlen(lst_suffix)+1);
	if (!y->lstfile)
		goto error;

	n = strlen(y->fileroot);

	strcpy(y->binfile, y->fileroot);
	strcpy(y->binfile+n, bin_suffix);
	strcpy(y->lstfile, y->fileroot);
	strcpy(y->lstfile+n, lst_suffix);

	y->l = l_alloc();
	if (!y->l)
		goto error;

	return y;

error:
	yasm_free(y);
	return 0;
}
Exemple #16
0
int parse_yasm_labels(struct label *l, const struct text *t)
{
	int errcode, no_org_directive;
	size_t i;
	uint64_t base_addr;
	enum { linelen = 1024 };
	char line[linelen];

	if (bug_on(!t))
		return -err_internal;

	base_addr = 0;
	no_org_directive = 1;

	/* determine base address from org directive, error out on
	 * sections.
	 */
	for (i = 0; i < t->n; i++) {
		char *tmp;

		errcode = text_line(t, line, linelen, i);
		if (errcode < 0)
			return errcode;

		tmp = strstr(line, "[section");
		if (tmp)
			return -err_section;

		tmp = strstr(line, "[org");
		if (!tmp)
			continue;

		base_addr = strtol(tmp+strlen("[org"), NULL, 0);
		no_org_directive = 0;
		break;
	}

	if (no_org_directive)
		return -err_no_org_directive;

	for (i = 0; i < t->n; i++) {
		char *tmp, *name;
		uint64_t addr;

		errcode = text_line(t, line, linelen, i);
		if (errcode < 0)
			goto error;

		/* skip line number count.  */
		tmp = strtok(line, " ");
		if (!tmp)
			continue;

		/* the label can now be on the same line as the memory
		 * address or on a line by its own.
		 * we look at the next token and (1) if it looks like a
		 * label, we search in the following lines for the
		 * corresponding address; or (2) if it looks like an
		 * address, we store it and see if the token after the
		 * opcode looks like a token; or (3) none of the above,
		 * we continue with the next line.
		 */

		/* second token after the line number count.  it's
		 * either an address; or a label.
		 */
		tmp = strtok(NULL, " ");
		if (!tmp)
			continue;

		if (!make_label(tmp)) {
			/* get address in case we find a label later.  */
			if (sscanf(tmp, "%" PRIx64, &addr) != 1)
				continue;

			/* skip the opcode token.  */
			tmp = strtok(NULL, " ");
			if (!tmp)
				continue;

			/* this might be a label now.  */
			tmp = strtok(NULL, " ");
			if (!make_label(tmp))
				continue;

			errcode = l_append(l, tmp, addr + base_addr);
			if (errcode < 0)
				goto error;
			continue;
		}
		name = duplicate_str(tmp);
		if (!name) {
			errcode = -err_no_mem;
			goto error;
		}

		/* there was a label so now an address needs to
		 * be found.
		 */
		errcode = -err_label_addr;
		for (i += 1; i < t->n; i++) {
			int errcode_text;

			errcode_text = text_line(t, line, linelen, i);
			if (errcode_text < 0) {
				errcode = errcode_text;
				break;
			}
			if (sscanf(line, "%*d %" PRIx64 " %*x %*s", &addr)
			    == 1) {
				errcode = l_append(l, name, addr + base_addr);
				break;
			}
		}
		if (errcode == -err_label_addr)
			fprintf(stderr, "label '%s' has no address\n", name);
		free(name);
		if (errcode < 0)
			goto error;
	}

	return 0;

error:
	l_free(l->next);
	free(l->name);
	l->next = NULL;
	l->name = NULL;
	return errcode;
}
Exemple #17
0
int pd_parse(struct pt_directive *pd, struct state *st)
{
	char *line, *comment, *ptdirective, *openpar, *closepar;
	char *directive, *payload;
	int errcode;
	char *c;

	if (bug_on(!pd))
		return -err_internal;

	if (bug_on(!st))
		return -err_internal;


	line = duplicate_str(st->line);
	if (!line)
		return -err_no_mem;

	/* make line lower case.  */
	for (c = line; *c; ++c)
		*c = (char) tolower(*c);

	/* if the current line is not a comment or contains no magic marker
	 * -err_no_directive is returned.
	 */
	errcode = -err_no_directive;

	/* search where the comment begins.  */
	comment = strchr(line, ';');

	/* if there is no comment in the line, we don't have anything to
	 * do.
	 */
	if (!comment)
		goto cleanup;

	/* search for @pt marker.  */
	ptdirective = strstr(comment+1, marker);

	/* if there is no such marker in the comment, we don't have
	 * anything to do.
	 */
	if (!ptdirective)
		goto cleanup;

	/* directive found, now parse the payload.  */
	errcode = 0;

	/* find position of next '(', separating the directive and the
	 * payload.
	 */
	openpar = strchr(ptdirective, '(');
	if (!openpar) {
		errcode = -err_missing_openpar;
		st_print_err(st, "invalid syntax", errcode);
		goto cleanup;
	}

	/* find position of next ')', marking the end of the payload */
	closepar = strchr(openpar, ')');
	if (!closepar) {
		errcode = -err_missing_closepar;
		st_print_err(st, "invalid syntax", errcode);
		goto cleanup;
	}

	/* make "multiple" strings by artifically terminating them with
	 * '\0' then get directive and payload substrings, which will
	 * have leading and trailing whitespace "removed".
	 */
	*openpar = '\0';
	*closepar = '\0';

	/* skip leading whitespace. */
	directive = ptdirective + strlen(marker);
	while (isspace(*directive))
		directive += 1;

	payload = openpar+1;

	errcode = pd_set(pd, directive, payload);

cleanup:
	free(line);
	return errcode;
}
Exemple #18
0
static void recv_only_or_dump(struct ctx *ctx)
{
	short ifflags = 0;
	int sock, irq, ifindex, fd = 0, ret;
	unsigned int size, it = 0;
	struct ring rx_ring;
	struct pollfd rx_poll;
	struct sock_fprog bpf_ops;
	struct timeval start, end, diff;
	struct block_desc *pbd;
	unsigned long frame_count = 0;

	sock = pf_socket();

	if (ctx->rfraw) {
		ctx->device_trans = xstrdup(ctx->device_in);
		xfree(ctx->device_in);

		enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in);
		ctx->link_type = LINKTYPE_IEEE802_11;
	}

	fmemset(&rx_ring, 0, sizeof(rx_ring));
	fmemset(&rx_poll, 0, sizeof(rx_poll));
	fmemset(&bpf_ops, 0, sizeof(bpf_ops));

	ifindex = device_ifindex(ctx->device_in);

	size = ring_size(ctx->device_in, ctx->reserve_size);

	enable_kernel_bpf_jit_compiler();

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

	ret = set_sockopt_hwtimestamp(sock, ctx->device_in);
	if (ret == 0 && ctx->verbose)
		printf("HW timestamping enabled\n");

	setup_rx_ring_layout(sock, &rx_ring, size, true, true);
	create_rx_ring(sock, &rx_ring, ctx->verbose);
	mmap_rx_ring(sock, &rx_ring);
	alloc_rx_ring_frames(sock, &rx_ring);
	bind_rx_ring(sock, &rx_ring, ifindex);

	prepare_polling(sock, &rx_poll);
	dissector_init_all(ctx->print_mode);

	if (ctx->cpu >= 0 && ifindex > 0) {
		irq = device_irq_number(ctx->device_in);
		device_set_irq_affinity(irq, ctx->cpu);

		if (ctx->verbose)
			printf("IRQ: %s:%d > CPU%d\n",
			       ctx->device_in, irq, ctx->cpu);
	}

	if (ctx->promiscuous)
		ifflags = enter_promiscuous_mode(ctx->device_in);

	if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap)
		__pcap_io->init_once_pcap();

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

	if (dump_to_pcap(ctx)) {
		__label__ try_file;
		struct stat stats;

		fmemset(&stats, 0, sizeof(stats));
		ret = stat(ctx->device_out, &stats);
		if (ret < 0) {
			ctx->dump_dir = 0;
			goto try_file;
		}

		ctx->dump_dir = S_ISDIR(stats.st_mode);
		if (ctx->dump_dir) {
			fd = begin_multi_pcap_file(ctx);
		} else {
		try_file:
			fd = begin_single_pcap_file(ctx);
		}
	}

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

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0)) {
		while (user_may_pull_from_rx_block((pbd = (void *)
				rx_ring.frames[it].iov_base))) {
			walk_t3_block(pbd, ctx, sock, &fd, &frame_count);

			kernel_may_pull_from_rx_block(pbd);
			it = (it + 1) % rx_ring.layout3.tp_block_nr;

			if (unlikely(sigint == 1))
				break;
		}

		poll(&rx_poll, 1, -1);
	}

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

	if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) {
		sock_rx_net_stats(sock, frame_count);

		printf("\r%12lu  sec, %lu usec in total\n",
		       diff.tv_sec, diff.tv_usec);
	} else {
		printf("\n\n");
		fflush(stdout);
	}

	bpf_release(&bpf_ops);
	dissector_cleanup_all();
	destroy_rx_ring(sock, &rx_ring);

	if (ctx->promiscuous)
		leave_promiscuous_mode(ctx->device_in, ifflags);

	if (ctx->rfraw)
		leave_rfmon_mac80211(ctx->device_trans, ctx->device_in);

	if (dump_to_pcap(ctx)) {
		if (ctx->dump_dir)
			finish_multi_pcap_file(ctx, fd);
		else
			finish_single_pcap_file(ctx, fd);
	}

	close(sock);
}
Exemple #19
0
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);
	}
}
Exemple #20
0
void curve25519_selftest(void)
{
	int i;
	unsigned char alicesk[32] = {
		0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d,
		0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45,
		0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
		0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a
	};
	unsigned char bobpk[32] = {
		0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4,
		0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37,
		0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d,
		0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f
	};
	unsigned char nonce[24] = {
		0x69, 0x69, 0x6e, 0xe9, 0x55, 0xb6, 0x2b, 0x73,
		0xcd, 0x62, 0xbd, 0xa8, 0x75, 0xfc, 0x73, 0xd6,
		0x82, 0x19, 0xe0, 0x03, 0x6b, 0x7a, 0x0b, 0x37
	};
	unsigned char m[163] = {
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0xbe, 0x07, 0x5f, 0xc5, 0x3c, 0x81, 0xf2, 0xd5,
		0xcf, 0x14, 0x13, 0x16, 0xeb, 0xeb, 0x0c, 0x7b,
		0x52, 0x28, 0xc5, 0x2a, 0x4c, 0x62, 0xcb, 0xd4,
		0x4b, 0x66, 0x84, 0x9b, 0x64, 0x24, 0x4f, 0xfc,
		0xe5, 0xec, 0xba, 0xaf, 0x33, 0xbd, 0x75, 0x1a,
		0x1a, 0xc7, 0x28, 0xd4, 0x5e, 0x6c, 0x61, 0x29,
		0x6c, 0xdc, 0x3c, 0x01, 0x23, 0x35, 0x61, 0xf4,
		0x1d, 0xb6, 0x6c, 0xce, 0x31, 0x4a, 0xdb, 0x31,
		0x0e, 0x3b, 0xe8, 0x25, 0x0c, 0x46, 0xf0, 0x6d,
		0xce, 0xea, 0x3a, 0x7f, 0xa1, 0x34, 0x80, 0x57,
		0xe2, 0xf6, 0x55, 0x6a, 0xd6, 0xb1, 0x31, 0x8a,
		0x02, 0x4a, 0x83, 0x8f, 0x21, 0xaf, 0x1f, 0xde,
		0x04, 0x89, 0x77, 0xeb, 0x48, 0xf5, 0x9f, 0xfd,
		0x49, 0x24, 0xca, 0x1c, 0x60, 0x90, 0x2e, 0x52,
		0xf0, 0xa0, 0x89, 0xbc, 0x76, 0x89, 0x70, 0x40,
		0xe0, 0x82, 0xf9, 0x37, 0x76, 0x38, 0x48, 0x64,
		0x5e, 0x07, 0x05
	};
	unsigned char c[163];
	unsigned char result[147] = {
		0xf3, 0xff, 0xc7, 0x70, 0x3f, 0x94, 0x00, 0xe5,
		0x2a, 0x7d, 0xfb, 0x4b, 0x3d, 0x33, 0x05, 0xd9,
		0x8e, 0x99, 0x3b, 0x9f, 0x48, 0x68, 0x12, 0x73,
		0xc2, 0x96, 0x50, 0xba, 0x32, 0xfc, 0x76, 0xce,
		0x48, 0x33, 0x2e, 0xa7, 0x16, 0x4d, 0x96, 0xa4,
		0x47, 0x6f, 0xb8, 0xc5, 0x31, 0xa1, 0x18, 0x6a,
		0xc0, 0xdf, 0xc1, 0x7c, 0x98, 0xdc, 0xe8, 0x7b,
		0x4d, 0xa7, 0xf0, 0x11, 0xec, 0x48, 0xc9, 0x72,
		0x71, 0xd2, 0xc2, 0x0f, 0x9b, 0x92, 0x8f, 0xe2,
		0x27, 0x0d, 0x6f, 0xb8, 0x63, 0xd5, 0x17, 0x38,
		0xb4, 0x8e, 0xee, 0xe3, 0x14, 0xa7, 0xcc, 0x8a,
		0xb9, 0x32, 0x16, 0x45, 0x48, 0xe5, 0x26, 0xae,
		0x90, 0x22, 0x43, 0x68, 0x51, 0x7a, 0xcf, 0xea,
		0xbd, 0x6b, 0xb3, 0x73, 0x2b, 0xc0, 0xe9, 0xda,
		0x99, 0x83, 0x2b, 0x61, 0xca, 0x01, 0xb6, 0xde,
		0x56, 0x24, 0x4a, 0x9e, 0x88, 0xd5, 0xf9, 0xb3,
		0x79, 0x73, 0xf6, 0x22, 0xa4, 0x3d, 0x14, 0xa6,
		0x59, 0x9b, 0x1f, 0x65, 0x4c, 0xb4, 0x5a, 0x74,
		0xe3, 0x55, 0xa5
	};

	bug_on(NONCE_LENGTH != 16);

	crypto_box_curve25519xsalsa20poly1305(c, m, 163, nonce, bobpk, alicesk);

	for (i = 16; i < 163; ++i) {
		if (c[i] != result[i - 16])
			panic("Crypto selftest failed! :-(\n");
	}
}
Exemple #21
0
static void pcap_to_xmit(struct ctx *ctx)
{
	__label__ out;
	uint8_t *out = NULL;
	int irq, ifindex, fd = 0, ret;
	unsigned int size, it = 0;
	unsigned long trunced = 0;
	struct ring tx_ring;
	struct frame_map *hdr;
	struct sock_fprog bpf_ops;
	struct timeval start, end, diff;
	pcap_pkthdr_t phdr;

	if (!device_up_and_running(ctx->device_out) && !ctx->rfraw)
		panic("Device not up and running!\n");

	bug_on(!__pcap_io);

	tx_sock = pf_socket();

	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(&tx_ring, 0, sizeof(tx_ring));
	fmemset(&bpf_ops, 0, sizeof(bpf_ops));

	if (ctx->rfraw) {
		ctx->device_trans = xstrdup(ctx->device_out);
		xfree(ctx->device_out);

		enter_rfmon_mac80211(ctx->device_trans, &ctx->device_out);
		if (ctx->link_type != LINKTYPE_IEEE802_11)
			panic("Wrong linktype of pcap!\n");
	}

	ifindex = device_ifindex(ctx->device_out);

	size = ring_size(ctx->device_out, ctx->reserve_size);

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

	set_packet_loss_discard(tx_sock);

	setup_tx_ring_layout(tx_sock, &tx_ring, size, ctx->jumbo);
	create_tx_ring(tx_sock, &tx_ring, ctx->verbose);
	mmap_tx_ring(tx_sock, &tx_ring);
	alloc_tx_ring_frames(tx_sock, &tx_ring);
	bind_tx_ring(tx_sock, &tx_ring, ifindex);

	dissector_init_all(ctx->print_mode);

	if (ctx->cpu >= 0 && ifindex > 0) {
		irq = device_irq_number(ctx->device_out);
		device_set_irq_affinity(irq, ctx->cpu);

		if (ctx->verbose)
			printf("IRQ: %s:%d > CPU%d\n",
			       ctx->device_out, irq, ctx->cpu);
	}

	if (ctx->kpull)
		interval = ctx->kpull;

	set_itimer_interval_value(&itimer, 0, interval);
	setitimer(ITIMER_REAL, &itimer, NULL); 

	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)) {
		while (user_may_pull_from_tx(tx_ring.frames[it].iov_base)) {
			hdr = tx_ring.frames[it].iov_base;
			out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);

			do {
				ret = __pcap_io->read_pcap(fd, &phdr, ctx->magic, out,
							   ring_frame_size(&tx_ring));
				if (unlikely(ret <= 0))
					goto out;

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

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

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

			show_frame_hdr(hdr, ctx->print_mode);

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

			kernel_may_pull_from_tx(&hdr->tp_h);

			it++;
			if (it >= tx_ring.layout.tp_frame_nr)
				it = 0;

			if (unlikely(sigint == 1))
				break;

			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);

	timer_purge();

	bpf_release(&bpf_ops);

	dissector_cleanup_all();
	destroy_tx_ring(tx_sock, &tx_ring);

	if (ctx->rfraw)
		leave_rfmon_mac80211(ctx->device_trans, ctx->device_out);

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

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

	close(tx_sock);

	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);
}
Exemple #22
0
static void recv_only_or_dump(struct ctx *ctx)
{
	short ifflags = 0;
	int sock, ifindex, fd = 0, ret;
	size_t size;
	unsigned int it = 0;
	struct ring rx_ring;
	struct pollfd rx_poll;
	struct sock_fprog bpf_ops;
	struct timeval start, end, diff;
	bool is_v3 = is_defined(HAVE_TPACKET3);

	sock = pf_socket_type(ctx->link_type);

	ifindex = device_ifindex(ctx->device_in);
	size = ring_size(ctx->device_in, ctx->reserve_size);

	enable_kernel_bpf_jit_compiler();

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

	if (ctx->hwtimestamp) {
		ret = set_sockopt_hwtimestamp(sock, ctx->device_in);
		if (ret == 0 && ctx->verbose)
			printf("HW timestamping enabled\n");
	}

	ring_rx_setup(&rx_ring, sock, size, ifindex, &rx_poll, is_v3, true,
		      ctx->verbose, ctx->fanout_group, ctx->fanout_type);

	dissector_init_all(ctx->print_mode);

	if (ctx->cpu >= 0 && ifindex > 0) {
		int irq = device_irq_number(ctx->device_in);
		device_set_irq_affinity(irq, ctx->cpu);

		if (ctx->verbose)
			printf("IRQ: %s:%d > CPU%d\n",
			       ctx->device_in, irq, ctx->cpu);
	}

	if (ctx->promiscuous)
		ifflags = device_enter_promiscuous_mode(ctx->device_in);

	if (dump_to_pcap(ctx) && __pcap_io->init_once_pcap)
		__pcap_io->init_once_pcap(true);

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

	if (dump_to_pcap(ctx)) {
		struct stat stats;

		ret = stat(ctx->device_out, &stats);
		if (ret < 0)
			ctx->dump_dir = 0;
		else
			ctx->dump_dir = S_ISDIR(stats.st_mode);

		if (ctx->dump_dir)
			fd = begin_multi_pcap_file(ctx);
		else
			fd = begin_single_pcap_file(ctx);
	}

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

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0)) {
#ifdef HAVE_TPACKET3
		struct block_desc *pbd;

		while (user_may_pull_from_rx_block((pbd = rx_ring.frames[it].iov_base))) {
			walk_t3_block(pbd, ctx, sock, &fd);

			kernel_may_pull_from_rx_block(pbd);
			it = (it + 1) % rx_ring.layout3.tp_block_nr;

			if (unlikely(sigint == 1))
				break;
		}
#else
		while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
			struct frame_map *hdr = rx_ring.frames[it].iov_base;
			uint8_t *packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
			pcap_pkthdr_t phdr;

			if (ctx->packet_type != -1)
				if (ctx->packet_type != hdr->s_ll.sll_pkttype)
					goto next;

			ctx->pkts_seen++;

			if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) {
				/* XXX: silently ignore for now. We used to
				 * report them with dump_rx_stats()  */
				goto next;
			}

			if (dump_to_pcap(ctx)) {
				tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic);

				ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet,
							    pcap_get_length(&phdr, ctx->magic));
				if (unlikely(ret != (int) pcap_get_total_length(&phdr, ctx->magic)))
					panic("Write error to pcap!\n");
			}

			show_frame_hdr(packet, hdr->tp_h.tp_snaplen,
				       ctx->link_type, hdr, ctx->print_mode,
				       ctx->pkts_seen);

			dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
					      ctx->link_type, ctx->print_mode,
					      &hdr->s_ll);

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

next:
			kernel_may_pull_from_rx(&hdr->tp_h);
			it = (it + 1) % rx_ring.layout.tp_frame_nr;

			if (unlikely(sigint == 1))
				break;

			update_pcap_next_dump(ctx, hdr->tp_h.tp_snaplen, &fd,
					      sock, is_v3);
		}
#endif /* HAVE_TPACKET3 */

		ret = poll(&rx_poll, 1, -1);
		if (unlikely(ret < 0)) {
			if (errno != EINTR)
				panic("Poll failed!\n");
		}
	}

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

	dump_rx_stats(ctx, sock, is_v3);
	printf("\r%12lu  sec, %lu usec in total\n",
			diff.tv_sec, diff.tv_usec);

	bpf_release(&bpf_ops);
	dissector_cleanup_all();
	destroy_rx_ring(sock, &rx_ring);

	if (ctx->promiscuous)
		device_leave_promiscuous_mode(ctx->device_in, ifflags);

	if (ctx->rfraw)
		leave_rfmon_mac80211(ctx->device_in);

	if (dump_to_pcap(ctx)) {
		if (ctx->dump_dir)
			finish_multi_pcap_file(ctx, fd);
		else
			finish_single_pcap_file(ctx, fd);
	}

	close(sock);
}
Exemple #23
0
/* Processes the current directive.
 * If the encoder returns an error, a message including current file and
 * line number together with the pt error string is printed on stderr.
 *
 * Returns 0 on success; a negative enum errcode otherwise.
 * Returns -err_internal if @p or @e is the NULL pointer.
 * Returns -err_parse_missing_directive if there was a pt directive marker,
 * but no directive.
 * Returns -stop_process if the .exp directive was encountered.
 * Returns -err_pt_lib if the pt encoder returned an error.
 * Returns -err_parse if a general parsing error was encountered.
 * Returns -err_parse_unknown_directive if there was an unknown pt directive.
 */
static int p_process(struct parser *p, struct pt_encoder *e)
{
	int bytes_written;
	int errcode;
	char *directive, *payload, *pt_label_name, *tmp;
	struct pt_directive *pd;
	struct pt_packet packet;

	if (bug_on(!p))
		return -err_internal;

	if (bug_on(!e))
		return -err_internal;

	pd = p->pd;
	if (!pd)
		return -err_internal;

	directive = pd->name;
	payload = pd->payload;

	pt_label_name = NULL;
	bytes_written = 0;
	errcode = 0;

	/* find a label name.  */
	tmp = strchr(directive, ':');
	if (tmp) {
		uint64_t x;

		pt_label_name = directive;
		directive = tmp+1;
		*tmp = '\0';

		/* ignore whitespace between label and directive. */
		while (isspace(*directive))
			directive += 1;

		/* if we can lookup a yasm label with the same name, the
		 * current pt directive label is invalid.  */
		errcode = yasm_lookup_label(p->y, &x, pt_label_name);
		if (errcode == 0)
			errcode = -err_label_not_unique;

		if (errcode != -err_no_label)
			return yasm_print_err(p->y, "label lookup",
					      errcode);

		/* if we can lookup a pt directive label with the same
		 * name, the current pt directive label is invalid.  */
		errcode = l_lookup(p->pt_labels, &x, pt_label_name);
		if (errcode == 0)
			errcode = -err_label_not_unique;

		if (errcode != -err_no_label)
			return yasm_print_err(p->y, "label lookup",
					      -err_label_not_unique);
	}

	/* now try to match the directive string and call the
	 * corresponding function that parses the payload and emits an
	 * according packet.
	 */
	if (strcmp(directive, "") == 0)
		return yasm_print_err(p->y, "invalid syntax",
				      -err_parse_missing_directive);
	else if (strcmp(directive, ".exp") == 0) {
		/* this is the end of processing pt directives, so we
		 * add a p_last label to the pt directive labels.
		 */
		errcode = l_append(p->pt_labels, "eos", p->pt_bytes_written);
		if (errcode < 0)
			return yasm_print_err(p->y, "append label", errcode);

		return -stop_process;
	}

	if (strcmp(directive, "psb") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "psb: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_psb;
	} else if (strcmp(directive, "psbend") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "psbend: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_psbend;
	} else if (strcmp(directive, "pad") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "pad: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_pad;
	} else if (strcmp(directive, "ovf") == 0) {
		errcode = parse_empty(payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "ovf: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_ovf;
	} else if (strcmp(directive, "tnt") == 0) {
		errcode = parse_tnt(&packet.payload.tnt.payload,
				    &packet.payload.tnt.bit_size, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tnt: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tnt_8;
	} else if (strcmp(directive, "tnt64") == 0) {
		errcode = parse_tnt(&packet.payload.tnt.payload,
				    &packet.payload.tnt.bit_size, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tnt64: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tnt_64;
	} else if (strcmp(directive, "tip") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tip;
	} else if (strcmp(directive, "tip.pge") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip.pge: parsing failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_tip_pge;
	} else if (strcmp(directive, "tip.pgd") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tip.pgd: parsing failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_tip_pgd;
	} else if (strcmp(directive, "fup") == 0) {
		errcode = parse_ip(p, &packet.payload.ip.ip,
				   &packet.payload.ip.ipc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "fup: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_fup;
	} else if (strcmp(directive, "mode.exec") == 0) {
		if (strcmp(payload, "16bit") == 0) {
			packet.payload.mode.bits.exec.csl = 0;
			packet.payload.mode.bits.exec.csd = 0;
		} else if (strcmp(payload, "64bit") == 0) {
			packet.payload.mode.bits.exec.csl = 1;
			packet.payload.mode.bits.exec.csd = 0;
		} else if (strcmp(payload, "32bit") == 0) {
			packet.payload.mode.bits.exec.csl = 0;
			packet.payload.mode.bits.exec.csd = 1;
		} else {
			errcode = yasm_print_err(p->y,
						 "mode.exec: argument must be one of \"16bit\", \"64bit\" or \"32bit\"",
						 -err_parse);
			goto error;
		}
		packet.payload.mode.leaf = pt_mol_exec;
		packet.type = ppt_mode;
	} else if (strcmp(directive, "mode.tsx") == 0) {
		if (strcmp(payload, "begin") == 0) {
			packet.payload.mode.bits.tsx.intx = 1;
			packet.payload.mode.bits.tsx.abrt = 0;
		} else if (strcmp(payload, "abort") == 0) {
			packet.payload.mode.bits.tsx.intx = 0;
			packet.payload.mode.bits.tsx.abrt = 1;
		} else if (strcmp(payload, "commit") == 0) {
			packet.payload.mode.bits.tsx.intx = 0;
			packet.payload.mode.bits.tsx.abrt = 0;
		} else {
			errcode = yasm_print_err(p->y,
						 "mode.tsx: argument must be one of \"begin\", \"abort\" or \"commit\"",
						 -err_parse);
			goto error;
		}
		packet.payload.mode.leaf = pt_mol_tsx;
		packet.type = ppt_mode;
	} else if (strcmp(directive, "pip") == 0) {
		errcode = parse_uint64(&packet.payload.pip.cr3, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "pip: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_pip;
	} else if (strcmp(directive, "tsc") == 0) {
		errcode = parse_uint64(&packet.payload.tsc.tsc, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "tsc: parsing failed", errcode);
			goto error;
		}
		packet.type = ppt_tsc;
	} else if (strcmp(directive, "cbr") == 0) {
		errcode = parse_uint8(&packet.payload.cbr.ratio, payload);
		if (errcode < 0) {
			yasm_print_err(p->y, "cbr: parsing cbr failed",
				       errcode);
			goto error;
		}
		packet.type = ppt_cbr;
	} else {
		errcode = yasm_print_err(p->y, "invalid syntax",
					 -err_parse_unknown_directive);
		goto error;
	}

	bytes_written = pt_enc_next(e, &packet);
	if (bytes_written < 0) {
		const char *errstr, *format;
		char *msg;
		size_t n;

		errstr = pt_errstr(pt_errcode(bytes_written));
		format = "encoder error in directive %s (status %s)";
		/* the length of format includes the "%s" (-2)
		 * characters, we add errstr (+-0) and then we need
		 * space for a terminating null-byte (+1).
		 */
		n = strlen(format)-4 + strlen(directive) + strlen(errstr) + 1;

		msg = malloc(n);
		if (!msg)
			errcode = yasm_print_err(p->y,
				       "encoder error not enough memory to show error code",
				       -err_pt_lib);
		else {
			sprintf(msg, format, directive, errstr);
			errcode = yasm_print_err(p->y, msg, -err_pt_lib);
			free(msg);
		}
	} else {
		if (pt_label_name) {
			errcode = l_append(p->pt_labels, pt_label_name,
					   p->pt_bytes_written);
			if (errcode < 0)
				goto error;
		}
		p->pt_bytes_written += bytes_written;
	}

error:
	if (errcode < 0)
		bytes_written = errcode;
	return bytes_written;
}
Exemple #24
0
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);
	}
}
Exemple #25
0
/* Generates the content of the .exp file by printing all lines with
 * everything up to and including the first comment semicolon removed.
 *
 * Returns 0 on success; a negative enum errcode otherwise.
 * Returns -err_internal if @p is the NULL pointer.
 * Returns -err_file_write if the .exp file could not be fully written.
 */
static int p_gen_expfile(struct parser *p)
{
	int errcode;
	enum { slen = 1024 };
	char s[slen];
	struct pt_directive *pd;
	char *filename;
	FILE *f;

	if (bug_on(!p))
		return -err_internal;

	pd = p->pd;

	/* the directive in the current line must be the .exp directive.  */
	errcode = yasm_pd_parse(p->y, pd);
	if (bug_on(errcode < 0))
		return -err_internal;

	if (bug_on(strcmp(pd->name, ".exp") != 0))
		return -err_internal;

	filename = expfilename(p, pd->payload);
	if (!filename)
		return -err_no_mem;
	f = fopen(filename, "w");
	if (!f) {
		free(filename);
		return -err_file_open;
	}

	for (;;) {
		int i;
		char *line, *comment;

		errcode = yasm_next_line(p->y, s, slen);
		if (errcode < 0)
			break;

		errcode = yasm_pd_parse(p->y, pd);
		if (errcode < 0 && errcode != -err_no_directive)
			break;

		if (errcode == 0 && strcmp(pd->name, ".exp") == 0) {
			fclose(f);
			printf("%s\n", filename);
			free(filename);
			filename = expfilename(p, pd->payload);
			if (!filename)
				return -err_no_mem;
			f = fopen(filename, "w");
			if (!f) {
				free(filename);
				return -err_file_open;
			}
			continue;
		}

		line = strchr(s, ';');
		if (!line)
			continue;

		line += 1;

		comment = strchr(line, '#');
		if (comment)
			*comment = '\0';

		/* remove trailing spaces.  */
		for (i = (int) strlen(line)-1; i >= 0 && isspace(line[i]); i--)
			line[i] = '\0';

		for (;;) {
			char *tmp, label[256];
			uint64_t addr;
			int i, zero_padding, qmark_padding, qmark_size, status;

			zero_padding = 0;
			qmark_padding = 0;
			qmark_size = 0;

			/* find the label character in the string.
			 * if there is no label character, we just print
			 * the rest of the line and end.
			 */
			tmp = strchr(line, '%');
			if (!tmp) {
				if (fprintf(f, "%s", line) < 0) {
					errcode = -err_file_write;
					goto error;
				}
				break;
			}

			/* make the label character a null byte and
			 * print the first portion, which does not
			 * belong to the label into the file.
			 */
			*tmp = '\0';
			if (fprintf(f, "%s", line) < 0) {
				errcode = -err_file_write;
				goto error;
			}

			/* test if there is a valid label name after the %.  */
			line = tmp+1;
			if (*line == '\0' || isspace(*line)) {
				errcode = -err_no_label;
				goto error;
			}

			/* check if zero padding is requested.  */
			if (*line == '0') {
				zero_padding = 1;
				line += 1;
			}
			/* chek if ? padding is requested.  */
			else if (*line == '?') {
				qmark_padding = 1;
				zero_padding = 1;
				qmark_size = 0;
				line += 1;
			}

			/* advance i to the first non alpha-numeric
			 * character. all characters everything from
			 * line[0] to line[i-1] belongs to the label
			 * name.
			 */
			for (i = 0; islabelchar(line[i]); i++)
				;

			if (i > 255) {
				errcode = -err_label_name;
				goto error;
			}
			strncpy(label, line, i);
			label[i] = '\0';

			/* advance to next character.  */
			line = &line[i];

			/* lookup the label name and print it to the
			 * output file.
			 */
			errcode = yasm_lookup_label(p->y, &addr, label);
			if (errcode < 0) {
				errcode = l_lookup(p->pt_labels, &addr, label);
				if (errcode < 0)
					goto error;

				if (zero_padding)
					status = fprintf(f, "%016" PRIx64, addr);
				else
					status = fprintf(f, "%" PRIx64, addr);

				if (status < 0) {
					errcode = -err_file_write;
					goto error;
				}

				continue;
			}

			/* check if masking is requested.  */
			if (*line == '.') {
				char *endptr;
				long int n;

				line += 1;

				n = strtol(line, &endptr, 0);
				/* check if strtol made progress and
				 * stops on a space or null byte.
				 * otherwise the int could not be
				 * parsed.
				 */
				if (line == endptr ||
				    (*endptr != '\0' && !isspace(*endptr)
				     && !ispunct(*endptr))) {
					errcode = -err_parse_int;
					goto error;
				}
				addr &= (1 << (n << 3)) - 1;
				line = endptr;

				qmark_size = 8 - n;
			}

			if (qmark_padding) {
				int i;

				status = fprintf(f, "0x");
				if (status < 0) {
					errcode = -err_file_write;
					goto error;
				}

				for (i = 0; i < qmark_size; ++i) {
					status = fprintf(f, "??");
					if (status < 0) {
						errcode = -err_file_write;
						goto error;
					}
				}

				for (; i < 8; ++i) {
					uint8_t byte;

					byte = (uint8_t)(addr >> ((7 - i) * 8));

					status = fprintf(f, "%02" PRIx8, byte);
					if (status < 0) {
						errcode = -err_file_write;
						goto error;
					}
				}
			} else if (zero_padding)
				status = fprintf(f, "0x%016" PRIx64, addr);
			else
				status = fprintf(f, "0x%" PRIx64, addr);

			if (status < 0) {
				errcode = -err_file_write;
				goto error;
			}

		}

		if (fprintf(f, "\n") < 0) {
			errcode = -err_file_write;
			goto error;
		}
	}
Exemple #26
0
int run(const char *file, char *const argv[])
{
	int errcode;

	int i;
	size_t size;
	char *args;

	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	DWORD exit_code;

	DWORD dwret;
	BOOL bret;


	errcode = 0;

	if (bug_on(!file)) {
		errcode = -err_internal;
		goto out;
	}

	if (bug_on(!argv)) {
		errcode = -err_internal;
		goto out;
	}


	/* calculate length of command line - this is the cumulative length of
	 * all arguments, plus two quotation marks (to make it quoted strings
	 * and allow for spaces in file/path names), plus a space after each
	 * arguments as delimiter (after the last arguments it's a terminating
	 * zero-byte instead of the space).	 *
	 */
	size = 0;
	for (i = 0; argv[i]; ++i)
		size += strlen(argv[i]) + 3;

	/* allocate command line string */
	args = calloc(size, 1);
	if (!args)
		return -err_no_mem;

	/* construct command line string, putting quotation marks
	 * around every argument of the vector and a space after it
	 */
	size = 0;
	for (i = 0; argv[i]; ++i) {
		args[size++] = '"';
		strcpy(args + size, argv[i]);
		size += strlen(argv[i]);
		args[size++] = '"';
		args[size++] = ' ';
	}
	/* transform last space into a terminating zero-byte and fix up size */
	args[--size] = '\0';


	/* initialize process/startup info */
	memset(&pi, 0, sizeof(pi));
	memset(&si, 0, sizeof(si));
	si.cb = sizeof(si);

	/* create process - since the first parameter is NULL, the
	 * second parameter represents a command as it would behave
	 * on a command shell
	 */
	bret = CreateProcess(NULL, args,
			     NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
	if (!bret) {
		errcode = -err_other;
		goto out_args;
	}

	dwret = WaitForSingleObject(pi.hProcess, INFINITE);
	if (dwret == WAIT_FAILED) {
		errcode = -err_other;
		goto out_handles;
	}

	bret = GetExitCodeProcess(pi.hProcess, &exit_code);
	if (!bret) {
		errcode = -err_other;
		goto out_handles;
	}

	if (exit_code != 0)
		errcode = -err_run;


out_handles:
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
out_args:
	free(args);
out:
	return errcode;
}
Exemple #27
0
static void recv_only_or_dump(struct ctx *ctx)
{
	uint8_t *packet;
	short ifflags = 0;
	int sock, irq, ifindex, fd = 0, ret;
	unsigned int size, it = 0;
	unsigned long frame_count = 0, skipped = 0;
	struct ring rx_ring;
	struct pollfd rx_poll;
	struct frame_map *hdr;
	struct sock_fprog bpf_ops;
	struct timeval start, end, diff;
	pcap_pkthdr_t phdr;

	if (!device_up_and_running(ctx->device_in) && !ctx->rfraw)
		panic("Device not up and running!\n");

	sock = pf_socket();

	if (ctx->rfraw) {
		ctx->device_trans = xstrdup(ctx->device_in);
		xfree(ctx->device_in);

		enter_rfmon_mac80211(ctx->device_trans, &ctx->device_in);
		ctx->link_type = LINKTYPE_IEEE802_11;
	}

	fmemset(&rx_ring, 0, sizeof(rx_ring));
	fmemset(&rx_poll, 0, sizeof(rx_poll));
	fmemset(&bpf_ops, 0, sizeof(bpf_ops));

	ifindex = device_ifindex(ctx->device_in);

	size = ring_size(ctx->device_in, ctx->reserve_size);

	enable_kernel_bpf_jit_compiler();

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

	set_sockopt_hwtimestamp(sock, ctx->device_in);

	setup_rx_ring_layout(sock, &rx_ring, size, ctx->jumbo);
	create_rx_ring(sock, &rx_ring, ctx->verbose);
	mmap_rx_ring(sock, &rx_ring);
	alloc_rx_ring_frames(&rx_ring);
	bind_rx_ring(sock, &rx_ring, ifindex);

	prepare_polling(sock, &rx_poll);
	dissector_init_all(ctx->print_mode);

	if (ctx->cpu >= 0 && ifindex > 0) {
		irq = device_irq_number(ctx->device_in);
		device_bind_irq_to_cpu(irq, ctx->cpu);

		if (ctx->verbose)
			printf("IRQ: %s:%d > CPU%d\n",
			       ctx->device_in, irq, ctx->cpu);
	}

	if (ctx->promiscuous)
		ifflags = enter_promiscuous_mode(ctx->device_in);

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

	if (dump_to_pcap(ctx)) {
		__label__ try_file;
		struct stat stats;

		fmemset(&stats, 0, sizeof(stats));
		ret = stat(ctx->device_out, &stats);
		if (ret < 0) {
			ctx->dump_dir = 0;
			goto try_file;
		}

		ctx->dump_dir = S_ISDIR(stats.st_mode);
		if (ctx->dump_dir) {
			fd = begin_multi_pcap_file(ctx);
		} else {
		try_file:
			fd = begin_single_pcap_file(ctx);
		}
	}

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

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0)) {
		while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
			__label__ next;

			hdr = rx_ring.frames[it].iov_base;
			packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
			frame_count++;

			if (ctx->packet_type != -1)
				if (ctx->packet_type != hdr->s_ll.sll_pkttype)
					goto next;

			if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) {
				skipped++;
				goto next;
			}

			if (dump_to_pcap(ctx)) {
				tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic);

				ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet,
							    pcap_get_length(&phdr, ctx->magic));
				if (unlikely(ret != pcap_get_total_length(&phdr, ctx->magic)))
					panic("Write error to pcap!\n");
			}

			show_frame_hdr(hdr, ctx->print_mode);

			dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
					      ctx->link_type, ctx->print_mode);

			if (frame_count_max != 0) {
				if (frame_count >= frame_count_max) {
					sigint = 1;
					break;
				}
			}

			next:

			kernel_may_pull_from_rx(&hdr->tp_h);

			it++;
			if (it >= rx_ring.layout.tp_frame_nr)
				it = 0;

			if (unlikely(sigint == 1))
				break;

			if (dump_to_pcap(ctx)) {
				if (ctx->dump_mode == DUMP_INTERVAL_SIZE) {
					interval += hdr->tp_h.tp_snaplen;

					if (interval > ctx->dump_interval) {
						next_dump = true;
						interval = 0;
					}
				}

				if (next_dump) {
					fd = next_multi_pcap_file(ctx, fd);
					next_dump = false;

					if (ctx->verbose)
						print_pcap_file_stats(sock, ctx, skipped);
				}
			}
		}

		poll(&rx_poll, 1, -1);
	}

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

	if (!(ctx->dump_dir && ctx->print_mode == PRINT_NONE)) {
		sock_print_net_stats(sock, skipped);

		printf("\r%12lu  sec, %lu usec in total\n",
		       diff.tv_sec, diff.tv_usec);
	} else {
		printf("\n\n");
		fflush(stdout);
	}

	bpf_release(&bpf_ops);
	dissector_cleanup_all();
	destroy_rx_ring(sock, &rx_ring);

	if (ctx->promiscuous)
		leave_promiscuous_mode(ctx->device_in, ifflags);

	if (ctx->rfraw)
		leave_rfmon_mac80211(ctx->device_trans, ctx->device_in);

	if (dump_to_pcap(ctx)) {
		if (ctx->dump_dir)
			finish_multi_pcap_file(ctx, fd);
		else
			finish_single_pcap_file(ctx, fd);
	}

	close(sock);
}
Exemple #28
0
static void xmit_slowpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned long orig_num)
{
	int ret, icmp_sock = -1;
	unsigned long num = 1, i = 0;
	struct timeval start, end, diff;
	unsigned long long tx_bytes = 0, tx_packets = 0;
	struct packet_dyn *pktd;
	struct sockaddr_ll saddr = {
		.sll_family = PF_PACKET,
		.sll_halen = ETH_ALEN,
		.sll_ifindex = device_ifindex(ctx->device),
	};

	if (ctx->num > 0)
		num = ctx->num;
	if (ctx->num == 0 && orig_num > 0)
		num = 0;

	if (ctx->smoke_test)
		icmp_sock = xmit_smoke_setup(ctx);

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

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0 && num > 0 && plen > 0)) {
		pktd = &packet_dyn[i];
		if (pktd->clen + pktd->rlen + pktd->slen) {
			apply_counter(i);
			apply_randomizer(i);
			apply_csum16(i);
		}
retry:
		ret = sendto(sock, packets[i].payload, packets[i].len, 0,
			     (struct sockaddr *) &saddr, sizeof(saddr));
		if (unlikely(ret < 0)) {
			if (errno == ENOBUFS) {
				sched_yield();
				goto retry;
			}
			if (ctx->smoke_test)
				panic("Sendto error: %s!\n", strerror(errno));
		}

		tx_bytes += packets[i].len;
		tx_packets++;

		if (ctx->smoke_test) {
			ret = xmit_smoke_probe(icmp_sock, ctx);
			if (unlikely(ret < 0)) {
				printf("%sSmoke test alert:%s\n", colorize_start(bold), colorize_end());
				printf("  Remote host seems to be unresponsive to ICMP probes!\n");
				printf("  Last instance was packet%lu, seed:%u, trafgen snippet:\n\n",
				       i, seed);

				dump_trafgen_snippet(packets[i].payload, packets[i].len);
				break;
			}
		}

		if (!ctx->rand) {
			i++;
			if (i >= plen)
				i = 0;
		} else
			i = rand() % plen;

		if (ctx->num > 0)
			num--;

		if ((ctx->gap.tv_sec | ctx->gap.tv_nsec) > 0)
			nanosleep(&ctx->gap, NULL);
	}

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

	if (ctx->smoke_test)
		close(icmp_sock);

	stats[cpu].tx_packets = tx_packets;
	stats[cpu].tx_bytes = tx_bytes;
	stats[cpu].tv_sec = diff.tv_sec;
	stats[cpu].tv_usec = diff.tv_usec;

	stats[cpu].state |= CPU_STATS_STATE_RES;
}

static void xmit_fastpath_or_die(struct ctx *ctx, unsigned int cpu, unsigned long orig_num)
{
	int ifindex = device_ifindex(ctx->device);
	uint8_t *out = NULL;
	unsigned int it = 0;
	unsigned long num = 1, i = 0;
	size_t size = ring_size(ctx->device, ctx->reserve_size);
	struct ring tx_ring;
	struct frame_map *hdr;
	struct timeval start, end, diff;
	struct packet_dyn *pktd;
	unsigned long long tx_bytes = 0, tx_packets = 0;

	set_sock_prio(sock, 512);

	ring_tx_setup(&tx_ring, sock, size, ifindex, ctx->jumbo_support, ctx->verbose);

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

	if (ctx->num > 0)
		num = ctx->num;
	if (ctx->num == 0 && orig_num > 0)
		num = 0;

	bug_on(gettimeofday(&start, NULL));

	while (likely(sigint == 0 && num > 0 && plen > 0)) {
		if (!user_may_pull_from_tx(tx_ring.frames[it].iov_base)) {
			int ret = pull_and_flush_tx_ring(sock);
			if (unlikely(ret < 0)) {
				/* We could hit EBADF if the socket has been closed before
				 * the timer was triggered.
				 */
				if (errno != EBADF && errno != ENOBUFS)
					panic("Flushing TX_RING failed: %s!\n", strerror(errno));
			}

			continue;
		}

		hdr = tx_ring.frames[it].iov_base;
		out = ((uint8_t *) hdr) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);

		hdr->tp_h.tp_snaplen = packets[i].len;
		hdr->tp_h.tp_len = packets[i].len;

		pktd = &packet_dyn[i];
		if (pktd->clen + pktd->rlen + pktd->slen) {
			apply_counter(i);
			apply_randomizer(i);
			apply_csum16(i);
		}

		fmemcpy(out, packets[i].payload, packets[i].len);

		tx_bytes += packets[i].len;
		tx_packets++;

		if (!ctx->rand) {
			i++;
			if (i >= plen)
				i = 0;
		} else
			i = rand() % plen;

		kernel_may_pull_from_tx(&hdr->tp_h);

		it++;
		if (it >= tx_ring.layout.tp_frame_nr)
			it = 0;

		if (ctx->num > 0)
			num--;
	}

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

	pull_and_flush_tx_ring_wait(sock);
	destroy_tx_ring(sock, &tx_ring);

	stats[cpu].tx_packets = tx_packets;
	stats[cpu].tx_bytes = tx_bytes;
	stats[cpu].tv_sec = diff.tv_sec;
	stats[cpu].tv_usec = diff.tv_usec;

	stats[cpu].state |= CPU_STATS_STATE_RES;
}
Exemple #29
0
int main(int argc, char **argv)
{
	char *ptr;
	int c, i, j, cpu_tmp, opt_index, ops_touched = 0, vals[4] = {0};
	bool prio_high = false, setsockmem = true;
	void (*main_loop)(struct ctx *ctx) = NULL;
	struct ctx ctx;

	init_ctx(&ctx);
	srand(time(NULL));

	while ((c = getopt_long(argc, argv, short_options, long_options,
				&opt_index)) != EOF) {
		switch (c) {
		case 'd':
		case 'i':
			ctx.device_in = xstrdup(optarg);
			break;
		case 'o':
			ctx.device_out = xstrdup(optarg);
			break;
		case 'P':
			ctx.prefix = xstrdup(optarg);
			break;
		case 'R':
			ctx.rfraw = 1;
			break;
		case 'r':
			ctx.randomize = true;
			break;
		case 'J':
			ctx.jumbo = true;
			break;
		case 'T':
			ctx.magic = (uint32_t) strtoul(optarg, NULL, 0);
			pcap_check_magic(ctx.magic);
			break;
		case 'f':
			ctx.filter = xstrdup(optarg);
			break;
		case 'M':
			ctx.promiscuous = false;
			break;
		case 'N':
			ctx.hwtimestamp = false;
			break;
		case 'A':
			setsockmem = false;
			break;
		case 'u':
			ctx.uid = strtoul(optarg, NULL, 0);
			ctx.enforce = true;
			break;
		case 'g':
			ctx.gid = strtoul(optarg, NULL, 0);
			ctx.enforce = true;
			break;
		case 'C':
			ctx.fanout_group = strtoul(optarg, NULL, 0);
			if (ctx.fanout_group == 0)
				panic("Non-zero fanout group id required!\n");
			break;
		case 'K':
			if (!strncmp(optarg, "hash", strlen("hash")))
				ctx.fanout_type = PACKET_FANOUT_HASH;
			else if (!strncmp(optarg, "lb", strlen("lb")) ||
				 !strncmp(optarg, "rr", strlen("rr")))
				ctx.fanout_type = PACKET_FANOUT_LB;
			else if (!strncmp(optarg, "cpu", strlen("cpu")))
				ctx.fanout_type = PACKET_FANOUT_CPU;
			else if (!strncmp(optarg, "rnd", strlen("rnd")))
				ctx.fanout_type = PACKET_FANOUT_RND;
			else if (!strncmp(optarg, "roll", strlen("roll")))
				ctx.fanout_type = PACKET_FANOUT_ROLLOVER;
			else if (!strncmp(optarg, "qm", strlen("qm")))
				ctx.fanout_type = PACKET_FANOUT_QM;
			else
				panic("Unknown fanout type!\n");
			break;
		case 'L':
			if (!strncmp(optarg, "defrag", strlen("defrag")))
				ctx.fanout_type |= PACKET_FANOUT_FLAG_DEFRAG;
			else if (!strncmp(optarg, "roll", strlen("roll")))
				ctx.fanout_type |= PACKET_FANOUT_FLAG_ROLLOVER;
			else
				panic("Unknown fanout option!\n");
			break;
		case 't':
			if (!strncmp(optarg, "host", strlen("host")))
				ctx.packet_type = PACKET_HOST;
			else if (!strncmp(optarg, "broadcast", strlen("broadcast")))
				ctx.packet_type = PACKET_BROADCAST;
			else if (!strncmp(optarg, "multicast", strlen("multicast")))
				ctx.packet_type = PACKET_MULTICAST;
			else if (!strncmp(optarg, "others", strlen("others")))
				ctx.packet_type = PACKET_OTHERHOST;
			else if (!strncmp(optarg, "outgoing", strlen("outgoing")))
				ctx.packet_type = PACKET_OUTGOING;
			else
				ctx.packet_type = -1;
			break;
		case 'S':
			ptr = optarg;
			for (j = i = strlen(optarg); i > 0; --i) {
				if (!isdigit(optarg[j - i]))
					break;
				ptr++;
			}

			if (!strncmp(ptr, "KiB", strlen("KiB")))
				ctx.reserve_size = 1 << 10;
			else if (!strncmp(ptr, "MiB", strlen("MiB")))
				ctx.reserve_size = 1 << 20;
			else if (!strncmp(ptr, "GiB", strlen("GiB")))
				ctx.reserve_size = 1 << 30;
			else
				panic("Syntax error in ring size param!\n");

			ctx.reserve_size *= strtoul(optarg, NULL, 0);
			break;
		case 'b':
			cpu_tmp = strtol(optarg, NULL, 0);

			cpu_affinity(cpu_tmp);
			if (ctx.cpu != -2)
				ctx.cpu = cpu_tmp;
			break;
		case 'H':
			prio_high = true;
			break;
		case 'c':
			ctx.pcap = PCAP_OPS_RW;
			ops_touched = 1;
			break;
		case 'm':
			ctx.pcap = PCAP_OPS_MM;
			ops_touched = 1;
			break;
		case 'G':
			ctx.pcap = PCAP_OPS_SG;
			ops_touched = 1;
			break;
		case 'Q':
			ctx.cpu = -2;
			break;
		case 's':
			ctx.print_mode = PRINT_NONE;
			break;
		case 'q':
			ctx.print_mode = PRINT_LESS;
			break;
		case 'X':
			ctx.print_mode =
				(ctx.print_mode == PRINT_ASCII) ?
				 PRINT_HEX_ASCII : PRINT_HEX;
			break;
		case 'l':
			ctx.print_mode =
				(ctx.print_mode == PRINT_HEX) ?
				 PRINT_HEX_ASCII : PRINT_ASCII;
			break;
		case 'k':
			ctx.kpull = strtoul(optarg, NULL, 0);
			break;
		case 'n':
			frame_count_max = strtoul(optarg, NULL, 0);
			break;
		case 'F':
			ptr = optarg;
			for (j = i = strlen(optarg); i > 0; --i) {
				if (!isdigit(optarg[j - i]))
					break;
				ptr++;
			}

			if (!strncmp(ptr, "KiB", strlen("KiB"))) {
				ctx.dump_interval = 1 << 10;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "MiB", strlen("MiB"))) {
				ctx.dump_interval = 1 << 20;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "GiB", strlen("GiB"))) {
				ctx.dump_interval = 1 << 30;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "sec", strlen("sec"))) {
				ctx.dump_interval = 1;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "min", strlen("min"))) {
				ctx.dump_interval = 60;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "hrs", strlen("hrs"))) {
				ctx.dump_interval = 60 * 60;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "s", strlen("s"))) {
				ctx.dump_interval = 1;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else {
				panic("Syntax error in time/size param!\n");
			}

			ctx.dump_interval *= strtoul(optarg, NULL, 0);
			break;
		case 'V':
			ctx.verbose = true;
			break;
		case 'B':
			ctx.dump_bpf = true;
			break;
		case 'D':
			pcap_dump_type_features();
			die();
			break;
		case 'U':
			update_geoip();
			die();
			break;
		case 'w':
			ctx.link_type = LINKTYPE_LINUX_SLL;
			break;
		case 'v':
			version();
			break;
		case 'h':
			help();
			break;
		case '?':
			switch (optopt) {
			case 'd':
			case 'i':
			case 'o':
			case 'f':
			case 't':
			case 'P':
			case 'F':
			case 'n':
			case 'S':
			case 'b':
			case 'k':
			case 'T':
			case 'u':
			case 'g':
			case 'e':
				panic("Option -%c requires an argument!\n",
				      optopt);
			default:
				if (isprint(optopt))
					printf("Unknown option character `0x%X\'!\n", optopt);
				die();
			}
		default:
			break;
		}
	}

	if (!ctx.filter && optind != argc)
		ctx.filter = argv2str(optind, argc, argv);

	if (!ctx.device_in)
		ctx.device_in = xstrdup("any");

	register_signal(SIGINT, signal_handler);
	register_signal(SIGQUIT, signal_handler);
	register_signal(SIGTERM, signal_handler);
	register_signal(SIGHUP, signal_handler);

	tprintf_init();

	if (prio_high) {
		set_proc_prio(-20);
		set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO));
	}

	if (device_mtu(ctx.device_in) || !strncmp("any", ctx.device_in, strlen(ctx.device_in))) {
		if (ctx.rfraw)
			setup_rfmon_mac80211_dev(&ctx, &ctx.device_in);

		if (!ctx.link_type)
			ctx.link_type = pcap_dev_to_linktype(ctx.device_in);
		if (link_has_sll_hdr(ctx.link_type)) {
			switch (ctx.magic) {
			case ORIGINAL_TCPDUMP_MAGIC:
				ctx.magic = ORIGINAL_TCPDUMP_MAGIC_LL;
				break;
			case NSEC_TCPDUMP_MAGIC:
				ctx.magic = NSEC_TCPDUMP_MAGIC_LL;
				break;
			case ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC):
				ctx.magic = ___constant_swab32(ORIGINAL_TCPDUMP_MAGIC_LL);
				break;
			case ___constant_swab32(NSEC_TCPDUMP_MAGIC):
				ctx.magic = ___constant_swab32(NSEC_TCPDUMP_MAGIC_LL);
				break;
			}
		}


		if (!ctx.device_out) {
			ctx.dump = 0;
			main_loop = recv_only_or_dump;
		} else if (device_mtu(ctx.device_out)) {
			register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
			main_loop = receive_to_xmit;
		} else {
			ctx.dump = 1;
			register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO);
			main_loop = recv_only_or_dump;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_SG;
		}
	} else {
		if (ctx.device_out && device_mtu(ctx.device_out)) {
			register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
			main_loop = pcap_to_xmit;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_MM;
		} else {
			setsockmem = false;
			main_loop = read_pcap;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_SG;
		}
	}

	bug_on(!main_loop);

	init_geoip(0);
	if (setsockmem)
		set_system_socket_memory(vals, array_size(vals));
	if (!ctx.enforce)
		xlockme();

	if (ctx.verbose)
		printf("pcap file I/O method: %s\n", pcap_ops_group_to_str[ctx.pcap]);

	main_loop(&ctx);

	if (!ctx.enforce)
		xunlockme();
	if (setsockmem)
		reset_system_socket_memory(vals, array_size(vals));
	destroy_geoip();

	device_restore_irq_affinity_list();
	tprintf_cleanup();

	destroy_ctx(&ctx);
	return 0;
}
Exemple #30
0
int main(int argc, char **argv)
{
	char *ptr;
	int c, i, j, cpu_tmp, opt_index, ops_touched = 0, vals[4] = {0};
	bool prio_high = false, setsockmem = true;
	void (*main_loop)(struct ctx *ctx) = NULL;
	struct ctx ctx;

	init_ctx(&ctx);
	srand(time(NULL));

	while ((c = getopt_long(argc, argv, short_options, long_options,
				&opt_index)) != EOF) {
		switch (c) {
		case 'd':
		case 'i':
			ctx.device_in = xstrdup(optarg);
			break;
		case 'o':
			ctx.device_out = xstrdup(optarg);
			break;
		case 'P':
			ctx.prefix = xstrdup(optarg);
			break;
		case 'R':
			ctx.link_type = LINKTYPE_IEEE802_11;
			ctx.rfraw = 1;
			break;
		case 'r':
			ctx.randomize = true;
			break;
		case 'J':
			ctx.jumbo = true;
			break;
		case 'T':
			ctx.magic = (uint32_t) strtoul(optarg, NULL, 0);
			pcap_check_magic(ctx.magic);
			break;
		case 'f':
			ctx.filter = xstrdup(optarg);
			break;
		case 'M':
			ctx.promiscuous = false;
			break;
		case 'A':
			setsockmem = false;
			break;
		case 'u':
			ctx.uid = strtoul(optarg, NULL, 0);
			ctx.enforce = true;
			break;
		case 'g':
			ctx.gid = strtoul(optarg, NULL, 0);
			ctx.enforce = true;
			break;
		case 't':
			if (!strncmp(optarg, "host", strlen("host")))
				ctx.packet_type = PACKET_HOST;
			else if (!strncmp(optarg, "broadcast", strlen("broadcast")))
				ctx.packet_type = PACKET_BROADCAST;
			else if (!strncmp(optarg, "multicast", strlen("multicast")))
				ctx.packet_type = PACKET_MULTICAST;
			else if (!strncmp(optarg, "others", strlen("others")))
				ctx.packet_type = PACKET_OTHERHOST;
			else if (!strncmp(optarg, "outgoing", strlen("outgoing")))
				ctx.packet_type = PACKET_OUTGOING;
			else
				ctx.packet_type = -1;
			break;
		case 'S':
			ptr = optarg;
			ctx.reserve_size = 0;

			for (j = i = strlen(optarg); i > 0; --i) {
				if (!isdigit(optarg[j - i]))
					break;
				ptr++;
			}

			if (!strncmp(ptr, "KiB", strlen("KiB")))
				ctx.reserve_size = 1 << 10;
			else if (!strncmp(ptr, "MiB", strlen("MiB")))
				ctx.reserve_size = 1 << 20;
			else if (!strncmp(ptr, "GiB", strlen("GiB")))
				ctx.reserve_size = 1 << 30;
			else
				panic("Syntax error in ring size param!\n");
			*ptr = 0;

			ctx.reserve_size *= strtol(optarg, NULL, 0);
			break;
		case 'b':
			cpu_tmp = strtol(optarg, NULL, 0);

			cpu_affinity(cpu_tmp);
			if (ctx.cpu != -2)
				ctx.cpu = cpu_tmp;
			break;
		case 'H':
			prio_high = true;
			break;
		case 'c':
			ctx.pcap = PCAP_OPS_RW;
			ops_touched = 1;
			break;
		case 'm':
			ctx.pcap = PCAP_OPS_MM;
			ops_touched = 1;
			break;
		case 'G':
			ctx.pcap = PCAP_OPS_SG;
			ops_touched = 1;
			break;
		case 'Q':
			ctx.cpu = -2;
			break;
		case 's':
			ctx.print_mode = PRINT_NONE;
			break;
		case 'q':
			ctx.print_mode = PRINT_LESS;
			break;
		case 'X':
			ctx.print_mode =
				(ctx.print_mode == PRINT_ASCII) ?
				 PRINT_HEX_ASCII : PRINT_HEX;
			break;
		case 'l':
			ctx.print_mode =
				(ctx.print_mode == PRINT_HEX) ?
				 PRINT_HEX_ASCII : PRINT_ASCII;
			break;
		case 'k':
			ctx.kpull = strtol(optarg, NULL, 0);
			break;
		case 'n':
			frame_count_max = strtol(optarg, NULL, 0);
			break;
		case 'F':
			ptr = optarg;
			ctx.dump_interval = 0;

			for (j = i = strlen(optarg); i > 0; --i) {
				if (!isdigit(optarg[j - i]))
					break;
				ptr++;
			}

			if (!strncmp(ptr, "KiB", strlen("KiB"))) {
				ctx.dump_interval = 1 << 10;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "MiB", strlen("MiB"))) {
				ctx.dump_interval = 1 << 20;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "GiB", strlen("GiB"))) {
				ctx.dump_interval = 1 << 30;
				ctx.dump_mode = DUMP_INTERVAL_SIZE;
			} else if (!strncmp(ptr, "sec", strlen("sec"))) {
				ctx.dump_interval = 1;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "min", strlen("min"))) {
				ctx.dump_interval = 60;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "hrs", strlen("hrs"))) {
				ctx.dump_interval = 60 * 60;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else if (!strncmp(ptr, "s", strlen("s"))) {
				ctx.dump_interval = 1;
				ctx.dump_mode = DUMP_INTERVAL_TIME;
			} else {
				panic("Syntax error in time/size param!\n");
			}

			*ptr = 0;
			ctx.dump_interval *= strtol(optarg, NULL, 0);
			break;
		case 'V':
			ctx.verbose = 1;
			break;
		case 'B':
			ctx.dump_bpf = true;
			break;
		case 'D':
			pcap_dump_type_features();
			die();
			break;
		case 'U':
			update_geoip();
			die();
			break;
		case 'v':
			version();
			break;
		case 'h':
			help();
			break;
		case '?':
			switch (optopt) {
			case 'd':
			case 'i':
			case 'o':
			case 'f':
			case 't':
			case 'P':
			case 'F':
			case 'n':
			case 'S':
			case 'b':
			case 'k':
			case 'T':
			case 'u':
			case 'g':
			case 'e':
				panic("Option -%c requires an argument!\n",
				      optopt);
			default:
				if (isprint(optopt))
					printf("Unknown option character `0x%X\'!\n", optopt);
				die();
			}
		default:
			break;
		}
	}

	if (!ctx.filter && optind != argc) {
		int ret;
		off_t offset = 0;

		for (i = optind; i < argc; ++i) {
			size_t alen = strlen(argv[i]) + 2;
			size_t flen = ctx.filter ? strlen(ctx.filter) : 0;

			ctx.filter = xrealloc(ctx.filter, 1, flen + alen);
			ret = slprintf(ctx.filter + offset, strlen(argv[i]) + 2, "%s ", argv[i]);
			if (ret < 0)
				panic("Cannot concatenate filter string!\n");
			else
				offset += ret;
		}
	}

	if (!ctx.device_in)
		ctx.device_in = xstrdup("any");

	register_signal(SIGINT, signal_handler);
	register_signal(SIGHUP, signal_handler);

	tprintf_init();

	if (prio_high) {
		set_proc_prio(-20);
		set_sched_status(SCHED_FIFO, sched_get_priority_max(SCHED_FIFO));
	}

	if (ctx.device_in && (device_mtu(ctx.device_in) ||
	    !strncmp("any", ctx.device_in, strlen(ctx.device_in)))) {
		if (!ctx.rfraw)
			ctx.link_type = pcap_devtype_to_linktype(ctx.device_in);
		if (!ctx.device_out) {
			ctx.dump = 0;
			main_loop = recv_only_or_dump;
		} else if (device_mtu(ctx.device_out)) {
			register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
			main_loop = receive_to_xmit;
		} else {
			ctx.dump = 1;
			register_signal_f(SIGALRM, timer_next_dump, SA_SIGINFO);
			main_loop = recv_only_or_dump;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_SG;
		}
	} else {
		if (ctx.device_out && device_mtu(ctx.device_out)) {
			register_signal_f(SIGALRM, timer_elapsed, SA_SIGINFO);
			main_loop = pcap_to_xmit;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_MM;
		} else {
			main_loop = read_pcap;
			if (!ops_touched)
				ctx.pcap = PCAP_OPS_SG;
		}
	}

	bug_on(!main_loop);

	init_geoip(0);
	if (setsockmem)
		set_system_socket_memory(vals, array_size(vals));
	if (!ctx.enforce)
		xlockme();

	main_loop(&ctx);

	if (!ctx.enforce)
		xunlockme();
	if (setsockmem)
		reset_system_socket_memory(vals, array_size(vals));
	destroy_geoip();

	device_restore_irq_affinity_list();
	tprintf_cleanup();

	destroy_ctx(&ctx);
	return 0;
}