This is a homework assignment, and I have to extract Ethernet data from the packet . also I should count tne number of different protocols.
I uploaded the whole program . I appreciate if anybody can help me.
I saw similar code on this site.
Do yu think this code is correct , because Eternet header has 8 byte preamle so destination addr should be p[8] not p[0] . Am I right?
here is the code:
#define RETSIGTYPE void
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <pcap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef setsignal_h
#define setsignal_h
RETSIGTYPE (*setsignal(int, RETSIGTYPE (*)(int)))(int);
#endif
char cpre580f98[] = "netdump";
void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p);
int packettype;
char *program_name;
/* Externs */
extern void bpf_dump(struct bpf_program *, int);
extern char *copy_argv(char **);
/* Forwards */
void program_ending(int);
/* Length of saved portion of packet. */
int snaplen = 1500;;
static pcap_t *pd;
extern int optind;
extern int opterr;
extern char *optarg;
int pflag = 0, aflag = 0;
int
main(int argc, char **argv)
{
int cnt, op, i, done = 0;
bpf_u_int32 localnet, netmask;
char *cp, *cmdbuf, *device;
struct bpf_program fcode;
void (*oldhandler)(int);
u_char *pcap_userdata;
char ebuf[PCAP_ERRBUF_SIZE];
cnt = -1;
device = NULL;
if ((cp = strrchr(argv[0], '/')) != NULL)
program_name = cp + 1;
else
program_name = argv[0];
opterr = 0;
while ((i = getopt(argc, argv, "pa")) != -1)
{
switch (i)
{
case 'p':
pflag = 1;
break;
case 'a':
aflag = 1;
break;
case '?':
default:
done = 1;
break;
}
if (done) break;
}
if (argc > (optind)) cmdbuf = copy_argv(&argv[optind]);
else cmdbuf = "";
if (device == NULL) {
device = pcap_lookupdev(ebuf);
if (device == NULL)
error("%s", ebuf);
}
pd = pcap_open_live(device, snaplen, 1, 1000, ebuf);
if (pd == NULL)
error("%s", ebuf);
i = pcap_snapshot(pd);
if (snaplen < i) {
warning("snaplen raised from %d to %d", snaplen, i);
snaplen = i;
}
if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
localnet = 0;
netmask = 0;
warning("%s", ebuf);
}
/*
* Let user own process after socket has been opened.
*/
setuid(getuid());
if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
error("%s", pcap_geterr(pd));
(void)setsignal(SIGTERM, program_ending);
(void)setsignal(SIGINT, program_ending);
/* Cooperate with nohup(1) */
if ((oldhandler = setsignal(SIGHUP, program_ending)) != SIG_DFL)
(void)setsignal(SIGHUP, oldhandler);
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
pcap_userdata = 0;
(void)fprintf(stderr, "%s: listening on %s\n", program_name, device);
if (pcap_loop(pd, cnt, raw_print, pcap_userdata) < 0) {
(void)fprintf(stderr, "%s: pcap_loop: %s\n",
program_name, pcap_geterr(pd));
exit(1);
}
pcap_close(pd);
exit(0);
}
/* routine is executed on exit */
// this subroutin print total number of packets we should add number of IP packets, number of ARP and number of broadcast
// ctrIP, ctrARP, ctrBCAST
// initialize these at the begining of program as global var and to zero
void program_ending(int signo)
{
struct pcap_stat stat;
if (pd != NULL && pcap_file(pd) == NULL) {
(void)fflush(stdout);
putc('\n', stderr);
if (pcap_stats(pd, &stat) < 0)
(void)fprintf(stderr, "pcap_stats: %s\n",
pcap_geterr(pd));
else {
(void)fprintf(stderr, "%d packets received by filter\n",
stat.ps_recv);
(void)fprintf(stderr, "%d packets dropped by kernel\n",
stat.ps_drop);
}
}
exit(0);
}
/* Like default_print() but data need not be aligned */
void
default_print_unaligned(register const u_char *cp, register u_int length)
{
register u_int i, s;
register int nshorts;
nshorts = (u_int) length / sizeof(u_short);
i = 0;
while (--nshorts >= 0) {
if ((i++ % 8) == 0)
(void)printf("\n\t\t\t");
s = *cp++;
(void)printf(" %02x%02x", s, *cp++);
}
if (length & 1) {
if ((i % 8) == 0)
(void)printf("\n\t\t\t");
(void)printf(" %02x", *cp);
}
}
/*
* By default, print the packet out in hex.
*/
void
default_print(register const u_char *bp, register u_int length)
{
register const u_short *sp;
register u_int i;
register int nshorts;
if ((long)bp & 1) {
default_print_unaligned(bp, length);
return;
}
sp = (u_short *)bp;
nshorts = (u_int) length / sizeof(u_short);
i = 0;
while (--nshorts >= 0) {
if ((i++ % 8) == 0)
(void)printf("\n\t");
(void)printf(" %04x", ntohs(*sp++));
}
if (length & 1) {
if ((i % 8) == 0)
(void)printf("\n\t");
(void)printf(" %02x", *(u_char *)sp);
}
}
/*
insert your code in this routine
*/
void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{ {
u_int length = h->len;
u_int caplen = h->caplen;
/* At this point we start extracting data from the packet, with the var idx keeping up with where we are in the packet */
// Print total packet size
printf("\nPacket Length\t%d bytes", h->len);
// Decode Ethernet (Layer 2) Header Info
int idx; // counter variable for indexing through packet
char eth_destination[6]; // var to store the ethernet destination address
char eth_source[6]; // var to store the ethernet source address
short eth_type; // var to store the ethernet type value
char eth_payload[10]; // string array to store payload description
char eth_bcast[6] = "0xFF";
// Extract Ethernet Destination Address (1st 6 bytes)
for ( idx = 0; idx < 6; idx++)
{
eth_destination[idx] = p[idx];
}
// Extract Ethernet Source Address (2nd 6 bytes)
for ( idx = 6; idx < 12; idx++)
{
eth_source[idx-6] = p[idx];
}
// Combine two byte Ethernet Type/Length field into one value
eth_type = p[12] * 256 + p[13];
// Check the packet type and increment related counter
if ( eth_type >= 0x600) {
switch ( eth_type )
{
case 0x800: // Check to see if the type indicates that the packet is IP
ctrIP++;
strcpy(eth_payload, "IP");
break;
case 0x806: // Check to see if the type indicates that the packet is ARP
ctrARP++;
strcpy(eth_payload, "ARP");
break;
default:
break;
}
}
// Check to see if the destination was a broadcast packet and increment related counter
/*
if ((eth_destination[0] == 0xFF ) && (eth_destination[1] == 0xFF ) && (eth_destination[2] == 0xFF ) && (eth_destination[3] == 0xFF ) && (eth_destination[4] == 0xFF ) && (eth_destination[5] == 0xFF )) {
ctrBCAST++;
}
*/
// Print Ethernet (Layer 2) Header Info
printf("Layer\tField\tValue\n");
printf("ETHERNET\tDestination\t%02x:%02x:%02x:%02x :%02x:%02x\n", eth_destination[0],eth_destination[1],eth_destination[2],eth_destination[3],eth_destination[4],eth_destination[5]);
printf("\t\tSource\t%02x:%02x:%02x:%02x:%02x:%02x\ n", eth_source[0],eth_source[1],eth_source[2],eth_source[3],eth_source[4],eth_source[5]);
printf("\t\tType\t0x%02x\n", eth_type);
printf("\t\tPayload\t%s\n", eth_payload);
// All packets will have ethernet info (decoded and printed above).
// At this point we have to determine what kind of data is at the next layer up (layer 3) and decode/print the data accordingly.
// This is done based on the eth_type variable.
if ( eth_type >= 0x600) {
switch ( eth_type )
{
case 0x800: // IP Packet
// insert code to decode and print IP (should this be a separate sub-routine?
break;
case 0x806: // ARP Packet
// insert code to decode and print ARP
break;
default:
break;
}
}
exit(0);
}