Exemplo n.º 1
0
void fg_pcap_init()
{
/* initalize *alldevs for later use */
#ifdef DEBUG
	pcap_if_t *d;
	char devdes[200];
#endif /* DEBUG */
	if (pcap_findalldevs(&alldevs, errbuf) == -1) {
		logging_log(LOG_WARNING,"Error in pcap_findalldevs: %s\n",
			    errbuf);
		return;
	}
#ifdef DEBUG
	for (d = alldevs; d; d = d->next) {
		pcap_addr_t *a;
		snprintf(devdes, sizeof(devdes), "%s: ", d->name);
		for (a = d->addresses; a; a = a->next) {
			char addr[100];
			if (!a->addr)
				continue;
			snprintf(addr, sizeof(addr), "a=%s",
				 fg_nameinfo(a->addr, sizeof(struct sockaddr)));
			strncat(devdes, addr, sizeof(devdes) - strlen(devdes) - 1);
			if (a->next)
				strncat(devdes, ", ", sizeof(devdes) - strlen(devdes) - 1);
		}
		DEBUG_MSG(LOG_ERR, "pcap: found pcapable device (%s)", devdes);
	}
#endif /* DEBUG*/
	pthread_mutex_init(&pcap_mutex, NULL);
#ifndef __DARWIN__
	pthread_barrier_init(&pcap_barrier, NULL, 2);
#endif /* __DARWIN__ */
	return;
}
Exemplo n.º 2
0
int get_imtu(int fd)
/* returns interface mtu */
{
	struct sockaddr_storage sa;
	socklen_t sl = sizeof(sa);

	struct ifreq ifreqs[20];

	struct ifconf ifconf;
	int nifaces, i, mtu = 0;

	memset(&ifconf,0,sizeof(ifconf));
	ifconf.ifc_buf = (char*)(ifreqs);
	ifconf.ifc_len = sizeof(ifreqs);

	if (getsockname(fd, (struct sockaddr *)&sa, &sl) < 0)
		return 0;

	if (ioctl(fd, SIOCGIFCONF, &ifconf) < 0)
		return 0;

	nifaces =  ifconf.ifc_len/sizeof(struct ifreq);

	for(i = 0; i < nifaces; i++)
	{
		if (sockaddr_compare((struct sockaddr *)&ifreqs[i].ifr_addr, (struct sockaddr *)&sa))
			break;
	}

	if (ioctl(fd, SIOCGIFMTU, &ifreqs[i]) < 0)
		return 0;

	DEBUG_MSG(LOG_NOTICE, "interface %s (%s) has mtu %d",
		  ifreqs[i].ifr_name,
		  fg_nameinfo((struct sockaddr *)&ifreqs[i].ifr_addr, sizeof(struct sockaddr)),
		  ifreqs[i].ifr_mtu);

	mtu = ifreqs[i].ifr_mtu;

	if (mtu > 0)
		return mtu;
	else
		return 0;
}
Exemplo n.º 3
0
static void* fg_pcap_work(void* arg)
{
	/* note: all the wierd casts in this function are completely useless,
	 * execpt they cirumvent strange compiler warnings because of libpcap
	 * typedef woo's */

#ifdef DEBUG
	struct pcap_stat p_stats;
#endif /* DEBUG */
	int rc;
	struct _flow * flow;
	flow = (struct _flow *) arg;
	pcap_if_t *d;
	struct sockaddr_storage sa;
	socklen_t sl = sizeof(sa);
	char found = 0;
	uint32_t net = 0;
	uint32_t mask = 0;

	char dump_filename[500];
	char hostname[100];

	struct bpf_program pcap_program;
	struct timespec now;
	char buf[60];

	DEBUG_MSG(LOG_DEBUG, "fg_pcap_thread() called for flow %d", flow->id);

	/* make sure all resources are released when finished */
	pthread_detach(pthread_self());
	pthread_cleanup_push(fg_pcap_cleanup, (void*) flow);

	if (getsockname(flow->fd, (struct sockaddr *)&sa, &sl) == -1) {
		logging_log(LOG_WARNING, "getsockname() failed. Eliding "
			    "packet capture for flow.");
		goto remove;
	}

	/* find appropriate (used for test) interface to dump */
	for (d = alldevs; d; d = d->next) {
		pcap_addr_t *a;
		for (a = d->addresses; a; a = a->next) {
			if (!a->addr)
				continue;
			if (sockaddr_compare(a->addr, (struct sockaddr *)&sa)) {
				DEBUG_MSG(LOG_NOTICE, "pcap: data connection "
					  "inbound from %s (%s)", d->name,
					  fg_nameinfo(a->addr,
						      sizeof(struct sockaddr)));
				found = 1;
				break;
			}
		}
		if (found)
			break;
	}

	if (!found) {
		logging_log(LOG_WARNING, "Failed to determine interface "
			    "for data connection. No pcap support.");
		goto remove;
	}

	/* Make sure errbuf contains zero-length string in order to enable
	 * pcap_open_live to report warnings. */
	errbuf[0] = '\0';
	flow->pcap_handle =
		(struct pcap_t *)pcap_open_live(d->name, PCAP_SNAPLEN,
						PCAP_PROMISC,
						0, /* no read timeout */
						errbuf);

	if (!flow->pcap_handle) {
		logging_log(LOG_WARNING, "Failed to init pcap on device %s:"
			    " %s", d->name, errbuf);
		goto remove;
	}


	if (pcap_lookupnet(d->name, &net, &mask, errbuf) < 0) {
		logging_log(LOG_WARNING, "pcap: netmask lookup failed: %s",
			    errbuf);
		goto remove;
	}

	/* We rely on a non-blocking dispatch loop */
	if (pcap_setnonblock((pcap_t *)flow->pcap_handle,
			     1 /* non-blocking */,
			     errbuf) < 0) {
		logging_log(LOG_WARNING, "pcap: failed to set non-blocking: "
			    "%s", errbuf);
		goto remove;
	}

	/* compile filter */
	if (pcap_compile((pcap_t *)flow->pcap_handle,
			 &pcap_program, PCAP_FILTER, 1, mask) < 0) {
		logging_log(LOG_WARNING, "pcap: failed compiling filter "
			    "'%s': %s", PCAP_FILTER,
			    pcap_geterr((pcap_t *)flow->pcap_handle));
		goto remove;
	}

	/* attach filter to interface */
	if (pcap_setfilter((pcap_t *)flow->pcap_handle,
			   &pcap_program) < 0) {
		logging_log(LOG_WARNING, "pcap: failed to set filter: "
			    "%s", pcap_geterr((pcap_t *)flow->pcap_handle));
		goto remove;
	}

	/* generate a nice filename */
	dump_filename[0] = '\0';

	/* dir and prefix */
	if (dump_dir)
		strcat(dump_filename, dump_dir);
	if (dump_prefix)
		strcat(dump_filename, dump_prefix);

	/* timestamp */
	gettime(&now);
	strftime(buf, sizeof(buf), "%Y-%m-%d-%H:%M:%S",
		 localtime(&now.tv_sec));
	strcat(dump_filename, buf);

	/* hostname */
	hostname[0]= '\0';
	if (!gethostname(hostname, 59)) {
		strcat(dump_filename, "-");
		strcat(dump_filename, hostname);
	}

	/* interface */
	strcat(dump_filename, "-");
	strcat(dump_filename, d->name);

	/* suffix */
	strcat(dump_filename, ".pcap");

	DEBUG_MSG(LOG_NOTICE, "dumping to \"%s\"", dump_filename);

	flow->pcap_dumper = (struct pcap_dumper_t *)pcap_dump_open(
				(pcap_t *)flow->pcap_handle, dump_filename);

	if (!flow->pcap_dumper) {
		logging_log(LOG_WARNING, "pcap: failed to open dump file "
			    "writing: %s",
			    pcap_geterr((pcap_t *)flow->pcap_handle));
		goto remove;
	}

	/* barrier: dump is ready */
#ifndef __DARWIN__
	pthread_barrier_wait(&pcap_barrier);
#endif /* __DARWIN__ */
	for (;;) {
		rc = pcap_dispatch((pcap_t *)flow->pcap_handle, -1,
				   &pcap_dump, (u_char *)flow->pcap_dumper);

		if (rc < 0) {
			logging_log(LOG_WARNING, "pcap_dispatch() failed. "
				    "Packet dumping stopped for flow %d.",
				    flow->id);
			/* cleanup automatically called */
			pthread_exit(0);
		}
#ifdef DEBUG
		pcap_stats((pcap_t *)flow->pcap_handle, &p_stats);
#endif /* DEBUG */
		DEBUG_MSG(LOG_NOTICE, "pcap: finished dumping %u packets for "
			  "flow %d", rc, flow->id);
		DEBUG_MSG(LOG_NOTICE, "pcap: %d packets received by filter for "
			  "flow %d", p_stats.ps_recv, flow->id);
		DEBUG_MSG(LOG_NOTICE, "pcap: %d packets dropped by kernel for "
			  "flow %d", p_stats.ps_drop, flow->id);
		if (rc == 0)
			/* if no packets are received try
			 * if we should cancel */
			pthread_testcancel();
	}
	pthread_cleanup_pop(1);

remove:
#ifndef __DARWIN__
	pthread_barrier_wait(&pcap_barrier);
#endif /* __DARWIN__ */
	return 0;

}