/*
*
* Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
* All rights reserved.
*
* This file is part of libtrace.
*
* This code has been developed by the University of Waikato WAND
* research group. For further information please see http://www.wand.net.nz/
*
* libtrace is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* libtrace is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*
*/
#include "libtrace_int.h"
#include "libtrace.h"
#include "protocols.h"
#include
#ifdef HAVE_WANDDER
#include
#endif
/* This file contains all the protocol decoding functions for the meta-data
* headers that may be prepended to captured packets.
*
* Supported protocols include (but are not limited to):
* Linux SLL
* PFLOG
* RadioTap
* Prism
*/
/* NB: type is returned as an ARPHRD_ type for SLL*/
void *trace_get_payload_from_linux_sll(const void *link,
uint16_t *arphrd_type, uint16_t *next,
uint32_t *remaining)
{
libtrace_sll_header_t *sll;
sll = (libtrace_sll_header_t*) link;
if (remaining) {
if (*remaining < sizeof(*sll)) {
*remaining = 0;
return NULL;
}
*remaining-=sizeof(*sll);
}
/* The SLL header is actually in place of a link layer header, so
* we want to use the protocol field to tell our caller what the
* next header is going to be */
if (next) *next = (libtrace_linktype_t)(ntohs(sll->protocol));
if (arphrd_type) *arphrd_type = ntohs(sll->hatype);
return (void*)((char*)sll+sizeof(*sll));
}
/* NB: type is returned as an ethertype */
static void *trace_get_payload_from_pflog(const void *link,
libtrace_linktype_t *type, uint32_t *remaining)
{
libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
if (remaining) {
if (*remainingit_len);
if (remaining) {
if (*remaining < rtaplen) {
*remaining = 0;
return NULL;
}
*remaining -= rtaplen;
}
if (type) *type = TRACE_TYPE_80211;
return (void*) ((char*)link + rtaplen);
}
static void *trace_get_payload_from_etsili(const void *link,
libtrace_linktype_t *type, uint32_t *remaining) {
#ifdef HAVE_WANDDER
wandder_etsispec_t *dec;
uint8_t *ccptr;
/* XXX Bit annoying to be creating and freeing this every time */
dec = wandder_create_etsili_decoder();
wandder_attach_etsili_buffer(dec, (uint8_t *)link, *remaining, false);
ccptr = wandder_etsili_get_cc_contents(dec, remaining);
/* Assuming all CCs are IP for now */
*type = TRACE_TYPE_NONE;
wandder_free_etsili_decoder(dec);
return ccptr;
#else
*remaining = NULL;
return NULL;
#endif
}
DLLEXPORT void *trace_get_packet_meta(const libtrace_packet_t *packet,
libtrace_linktype_t *linktype,
uint32_t *remaining)
{
uint32_t dummyrem;
void *pktbuf = NULL;
assert(packet != NULL);
assert(linktype != NULL);
if (remaining == NULL)
remaining = &dummyrem;
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:
case TRACE_TYPE_ERF_META:
case TRACE_TYPE_ETSILI:
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:
case TRACE_TYPE_NONDATA:
case TRACE_TYPE_OPENBSD_LOOP:
case TRACE_TYPE_UNKNOWN:
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 = 0;
uint16_t next = 0;
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, &next, remaining);
/* Ethernet header is usually absent in SLL captures,
* so we don't want to skip it just yet */
if (arphrd_type_to_libtrace(arphrd) == TRACE_TYPE_ETH && next != 0x0060)
*linktype = TRACE_TYPE_NONE;
else
*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_PFLOG:
nexthdr = trace_get_payload_from_pflog(meta,
linktype, remaining);
return nexthdr;
case TRACE_TYPE_ETSILI:
nexthdr = trace_get_payload_from_etsili(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_POS:
case TRACE_TYPE_AAL5:
case TRACE_TYPE_DUCK:
case TRACE_TYPE_LLCSNAP:
case TRACE_TYPE_PPP:
case TRACE_TYPE_METADATA:
case TRACE_TYPE_NONDATA:
case TRACE_TYPE_OPENBSD_LOOP:
case TRACE_TYPE_ERF_META:
case TRACE_TYPE_UNKNOWN:
/* 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;
}