Esempio n. 1
0
void abort_tx_frame(interface *i,void *frame){
	const omphalos_ctx *octx = get_octx();
	struct tpacket_hdr *thdr = frame;

	++i->txaborts;
	thdr->tp_status = TP_STATUS_AVAILABLE;
	if(octx->mode != OMPHALOS_MODE_SILENT){
		diagnostic("Aborted TX %ju on %s",i->txaborts,i->name);
	}
}
Esempio n. 2
0
// Mark a frame as ready-to-send. Must have come from get_tx_frame() using this
// same interface. Yes, we will see packets we generate on the RX ring.
int send_tx_frame(interface *i,void *frame){
	const omphalos_ctx *octx = get_octx();
	struct tpacket_hdr *thdr = frame;
	int ret = 0;

	assert(thdr->tp_status == TP_STATUS_PREPARING);
	if(octx->mode != OMPHALOS_MODE_SILENT){
		int self,out;

		categorize_tx(i,(const char *)frame + thdr->tp_mac,&self,&out);
		if(self){
			int r;

			r = send_to_self(i,frame);
			if(r < 0){
				++i->txerrors;
			}else{
				i->txbytes += r;
				++i->txframes;
			}
			ret |= r < 0 ? -1 : 0;
		}
		if(out){
			uint32_t tplen = thdr->tp_len;
			int r;

			//thdr->tp_status = TP_STATUS_SEND_REQUEST;
			//r = send(i->fd,NULL,0,0);
			r = send(i->fd,(const char *)frame + thdr->tp_mac,tplen,0);
			if(r == 0){
				r = tplen;
			}
			//diagnostic("Transmitted %d on %s",ret,i->name);
			if(r < 0){
				diagnostic("Error out-TXing %u on %s (%s)",tplen,i->name,strerror(errno));
				++i->txerrors;
			}else{
				i->txbytes += r;
				++i->txframes;
			}
			ret |= r < 0 ? -1 : 0;
		}
		thdr->tp_status = TP_STATUS_AVAILABLE;
	}else{
		abort_tx_frame(i,frame);
		ret = 0;
	}
	return ret;
}
Esempio n. 3
0
void observe_service(interface *i,struct l2host *l2,struct l3host *l3,
			unsigned proto,unsigned port,
			const wchar_t *srv,const wchar_t *srvver){
	const omphalos_ctx *octx = get_octx();
	l4srv *services,**prev,*cur;

	services = l3_getservices(l3);
	for(prev = &services ; (cur = *prev) ; prev = &cur->next){
		if(cur->proto > proto){
			break;
		}else if(cur->proto == proto){
			if(cur->port > port){
				break;
			}else if(cur->port == port){
				int r;

				if((r = wcscmp(cur->srv,srv)) == 0){
					return;
				}else if(r > 0){
					break;
				}
			}
		}
	}
	if((cur = new_service(proto,port,srv,srvver)) == NULL){
		return;
	}
	cur->next = *prev;
	*prev = cur;
	if(l3_setservices(l3,services)){
		*prev = cur->next;
		free_service(cur);
	}else if(octx->iface.srv_event){
		cur->opaque = octx->iface.srv_event(i,l2,l3,cur);
	}
}
Esempio n. 4
0
#include <omphalos/radiotap.h>
#include <omphalos/interface.h>

#define MAXINTERFACES (1u << 16) // lame FIXME

// Master lock across interfaces[], used to lazily initialize interface objects
static pthread_mutex_t iface_lock = PTHREAD_MUTEX_INITIALIZER;

static int ifaces[MAXINTERFACES];		// 1 for initialized, else 0
static interface interfaces[MAXINTERFACES];

// FIXME what the hell to do here...?
static void
handle_void_packet(omphalos_packet *op,const void *frame __attribute__ ((unused)),
                   size_t len __attribute__ ((unused))) {
    const struct omphalos_ctx *ctx = get_octx();
    const omphalos_iface *octx = &ctx->iface;

    assert(op->i);
    if(octx->packet_read) {
        octx->packet_read(op);
    }
}

static int
init_iface(interface *iface) {
    pthread_mutexattr_t attr;

    if(pthread_mutexattr_init(&attr)) {
        return -1;
    }
Esempio n. 5
0
// -1: error; don't call us anymore. 0: handled frame. 1: interrupted; we
// return for a cancellation check, and the frameptr oughtn't be advanced. The
// interface lock must be held upon entry.
int handle_ring_packet(interface *iface,int fd,void *frame){
	const struct omphalos_ctx *ctx = get_octx();
	const omphalos_iface *octx = &ctx->iface;
	struct tpacket_hdr *thdr = frame;
	omphalos_packet packet;
	int len;

	memset(&packet,0,sizeof(packet));
	packet.i = iface;
	while(thdr->tp_status == 0){
		struct pollfd pfd[1];
		int events,msec;

		pfd[0].fd = fd;
		pfd[0].revents = 0;
		pfd[0].events = POLLIN | POLLRDNORM | POLLERR;
		msec = IFACE_TIMESTAT_USECS / 1000;
		pthread_mutex_unlock(&iface->lock);
		events = poll(pfd,sizeof(pfd) / sizeof(*pfd),msec);
		pthread_mutex_lock(&iface->lock);
		if(events == 0){
			gettimeofday(&packet.tv,NULL);
			timestat_inc(&iface->fps,&packet.tv,0);
			timestat_inc(&iface->bps,&packet.tv,0);
			if(octx->packet_read){
				octx->packet_read(&packet);
			}
			return 1;
		}else if(events < 0){
			if(errno != EINTR){
				diagnostic("Error in poll() on %s (%s?)",
						iface->name,strerror(errno));
				return -1;
			}
			return 1;
		}else if(pfd[0].revents & POLLERR){
			// FIXME don't want to print this every time a device
			// is removed from underneath us, but also don't want
			// to race against notification...check to see if
			// device is down here? FIXME
			//diagnostic("Error polling psocket %d on %s",fd,i->name);
			return -1;
		}
	}
	++iface->frames;
	packet.tv.tv_sec = thdr->tp_sec;
	packet.tv.tv_usec = thdr->tp_usec;
	timestat_inc(&iface->fps,&packet.tv,1);
	if(thdr->tp_status & TP_STATUS_LOSING){
		struct tpacket_stats tstats;
		socklen_t slen;

		// FIXME only call once for each burst of TP_STATUS_LOSING
		slen = sizeof(tstats);
		if(getsockopt(fd,SOL_PACKET,PACKET_STATISTICS,&tstats,&slen)){
			diagnostic("Error reading stats on %s (%s?)",iface->name,strerror(errno));
		}else if(tstats.tp_drops){
			iface->drops += tstats.tp_drops;
			diagnostic("[%s] %u/%ju drops",iface->name,tstats.tp_drops,iface->drops);
		}
	}
	if((thdr->tp_status & TP_STATUS_COPY) || thdr->tp_snaplen != thdr->tp_len){
		++iface->truncated;
		if((len = recover_truncated_packet(iface,fd,thdr->tp_len)) <= 0){
			diagnostic("Partial capture on %s (%u/%ub)",
				iface->name,thdr->tp_snaplen,thdr->tp_len);
			frame = (char *)frame + thdr->tp_mac;
			len = thdr->tp_snaplen;
		}else{
			frame = iface->truncbuf;
			++iface->truncated_recovered;
			len = thdr->tp_len;
		}
	}else{
		frame = (char *)frame + thdr->tp_mac;
		len = thdr->tp_len;
	}
	timestat_inc(&iface->bps,&packet.tv,len);
	iface->bytes += len;
	iface->analyzer(&packet,frame,len);
	thdr->tp_status = TP_STATUS_KERNEL; // return the frame
	if(packet.l2s){
		l2srcpkt(packet.l2s);
	}
	if(packet.l2d){
		l2dstpkt(packet.l2d);
	}
	if(packet.l3s){
		l3_srcpkt(packet.l3s);
	}
	if(packet.l3d){
		l3_dstpkt(packet.l3d);
	}
	if(packet.malformed || packet.noproto){
		if(packet.malformed){
			++iface->malformed;
		}
		if(packet.noproto){
			++iface->noprotocol;
		}
		if(packet.pcap_ethproto){
			struct pcap_pkthdr pcap;
			size_t scribble = 0;
			struct pcap_ll pll;

			if(frame != iface->truncbuf){
				scribble = thdr->tp_mac;
				frame -= thdr->tp_mac;
			}else{
				scribble = 0;
			}
			pcap.caplen = pcap.len = len + scribble;
			pcap.ts = packet.tv;
			memset(&pll,0,sizeof(pll));
			pll.arphrd = htons(packet.i->arptype);
			pll.llen = htons(packet.i->addrlen);
			if(packet.l2s){
				hwaddrint hw = get_hwaddr(packet.l2s);
				memcpy(&pll.haddr,&hw,packet.i->addrlen > sizeof(pll.haddr) ?
						sizeof(pll.haddr) : packet.i->addrlen);
				// FIXME handle other pkttypes
				if(memcmp(&hw,packet.i->addr,packet.i->addrlen) == 0){
					pll.pkttype = htons(4);
				}
			}
			pll.ethproto = htons(packet.pcap_ethproto);
			// 'frame' starts at the L2 header, *not* the tpacket_thdr
			log_pcap_packet(&pcap,frame,packet.i->l2hlen + scribble,&pll);
			if(scribble){
				frame += thdr->tp_mac;
			}
		}
	}
	if(octx->packet_read){
		octx->packet_read(&packet);
	}
	return 0;
}