Exemple #1
0
static void heartbeat(int fd, short evtype, void *arg)
{
	static struct timeval now, diff, tv = {0, 0};
	struct mg *mg = arg;

	/* garbage collector - free whenever garbage > 128KB */
	if (mmatic_size(mg->mmtmp) > 1024 * 128) {
		mmatic_free(mg->mmtmp);
		mg->mmtmp = mmatic_create();
	}

	/* if no line generator is running and there was no packet to us in last 60 seconds - exit */
	if (mg->running == 0) {
		gettimeofday(&now, NULL);
		timersub(&now, &mg->last, &diff);

		if (diff.tv_sec >= 60) {
			dbg(0, "Finished, exiting...\n");
			mg->running--;
			event_base_loopexit(mg->evb, &tv);
			return;
		}
	}

	mgs_uschedule(&mg->hbs, HEARTBEAT_PERIOD);
}
Exemple #2
0
void flow(struct lfc *lfc, void *pdata,
          struct lfc_flow *lf, void *data)
{
    struct flow *f = data;

    printf(",%s", p2s[f->proto]);
    mmatic_free(f->ipq_flow);
}
Exemple #3
0
void pcap_deinit(struct tracedump *td)
{
	/* close the reader and wait for it */
	pthread_cancel(td->pc->reader);
	pthread_join(td->pc->reader, NULL);

	close(td->pc->fd);
	fclose(td->pc->fp);

	/* free the memory */
	mmatic_free(td->pc);
}
Exemple #4
0
void pcap_update(struct tracedump *td)
{
	struct sock_fprog *fp;

	pthread_mutex_lock(&td->mutex_ports);

	/* generate BPF filter code basing on the current port list */
	fp = gencode_alloc(td);

#ifdef CHECK_BPF
	/* verify the code on the user side - useful for debugging */
	sk_chk_filter(fp->filter, fp->len);
#endif

	/* attach the filter */
	if (setsockopt(td->pc->fd, SOL_SOCKET, SO_ATTACH_FILTER, fp, sizeof *fp) != 0)
		die_errno("setsockopt");

	pthread_mutex_unlock(&td->mutex_ports);
	mmatic_free(fp->filter);
	mmatic_free(fp);
}
Exemple #5
0
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...)
{
	/* int 0x80, int3 */
	unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 };
	char backup[4];
	struct user_regs_struct regs, regs2;
	int ss_vals, ss_mem, ss;
	va_list vl;
	enum arg_type type;
	uint32_t sv;
	void *ptr;
	uint8_t *stack, *stack_mem;
	uint32_t *stack32;
	int i, j;

	/*
	 * get the required amount of stack space
	 */
	ss_vals = 0;
	ss_mem = 0;
	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;
		sv  = va_arg(vl, uint32_t);

		/* each socketcall argument takes 4 bytes */
		ss_vals += 4;

		/* if its memory, it takes additional sv bytes */
		if (type == AT_MEM_IN || type == AT_MEM_INOUT) {
			ss_mem += sv;
			ptr = va_arg(vl, void *);
		}
	} while (true);
	va_end(vl);
	ss = ss_vals + ss_mem;

	/*
	 * backup
	 */
	ptrace_getregs(sp, &regs);
	memcpy(&regs2, &regs, sizeof regs);
	ptrace_read(sp, regs.eip, backup, sizeof backup);

	/*
	 * write the stack
	 */
	stack = mmatic_zalloc(td->mm, ss);
	stack32 = (uint32_t *) stack;
	stack_mem = stack + ss_vals;

	va_start(vl, sc_code);
	i = 0; j = 0;
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv  = va_arg(vl, uint32_t);

		if (type == AT_VALUE) {
			stack32[i++] = sv;
		} else { /* i.e. its a memory arg */
			stack32[i++] = regs.esp - ss_mem + j;

			/* copy the memory */
			ptr = va_arg(vl, void *);
			memcpy(stack_mem + j, ptr, sv);
			j += sv;
		}
	} while (true);
	va_end(vl);

	ptrace_write(sp, regs.esp - ss, stack, ss);

	/*
	 * write the code and run
	 */
	regs2.eax = 102; // socketcall
	regs2.ebx = sc_code;
	regs2.ecx = regs.esp - ss;

	ptrace_write(sp, regs.eip, code, sizeof code);
	ptrace_setregs(sp, &regs2);
	ptrace_cont(sp, 0, true);

	/*
	 * read back
	 */
	ptrace_getregs(sp, &regs2);
	ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem);

	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv = va_arg(vl, uint32_t);
		if (type == AT_VALUE) continue;

		ptr = va_arg(vl, void *);
		if (type == AT_MEM_IN) continue;

		memcpy(ptr, stack_mem, sv);
		stack_mem += sv;
	} while (true);
	va_end(vl);

	/* restore */
	ptrace_write(sp, regs.eip, backup, sizeof backup);
	ptrace_setregs(sp, &regs);

	mmatic_free(stack);

	return regs2.eax;
}
Exemple #6
0
int main(int argc, char *argv[])
{
	mmatic *mm = mmatic_create();
	mmatic *mmtmp = mmatic_create();
	struct mg *mg;
	int i;

	/*
	 * initialize and parse config
	 */

	mg = mmatic_zalloc(mm, sizeof(struct mg));
	mg->mm = mm;
	mg->mmtmp = mmtmp;
	apply_defaults(mg);

	/* get my id number from hostname */
	fetch_myid(mg);

	/* parse command line options */
	if (parse_argv(mg, argc, argv))
		return 1;

	/* parse configuration file options */
	if (mg->options.conf_file) {
		if (parse_config(mg))
			return 4;
	}

	/*
	 * config syntax looks OK, see if it is feasible
	 */

	/* initialize random number generator */
	srand48(mg->options.myid);

	/* init libevent */
	mg->evb = event_init();
	event_set_log_callback(libevent_log);

	/* init stats structures so mgstats_aggregator_add() used somewhere below works */
	mgstats_init(mg);

	/* attach to raw interfaces */
	if (mgi_init(mg, handle_packet) <= 0) {
		dbg(0, "no available interfaces found\n");
		return 2;
	}

	/* parse traffic file */
	if (parse_traffic(mg))
		return 3;

	/*
	 * all OK, prepare to start
	 */

	/* synchronize time reference point on all nodes */
	mgc_sync(mg);

	/* schedule stats writing */
	mgstats_start(mg);

	/* attach global stats */
	_stats_init(mg);

	/* schedule heartbeat and disk sync signals */
	heartbeat_init(mg);
	sync_init(mg);

	/* schedule the real work of this node: line generators */
	for (i = 1; i < TRAFFIC_LINE_MAX; i++) {
		if (!(mg->lines[i] && mg->lines[i]->my))
			continue;

		/* this will schedule first execution */
		mgs_sleep(mg->lines[i], NULL);
		mg->running++;
	}

	/* suppose last frame was received now */
	gettimeofday(&mg->last, NULL);

	/*
	 * start!
	 */

	dbg(0, "Starting\n");
	event_base_dispatch(mg->evb);

	/*******************************/

	/*
	 * cleanup after end of libevent loop
	 */

	event_base_free(mg->evb);
	mmatic_free(mg->mm);
	mmatic_free(mg->mmtmp);

	fflush(NULL);
	sync();

	return 0;
}
Exemple #7
0
int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...)
{
	struct user_regs_struct regs, regs2;
	int ss_vals, ss_mem, ss;
	va_list vl;
	enum arg_type type;
	uint32_t sv;
	void *ptr;
	uint8_t *stack, *stack_mem;
	uint32_t *stack32;
	int i, j;

	/*
	 * get the required amount of stack space
	 */
	ss_vals = 0;  // stack space for immediate values
	ss_mem = 0;   // stack space for pointer values
	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;
		sv  = va_arg(vl, uint32_t);

		/* each socketcall argument takes 4 bytes */
		ss_vals += 4;

		/* if its memory, it takes additional sv bytes */
		if (type == AT_MEM_IN || type == AT_MEM_INOUT) {
			ss_mem += sv;
			ptr = va_arg(vl, void *);
		}
	} while (true);
	va_end(vl);
	ss = ss_vals + ss_mem;

	/*
	 * backup
	 */
	ptrace_getregs(sp, &regs);
	memcpy(&regs2, &regs, sizeof regs);

	/*
	 * write the stack
	 */
	stack = mmatic_zalloc(td->mm, ss); // stack area for immediate values
	stack32 = (uint32_t *) stack;
	stack_mem = stack + ss_vals;       // stack area for pointer values

	va_start(vl, sc_code);
	i = 0; j = 0;
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv  = va_arg(vl, uint32_t);

		if (type == AT_VALUE) {
			stack32[i++] = sv;
		} else { /* i.e. its a memory arg */
			stack32[i++] = regs.esp - ss_mem + j;

			/* copy the memory */
			ptr = va_arg(vl, void *);
			memcpy(stack_mem + j, ptr, sv);
			j += sv;
		}
	} while (true);
	va_end(vl);

	ptrace_write(sp, regs.esp - ss, stack, ss);

	/*
	 * write the code and run
	 */
	_prepare(sp);

	regs2.eax = 102;            // socketcall
	regs2.ebx = sc_code;
	regs2.ecx = regs.esp - ss;
	regs2.eip = sp->vdso_addr;  // gateway to int3

	ptrace_setregs(sp, &regs2);
	ptrace_cont_syscall(sp, 0, true);   // enter...
	ptrace_cont_syscall(sp, 0, true);   // ...and exit

	/*
	 * read back
	 */
	ptrace_getregs(sp, &regs2);
	ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem);

	va_start(vl, sc_code);
	do {
		type = va_arg(vl, enum arg_type);
		if (type == AT_LAST) break;

		sv = va_arg(vl, uint32_t);
		if (type == AT_VALUE) continue;

		ptr = va_arg(vl, void *);
		if (type == AT_MEM_IN) continue;

		memcpy(ptr, stack_mem, sv);
		stack_mem += sv;
	} while (true);
	va_end(vl);

	/* restore */
	ptrace_setregs(sp, &regs);
	mmatic_free(stack);

	return regs2.eax;
}
Exemple #8
0
static void *gc_thread(void *arg)
{
	struct tracedump *td;
	sigset_t ss;
	uint8_t *tcp = NULL, *udp = NULL;
	unsigned int port;
	struct port *sp;
	int count = 0;
	struct timeval now;

	td = (struct tracedump *) arg;
	sigaddset(&ss, SIGTERM);
	sigaddset(&ss, SIGINT);
	pthread_sigmask(SIG_SETMASK, &ss, NULL);

	while (1) {
		sleep(60);

		/* read list of active tcp/udp ports */
		tcp = port_list(td, true);
		udp = port_list(td, false);
		if (!tcp || !udp) {
			dbg(1, "gc: reading tcp/udp ports failed\n");
			goto next;
		}

		/*
		 * iterate through all monitored TCP/UDP ports and delete those
		 * that are not needed anymore
		 */
		pthread_mutex_lock(&td->mutex_ports);
		gettimeofday(&now, NULL);

		/* TCP */
		thash_reset(td->tcp_ports);
		while ((sp = thash_uint_iter(td->tcp_ports, &port))) {
			/* skip ports "younger" than 60 secs
			 * workaround that autobound TCP ports are not visible in procfs - Linux bug? */
			if (pjf_timediff(&now, &sp->since)/1000000 < 60)
				continue;

			if (!PORT_ISSET(tcp, port)) {
				count++;
				thash_uint_set(td->tcp_ports, port, NULL);
				dbg(3, "port TCP/%d deleted\n", port);
			}
		}

		/* UDP */
		thash_reset(td->udp_ports);
		while ((sp = thash_uint_iter(td->udp_ports, &port))) {
			if (!PORT_ISSET(udp, port)) {
				count++;
				thash_uint_set(td->udp_ports, port, NULL);
				dbg(3, "port UDP/%d deleted\n", port);
			}
		}

		pthread_mutex_unlock(&td->mutex_ports);

		/* if any changes were made, run the BPF filter update */
		if (count > 0)
			pcap_update(td);

next:
		if (tcp) mmatic_free(tcp);
		if (udp) mmatic_free(udp);
	}

	return NULL;
}
Exemple #9
0
void verdict_free(struct spi *spi)
{
	mmatic_free(spi->vdata);
	return;
}
Exemple #10
0
void flow_destroy(struct spi_flow *flow)
{
	mmatic_free(flow);
}