/****************************************************************************
** File: datalink.c
**
** Author: Mike Borella
**
** Comments: Generic datalink module
**
** $Id: datalink.c,v 1.25 2002/01/04 17:24:38 mborella Exp $
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program 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 Library General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/
#include "global.h"
#include "error.h"
#include "datalink.h"
#include "ethernet.h"
#include "loopback.h"
#include "slip.h"
#include "raw.h"
#include "ppp.h"
#include "padding.h"
#include "payload.h"
#include "stats.h"
#include "dynports.h"
extern struct arg_t * my_args;
extern int packet_displayed;
extern int start_of_packet;
extern FILE * outfile;
/* Map for datalink types */
strmap_t datalink_type_map[] =
{
{ DATALINK_TYPE_ETHERNET, "ethernet" },
{ DATALINK_TYPE_8023, "802.3" },
{ DATALINK_TYPE_TOKENBUS, "token bus" },
{ DATALINK_TYPE_TOKENRING, "token ring" },
{ DATALINK_TYPE_METRONET, "metro net" },
{ DATALINK_TYPE_HDLC, "HDLC" },
{ DATALINK_TYPE_CHARSYNCH, "character synchronous" },
{ DATALINK_TYPE_IBMC2C, "IBM channel-to-channel" },
{ DATALINK_TYPE_FDDI, "FDDI" },
{ DATALINK_TYPE_NULL, "null" },
{ DATALINK_TYPE_SLIP, "SLIP" },
{ DATALINK_TYPE_PPP, "PPP" },
{ DATALINK_TYPE_RAWIP, "raw ip" },
{ 0, ""}
};
/*----------------------------------------------------------------------------
**
** datalink_pcap()
**
** Libpcap specific wrapper for the generic datalink function
**
**----------------------------------------------------------------------------
*/
void datalink_pcap(u_char * user, const struct pcap_pkthdr * h, u_char * pkt)
{
int linktype = -1;
u_int32_t * link;
struct timeval tv;
/* Translate the link type */
link = (u_int32_t *) user;
switch(*link)
{
case DLT_NULL:
linktype = DATALINK_TYPE_NULL;
break;
case DLT_EN10MB:
linktype = DATALINK_TYPE_ETHERNET;
break;
case DLT_SLIP:
linktype = DATALINK_TYPE_SLIP;
break;
case DLT_PPP:
linktype = DATALINK_TYPE_PPP;
break;
#ifdef DLT_RAW /* Not supported in some arch or older pcap versions */
case DLT_RAW:
linktype = DATALINK_TYPE_RAWIP;
break;
#endif
default:
error_fatal("\ncannot handle data link type %d", link);
}
/*
* Copy the timestamp our own timeval struct to avoid compilation
* errors with older versions of libpcap.
*/
tv.tv_sec = h->ts.tv_sec;
tv.tv_usec = h->ts.tv_usec;
/* Call the generic datalink function */
datalink(linktype, tv, h->caplen, h->len, pkt);
}
/*----------------------------------------------------------------------------
**
** datalink()
**
**----------------------------------------------------------------------------
*/
void datalink(int linktype, struct timeval ts, u_int32_t captured_length,
u_int32_t media_length, u_int8_t * pkt)
{
packet_t packet;
static int count = 1; /* count of the number of packets */
/*
* For minimal mode. We haven't displayed part of a packet yet...
* Set the start of packet flag so that we can display a nicer separator
*/
packet_displayed = 0;
start_of_packet = 1;
/*
* Reset the stats counted flag and unpause the counting if paused.
* This avoids the double-counting of encapsulated headers.
*/
stats_reset();
stats_unpause();
/*
* Set up packet into data structure
*/
packet.contents = my_malloc(captured_length+1);
memcpy(packet.contents, pkt, captured_length);
packet.current = &packet.contents[0];
packet.end = &packet.contents[0] + captured_length;
packet.apparent_end = packet.end;
packet.media_length = media_length;
snprintf(packet.timestamp, PACKET_TIMESTAMP_LEN, "%u.%06u",
(u_int32_t) ts.tv_sec, (u_int32_t) ts.tv_usec);
/*
* If we're in minimal mode, start off with the count number
* and the optional packet timestamp
*/
if (my_args->m)
{
display_minimal((u_int8_t *) &count, 4, DISP_DEC);
display_minimal_string(" ");
count ++;
if (!my_args->T)
{
display_minimal_string(packet.timestamp);
display_minimal_string(" ");
}
}
/*
* Delete any remaining hex buffer contents
*/
hexbuffer_kill();
/*
* Determine what to do next
*/
switch(linktype)
{
case DATALINK_TYPE_NULL:
dump_loopback(&packet);
break;
case DATALINK_TYPE_ETHERNET:
dump_ethernet(&packet);
break;
case DATALINK_TYPE_SLIP:
dump_slip(&packet);
break;
case DATALINK_TYPE_PPP:
dump_ppp(&packet);
break;
case DATALINK_TYPE_RAWIP:
dump_raw(&packet);
break;
default:
error_fatal("\ncannot handle data link type %d", linktype);
}
/*
* Make sure we set the layer back to a null value in case one of
* the layers was suppressed.
*/
set_layer(LAYER_NONE);
/*
* Both payload and padding shouldn't be displayed in minimal mode
*/
if (!my_args->m)
{
/*
* If there is any remaining data and the user wants to see it, dump it
* out now
*/
if (my_args->p && get_packet_apparentbytesleft(&packet))
dump_payload(&packet);
/*
* If there is a padding and the user wants to see it, dump it out now
*/
if (my_args->d && packet_haspadding(&packet))
dump_padding(&packet);
}
/*
* For minimal mode, finish with a carriage return
*/
if (my_args->m && packet_displayed)
{
display_minimal_cr();
display_minimal_cr();
}
/*
* Time out stale dynamic port mappings
*/
dynports_timeout();
/*
* Deallocate memory
*/
my_free(packet.contents);
}
syntax highlighted by Code2HTML, v. 0.9.1