Index: unk/lib/protocols.c
===================================================================
--- /trunk/lib/protocols.c	(revision 1283)
+++ 	(revision )
@@ -1,1161 +1,0 @@
-/* This file has the various helper functions used to decode various protocols 
- *
- * $Id$
- */ 
-#include "libtrace.h"
-#include "libtrace_int.h"
-#include <assert.h>
-#include <stdio.h>
-
-#ifndef WIN32
-#include <net/if_arp.h>
-#endif
-
-#ifndef ARPHRD_ETHER
-#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
-#endif
-
-#ifndef ARPHRD_PPP
-#define ARPHRD_PPP      512
-#endif
-
-
-static void *trace_get_payload_from_llcsnap(void *link,
-		uint16_t *type, uint32_t *remaining);
-
-/* Returns the payload from 802.3 ethernet.  Type optionally returned in
- * "type" in host byte order.  This will return a vlan header.
- */
-static void *trace_get_payload_from_ethernet(void *ethernet, 
-		uint16_t *type,
-		uint32_t *remaining)
-{
-	libtrace_ether_t *eth = (libtrace_ether_t*)ethernet;
-
-	if (remaining) {
-		if (*remaining < sizeof(*eth))
-			return NULL;
-		*remaining-=sizeof(*eth);
-	}
-
-	if (type)
-		*type = ntohs(eth->ether_type);
-
-	return (void*)((char *)eth + sizeof(*eth));
-}
-
-/* skip any 802.1q headers if necessary 
- * type is input/output
- */
-void *trace_get_vlan_payload_from_ethernet_payload(void *ethernet, uint16_t *type,
-		uint32_t *remaining)
-{
-	assert(type && "You must pass a type in!");
-
-	if (*type == 0x8100) {
-		libtrace_8021q_t *vlanhdr = (libtrace_8021q_t *)ethernet;
-
-		if (remaining) {
-			if (*remaining < sizeof(libtrace_8021q_t))
-				return NULL;
-
-			*remaining=*remaining-sizeof(libtrace_8021q_t);
-		}
-
-		*type = ntohs(vlanhdr->vlan_ether_type);
-
-		return (void*)((char *)ethernet + sizeof(*vlanhdr));
-	}
-
-	return ethernet;
-}
-
-/* skip any MPLS headers if necessary, guessing what the next type is
- * type is input/output.  If the next type is "ethernet" this will
- * return a type of 0x0000.
- */
-static void *trace_get_mpls_payload_from_ethernet_payload(void *ethernet,
-		uint16_t *type, uint32_t *remaining)
-{
-	assert(type && "You must pass a type in!");
-
-	if (*type == 0x8847) {
-		if ((((char*)ethernet)[2]&0x01)==0) {
-			*type = 0x8847;
-		}
-		else {
-			if (!remaining || *remaining>=5) {
-				switch (((char*)ethernet)[4]&0xF0) {
-					case 0x40:
-						*type = 0x0800;
-						break;
-					case 0x60:
-						*type = 0x86DD;
-						break;
-					default:
-						/* Ethernet */
-						*type = 0;
-				}
-			}
-		}
-		ethernet=(char*)ethernet+4;
-		if (remaining) {
-			if (*remaining<4)
-				return NULL;
-			else
-				*remaining-=4;
-		}
-
-
-		return ethernet;
-	}
-	else
-		return NULL;
-}
-
-static void *trace_get_payload_from_80211(void *link, uint16_t *type, uint32_t *remaining)
-{
-	libtrace_80211_t *wifi;
-	uint16_t *eth; /* ethertype */
-	int8_t extra = 0; /* how many QoS bytes to skip */
-	
-	if (remaining && *remaining < sizeof(libtrace_80211_t))
-		return NULL;
-
-	wifi=(libtrace_80211_t*)link;
-
-	/* Data packet? */
-	if (wifi->type != 2) {
-		return NULL;
-	}
-
-	/* If FromDS and ToDS are both set then we have a four-address
-	 * frame. Otherwise we have a three-address frame */
-	if (!(wifi->to_ds && wifi->from_ds)) 
-		extra -= 6; 
-	
-	/* Indicates QoS field present, see IEEE802.11e-2005 pg 21 */
-	if (wifi->subtype & 0x8) 
-		extra += 2;
-
-	if (remaining && *remaining < sizeof(*eth))
-		return NULL;
-
-	eth=(uint16_t *)((char*)wifi+sizeof(*wifi)+extra);
-	
-	if (*eth == 0xaaaa)
-		/* Payload contains an 802.2 LLC/SNAP frame */
-		return trace_get_payload_from_llcsnap((void *)eth, type, remaining);
-			
-	/* Otherwise we assume an Ethernet II frame */
-	if (type) *type=ntohs(*eth);
-	if (remaining) *remaining = *remaining - sizeof(libtrace_80211_t) - extra - sizeof(*eth);
-	
-	return (void*)((char*)eth+sizeof(*eth));
-}
-
-/* NB: type is returned as an ARPHRD_ type for SLL*/
-void *trace_get_payload_from_linux_sll(const void *link,
-		uint16_t *type, uint32_t *remaining) 
-{
-	libtrace_sll_header_t *sll;
-
-	sll = (libtrace_sll_header_t*) link;
-
-	if (remaining) {
-		if (*remaining < sizeof(*sll))
-			return NULL;
-		*remaining-=sizeof(*sll);
-	}
-
-	/* What kind of wacked out header, has this in host order?! */
-	if (type) *type = ntohs(sll->hatype);
-
-	return (void*)((char*)sll+sizeof(*sll));
-
-}
-
-DLLEXPORT
-void *trace_get_payload_from_atm(void *link,
-		uint8_t *type, uint32_t *remaining)
-{
-	libtrace_atm_capture_cell_t *cell;
-	if (remaining && *remaining<sizeof(libtrace_atm_capture_cell_t))
-		return NULL;
-	cell=(libtrace_atm_capture_cell_t*)link;
-
-	if (type)
-		*type=cell->pt;
-
-	if (remaining)
-		*remaining-=sizeof(libtrace_atm_capture_cell_t);
-
-	return ((char*)link)+sizeof(libtrace_atm_capture_cell_t);
-}
-
-static void *trace_get_payload_from_llcsnap(void *link,
-		uint16_t *type, uint32_t *remaining)
-{
-	/* 64 byte capture. */
-	libtrace_llcsnap_t *llc = (libtrace_llcsnap_t*)link;
-
-	if (remaining) {
-		if (*remaining < sizeof(libtrace_llcsnap_t))
-			return NULL;
-		*remaining-=(sizeof(libtrace_llcsnap_t));
-	}
-
-	llc = (libtrace_llcsnap_t*)((char *)llc);
-
-	if (type) *type = ntohs(llc->type);
-
-	return (void*)((char*)llc+sizeof(*llc));
-}
-
-static void *trace_get_payload_from_ppp(void *link, 
-		uint16_t *type, uint32_t *remaining)
-{
-	/* 64 byte capture. */
-	libtrace_ppp_t *ppp = (libtrace_ppp_t*)link;
-
-	if (remaining) {
-		if (*remaining < sizeof(libtrace_ppp_t))
-			return NULL;
-		*remaining-=sizeof(libtrace_ppp_t);
-	}
-
-	if (type) {
-		switch(ntohs(ppp->protocol)) {
-			case 0x0021: *type = 0x0800; break;
-		}
-	}
-
-
-	return (void*)((char *)ppp+sizeof(*ppp));
-}
-
-typedef struct libtrace_chdlc_t {
-	uint8_t address;	/** 0xF0 for unicast, 0xF8 for multicast */
-	uint8_t control;
-	uint16_t ethertype;
-} libtrace_chdlc_t;
-
-static void *trace_get_payload_from_chdlc(void *link, 
-		uint16_t *type, uint32_t *remaining)
-{
-	libtrace_chdlc_t *chdlc = (libtrace_chdlc_t*)link;
-
-	if (remaining) {
-		if (*remaining < sizeof(libtrace_chdlc_t))
-			return NULL;
-		*remaining-=sizeof(libtrace_chdlc_t);
-	}
-
-	if (type) {
-		*type=ntohs(chdlc->ethertype);
-	}
-
-
-	return (void*)((char *)chdlc+sizeof(*chdlc));
-}
-
-static void *trace_get_payload_from_pflog(void *link,
-		uint16_t *type, uint32_t *remaining)
-{
-	libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
-    if (remaining) {
-		if (*remaining<sizeof(*pflog)) 
-			return NULL;
-		*remaining-=sizeof(*pflog);
-	}
-	if (type) {
-		switch(pflog->af) {
-			case AF_INET6: *type=0x86DD; break;
-			case AF_INET:  *type=0x0800; break;
-			default:
-				      /* Unknown */
-				      return NULL;
-		}
-	}
-	return (void*)((char*)pflog+ sizeof(*pflog));
-}
-
-/* Returns the 'payload' of the prism header, which is the 802.11 frame */
-static void *trace_get_payload_from_prism (const void *link,
-		libtrace_linktype_t *type, uint32_t *remaining)
-{
-	if (remaining) {
-		if (*remaining<144) 
-			return NULL;
-		*remaining-=144;
-	}
-
-	if (type) *type = TRACE_TYPE_80211;
-
-	return (void *) ((char*)link+144);
-}
-
-/* Returns the 'payload' of the radiotap header, which is the 802.11 frame */
-static void *trace_get_payload_from_radiotap (const void *link, 
-		libtrace_linktype_t *type, uint32_t *remaining)
-{
-	struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link;
-	uint16_t rtaplen = bswap_le_to_host16(rtap->it_len);
-	if (remaining) {
-		if (*remaining < rtaplen)
-			return NULL;
-		*remaining -= rtaplen;
-	}
-
-	if (type) *type = TRACE_TYPE_80211;
-
-	return (void*) ((char*)link + rtaplen);
-}
-
-void *trace_get_payload_from_link(void *link, libtrace_linktype_t linktype, 
-		uint16_t *type, uint32_t *remaining)
-{
-	void *l = NULL;
-	uint16_t dummytype;
-	
-	switch(linktype) {
-		case TRACE_TYPE_80211_PRISM:
-			l = trace_get_payload_from_prism(link,&linktype,remaining);
-			return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
-		case TRACE_TYPE_80211_RADIO:
-			l = trace_get_payload_from_radiotap(link,&linktype,remaining);
-			return (l ? trace_get_payload_from_link(l, TRACE_TYPE_80211, type, remaining) : NULL);
-		case TRACE_TYPE_80211:
-			return trace_get_payload_from_80211(link,type,remaining);
-
-		case TRACE_TYPE_ETH:
-			return trace_get_payload_from_ethernet(link,type,remaining);
-		case TRACE_TYPE_NONE:
-			if ((*(char*)link&0xF0) == 0x40)
-				*type=0x0800;
-			else if ((*(char*)link&0xF0) == 0x60)
-				*type=0x86DD;
-			return link; /* I love the simplicity */
-		case TRACE_TYPE_LINUX_SLL:
-			l = trace_get_payload_from_linux_sll(link,&dummytype,remaining);
-			if (type) *type = dummytype;
-			return (l ? trace_get_payload_from_link(l,
-						arphrd_type_to_libtrace(dummytype), type, remaining) : NULL);
-			
-		case TRACE_TYPE_PFLOG:
-			return trace_get_payload_from_pflog(link,type,remaining);
-		case TRACE_TYPE_PPP:
-			return trace_get_payload_from_ppp(link,type,remaining);
-		case TRACE_TYPE_ATM:
-			l=trace_get_payload_from_atm(link,NULL,remaining);
-			return (l ? trace_get_payload_from_llcsnap(l,
-						type, remaining):NULL);
-		case TRACE_TYPE_DUCK:
-			return NULL; /* duck packets have no payload! */
-		case TRACE_TYPE_METADATA:
-			return NULL; /* The payload is in these packets does
-					not correspond to a genuine link-layer
-					*/
-		default:
-			break;
-	}
-	fprintf(stderr, "Don't understand link layer type %i in trace_get_payload_from_link()\n",
-		linktype);
-	return NULL;
-}
-
-libtrace_ip_t *trace_get_ip(libtrace_packet_t *packet) 
-{
-	uint16_t ethertype;
-	void *ret;
-
-	uint32_t remaining = trace_get_capture_length(packet);
-
-	ret = trace_get_layer3(packet,&ethertype,&remaining);
-
-	if (!ret || ethertype!=0x0800)
-		return NULL;
-
-	/* Not an IPv4 packet */
-	if (((libtrace_ip_t*)ret)->ip_v != 4)
-		return NULL;
-
-	return (libtrace_ip_t*)ret;
-}
-
-libtrace_ip6_t *trace_get_ip6(libtrace_packet_t *packet) 
-{
-	uint16_t ethertype;
-	void *ret;
-
-	uint32_t remaining = trace_get_capture_length(packet);
-
-	ret = trace_get_layer3(packet,&ethertype,&remaining);
-
-	if (!ret || ethertype!=0x86DD)
-		return NULL;
-
-	return (libtrace_ip6_t*)ret;
-}
-
-#define SW_IP_OFFMASK 0xff1f
-
-DLLEXPORT void *trace_get_payload_from_ip(libtrace_ip_t *ipptr, uint8_t *prot,
-		uint32_t *remaining) 
-{
-        void *trans_ptr = 0;
-
-        if ((ntohs(ipptr->ip_off) & SW_IP_OFFMASK) != 0) {
-		return NULL;
-	}
-
-	if (remaining) {
-		if (*remaining<(ipptr->ip_hl*4U)) {
-			return NULL;
-		}
-		*remaining-=(ipptr->ip_hl * 4);
-	}
-
-        trans_ptr = (void *)((char *)ipptr + (ipptr->ip_hl * 4));
-
-	if (prot) *prot = ipptr->ip_p;
-
-        return trans_ptr;
-}
-
-void *trace_get_payload_from_ip6(libtrace_ip6_t *ipptr, uint8_t *prot,
-		uint32_t *remaining) 
-{
-	void *payload = (char*)ipptr+sizeof(libtrace_ip6_t);
-	uint8_t nxt = ipptr->nxt;
-
-	if (remaining) {
-		if (*remaining<sizeof(libtrace_ip6_t))
-			return NULL;
-		*remaining-=sizeof(libtrace_ip6_t);
-	}
-
-	while(1) {
-		switch (nxt) {
-			case 0: /* hop by hop options */
-			case 43: /* routing */
-			case 44: /* fragment */
-			case 50: /* ESP */
-			case 51: /* AH */
-			case 60: /* Destination options */
-				{
-					uint16_t len=((libtrace_ip6_ext_t*)payload)->len
-					+sizeof(libtrace_ip6_ext_t);
-
-					if (remaining) {
-						if (*remaining < len) {
-							/* Snap too short */
-							return NULL;
-						}
-						*remaining-=len;
-					}
-
-					payload=(char*)payload+len;
-					nxt=((libtrace_ip6_ext_t*)payload)->nxt;
-					continue;
-				}
-			default:
-				if (prot) *prot=nxt;
-				return payload;
-		}
-	}
-}
-
-DLLEXPORT void *trace_get_packet_meta(const libtrace_packet_t *packet, 
-		libtrace_linktype_t *linktype,
-		uint32_t *remaining)
-{
-	uint32_t dummyrem;
-
-	assert(packet != NULL);
-	assert(linktype != NULL);
-	
-	if (remaining == NULL) 
-		remaining = &dummyrem;
-	
-	void *pktbuf = trace_get_packet_buffer(packet, linktype, remaining);
-	switch (*linktype) {
-		case TRACE_TYPE_LINUX_SLL:
-		case TRACE_TYPE_80211_RADIO:
-		case TRACE_TYPE_80211_PRISM:
-			return pktbuf;
-		/* Non metadata packets */
-		case TRACE_TYPE_HDLC_POS:
-		case TRACE_TYPE_ETH:
-		case TRACE_TYPE_ATM:
-		case TRACE_TYPE_80211:
-		case TRACE_TYPE_NONE:
-		case TRACE_TYPE_PFLOG:
-		case TRACE_TYPE_POS:
-		case TRACE_TYPE_AAL5:
-		case TRACE_TYPE_DUCK:
-		case TRACE_TYPE_LLCSNAP:
-		case TRACE_TYPE_PPP:
-		case TRACE_TYPE_METADATA:
-			return NULL;
-	}
-
-	/* Shouldn't get here */
-	return NULL;
-}
-
-DLLEXPORT void *trace_get_payload_from_meta(const void *meta,
-		libtrace_linktype_t *linktype,
-		uint32_t *remaining)
-{
-	void *nexthdr; 
-	uint16_t arphrd;
-	
-	assert(meta != NULL);
-	assert(linktype != NULL);
-	assert(remaining != NULL);
-	
-	switch(*linktype) {
-		case TRACE_TYPE_LINUX_SLL:
-			nexthdr = trace_get_payload_from_linux_sll(meta,
-					&arphrd, remaining);
-			*linktype = arphrd_type_to_libtrace(arphrd);
-			return nexthdr;
-		case TRACE_TYPE_80211_RADIO:
-			nexthdr = trace_get_payload_from_radiotap(meta,
-					linktype, remaining);
-			return nexthdr;
-		case TRACE_TYPE_80211_PRISM:
-			nexthdr = trace_get_payload_from_prism(meta,
-					linktype, remaining);
-			return nexthdr;
-		case TRACE_TYPE_HDLC_POS:
-		case TRACE_TYPE_ETH:
-		case TRACE_TYPE_ATM:
-		case TRACE_TYPE_80211:
-		case TRACE_TYPE_NONE:
-		case TRACE_TYPE_PFLOG:
-		case TRACE_TYPE_POS:
-		case TRACE_TYPE_AAL5:
-		case TRACE_TYPE_DUCK:
-		case TRACE_TYPE_LLCSNAP:
-		case TRACE_TYPE_PPP:
-		case TRACE_TYPE_METADATA:
-			/* In this case, the pointer passed in does not point
-			 * to a metadata header and so we cannot get the
-			 * payload.
-			 */
-			return NULL;
-	}
-	/* Shouldn't get here */
-	return NULL;
-}
-
-DLLEXPORT void *trace_get_layer2(const libtrace_packet_t *packet,
-		libtrace_linktype_t *linktype,
-		uint32_t *remaining) 
-{
-	uint32_t dummyrem;
-	
-	assert(packet != NULL);
-	assert(linktype != NULL);
-
-	if (remaining == NULL)
-		remaining = &dummyrem;
-	
-	void *meta = trace_get_packet_meta(packet, linktype, remaining);
-
-	/* If there are no meta-data headers, we just return the start of the
-	 * packet buffer, along with the linktype, etc.
-	 */
-	if (meta == NULL) 
-		return trace_get_packet_buffer(packet, linktype, remaining);
-	
-	/* If there are meta-data headers, we need to skip over them until we
-	 * find a non-meta data header and return that.
-	 */
-	for(;;) {
-		void *nexthdr = trace_get_payload_from_meta(meta, 
-				linktype, remaining);
-		if (nexthdr == NULL)
-			return meta;
-		meta = nexthdr;
-	}
-}
-
-DLLEXPORT void *trace_get_payload_from_layer2(void *link,
-		libtrace_linktype_t linktype,
-		uint16_t *ethertype,
-		uint32_t *remaining)
-{
-	void *l;
-	switch(linktype) {
-		/* Packet Metadata headers, not layer2 headers */
-		case TRACE_TYPE_80211_PRISM:
-		case TRACE_TYPE_80211_RADIO:
-		case TRACE_TYPE_LINUX_SLL:
-			return NULL;
-
-		/* duck packets have no payload! */
-		case TRACE_TYPE_DUCK:
-			return NULL;
-
-		/* The payload is in these packets does
-		   not correspond to a genuine link-layer
-		   */
-		case TRACE_TYPE_METADATA:
-			return NULL;
-
-		case TRACE_TYPE_80211:
-			return trace_get_payload_from_80211(link,ethertype,remaining);
-		case TRACE_TYPE_ETH:
-			return trace_get_payload_from_ethernet(link,ethertype,remaining);
-		case TRACE_TYPE_NONE:
-			if ((*(char*)link&0xF0) == 0x40)
-				*ethertype=0x0800;
-			else if ((*(char*)link&0xF0) == 0x60)
-				*ethertype=0x86DD;
-			return link; /* I love the simplicity */
-		case TRACE_TYPE_PFLOG:
-			return trace_get_payload_from_pflog(link,ethertype,remaining);
-		case TRACE_TYPE_PPP:
-			return trace_get_payload_from_ppp(link,ethertype,remaining);
-		case TRACE_TYPE_ATM:
-			l=trace_get_payload_from_atm(link,NULL,remaining);
-			/* FIXME: We shouldn't skip llcsnap here, we should return
-			 * an ethertype for it (somehow)
-			 */
-			return (l ? trace_get_payload_from_llcsnap(l,
-						ethertype, remaining):NULL);
-		case TRACE_TYPE_LLCSNAP:
-			return trace_get_payload_from_llcsnap(link,ethertype,remaining);
-
-		case TRACE_TYPE_HDLC_POS:
-			return trace_get_payload_from_chdlc(link,ethertype,
-					remaining);
-		/* TODO: Unsupported */
-		case TRACE_TYPE_POS:
-		case TRACE_TYPE_AAL5:
-			return NULL;
-	}
-	return NULL;
-
-}
-
-DLLEXPORT void *trace_get_layer3(const libtrace_packet_t *packet,
-		uint16_t *ethertype,
-		uint32_t *remaining)
-{
-	void *iphdr;
-	uint16_t dummy_ethertype;
-	void *link;
-	uint32_t dummy_remaining;
-	libtrace_linktype_t linktype;
-
-	if (!ethertype) ethertype=&dummy_ethertype;
-
-	if (!remaining) remaining=&dummy_remaining;
-
-	/* use l3 cache */
-	if (packet->l3_header)
-	{
-		link = trace_get_packet_buffer(packet,&linktype,remaining);
-
-		if (!link)
-			return NULL;
-
-		*ethertype = packet->l3_ethertype;
-		*remaining -= (packet->l3_header - link);
-
-		return packet->l3_header;
-	}
-
-	link = trace_get_layer2(packet,&linktype,remaining);
-
-	iphdr = trace_get_payload_from_layer2(
-			link,
-			linktype,
-			ethertype,
-			remaining);
-
-	if (!iphdr)
-		return NULL;
-
-	for(;;) {
-		switch(*ethertype) {
-		case 0x8100: /* VLAN */
-			iphdr=trace_get_vlan_payload_from_ethernet_payload(
-					  iphdr,ethertype,NULL);
-			continue;
-		case 0x8847: /* MPLS */
-			iphdr=trace_get_mpls_payload_from_ethernet_payload(
-					  iphdr,ethertype,NULL);
-
-			if (iphdr && ethertype == 0x0) {
-				iphdr=trace_get_payload_from_ethernet(
-						iphdr,ethertype,NULL);
-			}
-			continue;
-		default:
-			break;
-		}
-
-		break;
-	}
-
-	/* Store values in the cache for later */
-	/* Cast away constness, nasty, but this is just a cache */
-	((libtrace_packet_t*)packet)->l3_ethertype = *ethertype;
-	((libtrace_packet_t*)packet)->l3_header = iphdr;
-
-	return iphdr;
-}
-
-DLLEXPORT void *trace_get_transport(const libtrace_packet_t *packet, 
-		uint8_t *proto,
-		uint32_t *remaining
-		) 
-{
-	uint8_t dummy_proto;
-	uint16_t ethertype;
-	uint32_t dummy_remaining;
-	void *transport;
-
-	if (!proto) proto=&dummy_proto;
-
-	if (!remaining) remaining=&dummy_remaining;
-
-	transport = trace_get_layer3(packet,&ethertype,remaining);
-
-	if (!transport)
-		return NULL;
-
-	switch (ethertype) {
-		case 0x0800: /* IPv4 */
-			transport=trace_get_payload_from_ip(
-				(libtrace_ip_t*)transport, proto, remaining);
-			/* IPv6 */
-			if (transport && *proto == 41) {
-				transport=trace_get_payload_from_ip6(
-				 (libtrace_ip6_t*)transport, proto,remaining);
-			}
-			return transport;
-		case 0x86DD: /* IPv6 */
-			return trace_get_payload_from_ip6(
-				(libtrace_ip6_t*)transport, proto, remaining);
-			
-		default:
-			*proto=0;
-			return NULL;
-	}
-
-}
-
-DLLEXPORT libtrace_tcp_t *trace_get_tcp(libtrace_packet_t *packet) {
-	uint8_t proto;
-	libtrace_tcp_t *tcp;
-
-	tcp=(libtrace_tcp_t*)trace_get_transport(packet,&proto,NULL);
-
-	if (!tcp || proto != 6)
-		return NULL;
-
-	return (libtrace_tcp_t*)tcp;
-}
-
-DLLEXPORT libtrace_tcp_t *trace_get_tcp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
-{
-	libtrace_tcp_t *tcpptr = 0;
-
-	if (ip->ip_p == 6)  {
-		tcpptr = (libtrace_tcp_t *)
-			trace_get_payload_from_ip(ip, NULL, remaining);
-	}
-
-	return tcpptr;
-}
-
-DLLEXPORT libtrace_udp_t *trace_get_udp(libtrace_packet_t *packet) {
-	uint8_t proto;
-	libtrace_udp_t *udp;
-
-	udp=(libtrace_udp_t*)trace_get_transport(packet,&proto,NULL);
-
-	if (!udp || proto != 17)
-		return NULL;
-
-	return udp;
-}
-
-DLLEXPORT libtrace_udp_t *trace_get_udp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
-{
-	libtrace_udp_t *udpptr = 0;
-
-	if (ip->ip_p == 17) {
-		udpptr = (libtrace_udp_t *)
-			trace_get_payload_from_ip(ip, NULL, remaining);
-	}
-
-	return udpptr;
-}
-
-DLLEXPORT libtrace_icmp_t *trace_get_icmp(libtrace_packet_t *packet) {
-	uint8_t proto;
-	libtrace_icmp_t *icmp;
-
-	icmp=(libtrace_icmp_t*)trace_get_transport(packet,&proto,NULL);
-
-	if (!icmp || proto != 1)
-		return NULL;
-
-	return icmp;
-}
-
-DLLEXPORT libtrace_icmp_t *trace_get_icmp_from_ip(libtrace_ip_t *ip, uint32_t *remaining)
-{
-	libtrace_icmp_t *icmpptr = 0;
-
-	if (ip->ip_p == 1)  {
-		icmpptr = (libtrace_icmp_t *)trace_get_payload_from_ip(ip, 
-				NULL, remaining);
-	}
-
-	return icmpptr;
-}
-
-DLLEXPORT void *trace_get_payload_from_udp(libtrace_udp_t *udp, uint32_t *remaining)
-{
-	if (remaining) {
-		if (*remaining < sizeof(libtrace_udp_t))
-			return NULL;
-		*remaining-=sizeof(libtrace_udp_t);
-	}
-	return (void*)((char*)udp+sizeof(libtrace_udp_t));
-}
-
-DLLEXPORT void *trace_get_payload_from_tcp(libtrace_tcp_t *tcp, uint32_t *remaining)
-{
-	unsigned int dlen = tcp->doff*4;
-	if (remaining) {
-		if (*remaining < dlen)
-			return NULL;
-		*remaining-=dlen;
-	}
-	return (void *)((char *)tcp+dlen);
-}
-
-DLLEXPORT void *trace_get_payload_from_icmp(libtrace_icmp_t *icmp, uint32_t *remaining)
-{
-	if (remaining) {
-		if (*remaining < sizeof(libtrace_icmp_t))
-			return NULL;
-		*remaining-=sizeof(libtrace_icmp_t);
-	}
-	return (char*)icmp+sizeof(libtrace_icmp_t);
-}
-
-struct ports_t {
-	uint16_t src;
-	uint16_t dst;
-};
-
-/* Return the client port
- */
-DLLEXPORT uint16_t trace_get_source_port(const libtrace_packet_t *packet)
-{
-	uint32_t remaining;
-	const struct ports_t *port = 
-		(const struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
-			NULL, &remaining);
-
-	/* snapped too early */
-	if (remaining<2)
-		return 0;
-
-	if (port)
-		return ntohs(port->src);
-	else
-		return 0;
-}
-
-/* Same as get_source_port except use the destination port */
-DLLEXPORT uint16_t trace_get_destination_port(const libtrace_packet_t *packet)
-{
-	uint32_t remaining;
-	struct ports_t *port = 
-		(struct ports_t*)trace_get_transport((libtrace_packet_t*)packet,
-			NULL, &remaining);
-	/* snapped to early */
-	if (remaining<4)
-		return 0;
-
-	if (port)
-		return ntohs(port->dst);
-	else
-		return 0;
-}
-
-/* Take a pointer to the start of an IEEE 802.11 MAC frame and return a pointer
- * to the source MAC address.  
- * If the frame does not contain a sender address, e.g. ACK frame, return NULL.
- * If the frame is a 4-address WDS frame, return TA, i.e. addr2.
- * NB: This function decodes the 802.11 header, so it assumes that there are no
- * bit-errors. If there are, all bets are off.
- */
-static
-uint8_t *get_source_mac_from_wifi(void *wifi) {
-	if (wifi == NULL) return NULL;
-	struct libtrace_80211_t *w = (struct libtrace_80211_t *) wifi;
-	
-	/* If the frame is of type CTRL */
-	if (w->type == 0x1) 
-		/* If bit 2 of the subtype field is zero, this indicates that
-		 * there is no transmitter address, i.e. the frame is either an
-		 * ACK or a CTS frame */
-		if ((w->subtype & 0x2) == 0)
-			return NULL;
-
-	/* Always return the address of the transmitter, i.e. address 2 */
-	return (uint8_t *) &w->mac2;
-}
-
-DLLEXPORT uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
-	void *link;
-	uint32_t remaining;
-	libtrace_linktype_t linktype;
-	assert(packet);
-	link = trace_get_layer2(packet,&linktype,&remaining);
-
-	if (!link)
-		return NULL;
-	
-	switch (linktype) {
-		case TRACE_TYPE_ETH:
-			return (uint8_t *)&(((libtrace_ether_t*)link)->ether_shost);
-		case TRACE_TYPE_80211:
-			return get_source_mac_from_wifi(link);
-		/* These packets don't have MAC addresses */
-		case TRACE_TYPE_POS:
-		case TRACE_TYPE_NONE:
-		case TRACE_TYPE_HDLC_POS:
-		case TRACE_TYPE_PFLOG:
-		case TRACE_TYPE_ATM:
-		case TRACE_TYPE_DUCK:
-		case TRACE_TYPE_METADATA:
-		case TRACE_TYPE_AAL5:
-		case TRACE_TYPE_LLCSNAP:
-		case TRACE_TYPE_PPP:
-			return NULL;
-
-		/* Metadata headers should already be skipped */
-		case TRACE_TYPE_LINUX_SLL:
-		case TRACE_TYPE_80211_PRISM:
-		case TRACE_TYPE_80211_RADIO:
-			assert(!"Metadata headers should already be skipped");
-			break;
-	}
-	fprintf(stderr,"%s not implemented for linktype %i\n", __func__, linktype);
-	assert(0);
-	return NULL;
-}
-
-DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) 
-{
-	void *link;
-	libtrace_linktype_t linktype;
-	uint32_t remaining;
-
-	link = trace_get_layer2(packet,&linktype,&remaining);
-
-	libtrace_80211_t *wifi;
-        libtrace_ether_t *ethptr = (libtrace_ether_t*)link;
-
-
-	if (!link)
-		return NULL;
-
-	switch (linktype) {
-		case TRACE_TYPE_80211:
-			wifi=(libtrace_80211_t*)link;
-			return (uint8_t*)&wifi->mac1;
-		case TRACE_TYPE_80211_RADIO:
-			wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
-					link,NULL,NULL);
-			return (uint8_t*)&wifi->mac1;
-		case TRACE_TYPE_80211_PRISM:
-			wifi=(libtrace_80211_t*)((char*)link+144);
-			return (uint8_t*)&wifi->mac1;
-		case TRACE_TYPE_ETH:
-			return (uint8_t*)&ethptr->ether_dhost;
-		case TRACE_TYPE_POS:
-		case TRACE_TYPE_NONE:
-		case TRACE_TYPE_ATM:
-		case TRACE_TYPE_HDLC_POS:
-		case TRACE_TYPE_LINUX_SLL:
-		case TRACE_TYPE_PFLOG:
-		case TRACE_TYPE_DUCK:
-		case TRACE_TYPE_METADATA:
-			/* No MAC address */
-			return NULL;
-		default:
-			break;
-	}
-	fprintf(stderr,"Not implemented\n");
-	assert(0);
-	return NULL;
-}
-
-DLLEXPORT struct sockaddr *trace_get_source_address(
-		const libtrace_packet_t *packet, struct sockaddr *addr)
-{
-	uint16_t ethertype;
-	uint32_t remaining;
-	void *l3;
-	struct ports_t *ports;
-	static struct sockaddr_storage dummy;
-
-	if (!addr)
-		addr=(struct sockaddr*)&dummy;
-
-	l3 = trace_get_layer3(packet,&ethertype,&remaining);
-
-	if (!l3)
-		return NULL;
-
-	switch (ethertype) {
-		case 0x0800: /* IPv4 */
-		{
-			struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
-			libtrace_ip_t *ip = (libtrace_ip_t*)l3;
-			ports = (struct ports_t*)
-				trace_get_payload_from_ip(ip,NULL,&remaining);
-			addr4->sin_family=AF_INET;
-			if (ports && remaining>=sizeof(*ports))
-				addr4->sin_port=ports->src;
-			else
-				addr4->sin_port=0;
-			addr4->sin_addr=ip->ip_src;
-			return addr;
-		}
-		case 0x86DD: /* IPv6 */
-		{
-			struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
-			libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
-			ports = (struct ports_t*)
-				trace_get_payload_from_ip6(ip6,NULL,&remaining);
-			addr6->sin6_family=AF_INET6;
-			if (ports && remaining>=sizeof(*ports))
-				addr6->sin6_port=ports->src;
-			else
-				addr6->sin6_port=0;
-			addr6->sin6_flowinfo=0;
-			addr6->sin6_addr=ip6->ip_src;
-			return addr;
-		}
-		default:
-			return NULL;
-	}
-}
-
-DLLEXPORT struct sockaddr *trace_get_destination_address(
-		const libtrace_packet_t *packet, struct sockaddr *addr)
-{
-	uint16_t ethertype;
-	uint32_t remaining;
-	void *l3;
-	struct ports_t *ports;
-	static struct sockaddr_storage dummy;
-
-	if (!addr)
-		addr=(struct sockaddr*)&dummy;
-
-	l3 = trace_get_layer3(packet,&ethertype,&remaining);
-
-	if (!l3)
-		return NULL;
-
-	switch (ethertype) {
-		case 0x0800: /* IPv4 */
-		{
-			struct sockaddr_in *addr4=(struct sockaddr_in*)addr;
-			libtrace_ip_t *ip = (libtrace_ip_t*)l3;
-			ports = (struct ports_t*)
-				trace_get_payload_from_ip(ip,NULL,&remaining);
-			addr4->sin_family=AF_INET;
-			if (ports && remaining>=sizeof(*ports))
-				addr4->sin_port=ports->dst;
-			else
-				addr4->sin_port=0;
-			addr4->sin_addr=ip->ip_dst;
-			return addr;
-		}
-		case 0x86DD: /* IPv6 */
-		{
-			struct sockaddr_in6 *addr6=(struct sockaddr_in6*)addr;
-			libtrace_ip6_t *ip6 = (libtrace_ip6_t*)l3;
-			ports = (struct ports_t*)
-				trace_get_payload_from_ip6(ip6,NULL,&remaining);
-			addr6->sin6_family=AF_INET6;
-			if (ports && remaining>=sizeof(*ports))
-				addr6->sin6_port=ports->dst;
-			else
-				addr6->sin6_port=0;
-			addr6->sin6_flowinfo=0;
-			addr6->sin6_addr=ip6->ip_dst;
-			return addr;
-		}
-		default:
-			return NULL;
-	}
-}
-
-/* parse an ip or tcp option
- * @param[in,out] ptr	the pointer to the current option
- * @param[in,out] len	the length of the remaining buffer
- * @param[out] type	the type of the option
- * @param[out] optlen 	the length of the option
- * @param[out] data	the data of the option
- *
- * @returns bool true if there is another option (and the fields are filled in)
- *               or false if this was the last option.
- *
- * This updates ptr to point to the next option after this one, and updates
- * len to be the number of bytes remaining in the options area.  Type is updated
- * to be the code of this option, and data points to the data of this option,
- * with optlen saying how many bytes there are.
- *
- * @note Beware of fragmented packets.
- * @author Perry Lorier
- */
-DLLEXPORT int trace_get_next_option(unsigned char **ptr,int *len,
-			unsigned char *type,
-			unsigned char *optlen,
-			unsigned char **data)
-{
-	if (*len<=0)
-		return 0;
-	*type=**ptr;
-	switch(*type) {
-		case 0: /* End of options */
-			return 0;
-		case 1: /* Pad */
-			(*ptr)++;
-			(*len)--;
-			return 1;
-		default:
-			*optlen = *(*ptr+1);
-			if (*optlen<2)
-				return 0; /* I have no idea wtf is going on
-					   * with these packets
-					   */
-			(*len)-=*optlen;
-			(*data)=(*ptr+2);
-			(*ptr)+=*optlen;
-			if (*len<0)
-				return 0;
-			return 1;
-	}
-	assert(0);
-}
-
-
