/**************************************************************************** ** 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); }