I'm required to write a packet sniffer in the C programming language and Identify the Packet as IP, ARP, or Broadcast and count how many packets of each. I'm able to get IP packets identified and counted, but don't seem to be seeing any ARP or Broadcasts correctly or count them.
I also get this warning when I compile my code:
/netdump.c: In function 'raw_print':
./netdump.c:284: warning: cast to pointer from integer of different size
./netdump.c:285: warning: comparison between pointer and integer
Any help is appreciated!!! I'm more concerned with why I'm not getting any ARP or Broadcast packets being identified and counted.
Thanks Again,
JW
#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
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
#define SIZE_ETHERNET 14
#define SIZE_IPHDR 20
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
u_short ether_type; /* IP? ARP? etc */
};
/* ARP packet */
struct sniff_arp {
u_short arp_hwtype;
u_short arp_proto;
u_char arp_addrlen;
u_char arp_protolen;
u_short arp_operation;
u_char arp_src[6];
u_char arp_src_proto_addr[4];
u_char arp_dst[6];
u_char arp_dst_proto_addr[4];
};
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
u_char ip_src[4]; /* source port */
u_char ip_dst[4]; /* destination port */
// struct in_addr ip_src,ip_dst; /* source and dest address */
};
int nPackets = 1;
int nARP = 0;
int nIP = 0;
int nBroadcast = 0;
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 */
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 {
printf("Statistics:\n_________________________________________________\n");
printf("Packet Counts:\n");
printf("ARP......%d\n",nARP);
printf("IP.......%d\n",nIP);
printf("BRDCST...%d\n\n",nBroadcast);
printf("\n\n");
(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)
{
/* declare pointers to packet headers */
const struct sniff_ethernet *ethernet; /* The ethernet header */
const struct sniff_arp *arp; /* The arp packet */
const struct sniff_ip *ip; /* The IP header */
char *payload; /* Packet payload */
char data[1480];
int shoPayload = 0;
ethernet = (struct sniff_ethernet*)(p);
//decode ethernet packet header
u_short type;
int i=0, bcst=1;
u_char test;
//short bcast = "ff";
printf("Ethernet Header\n---------------------------\n");
printf("Src: %02x:%02x:%02x:%02x:%02x:%02x\n", ethernet->ether_shost[0],ethernet->ether_shost[1],ethernet->ether_shost[2],ethernet->ether_shost[3],ethernet->ether_shost[4],ethernet->ether_shost[5]);
printf("Dst: %02x:%02x:%02x:%02x:%02x:%02x\n", ethernet->ether_dhost[0],ethernet->ether_dhost[1],ethernet->ether_dhost[2],ethernet->ether_dhost[3],ethernet->ether_dhost[4],ethernet->ether_dhost[5]);
while (i < 6) {
printf("%x:",(u_char *)ethernet->ether_dhost[i]);
if ("ff" != ethernet->ether_dhost[i]) {
printf("%x:",ethernet->ether_dhost[i]);
bcst = 0;
//bcst ++;
//nBroadcast++;
//printf("Broadcast\n");
}
i++;
}
if (bcst == 1) {
nBroadcast++;
printf("Broadcast\n");
}
type = ntohs(ethernet->ether_type);
printf("\nType: 0x%x \n", type);
switch (type) {
case 0x806:
//decode ARP packet header
arp = (struct sniff_arp*)(p + SIZE_ETHERNET);
printf("Payload = ARP\n");
printf("\n\tARP Decode\n\t-------------------\n");
printf("\tHW type: %04x\n", arp->arp_hwtype);
printf("\tProto type: %04x\n", arp->arp_proto);
printf("\tHW Addr Len: %02x\n", arp->arp_addrlen);
printf("\tProto Len: %02x\n", arp->arp_protolen);
printf("\tSrc: %02x:%02x:%02x:%02x:%02x:%02x\n", arp->arp_src[0],arp->arp_src[1],arp->arp_src[2],arp->arp_src[3],arp->arp_src[4],arp->arp_src[5]);
printf("\tDst: %02x:%02x:%02x:%02x:%02x:%02x\n", arp->arp_dst[0],arp->arp_dst[1],arp->arp_dst[2],arp->arp_dst[3],arp->arp_dst[4],arp->arp_dst[5]);
//printf("\tSrc IP: %d.%d.%d.%d\n", arp->arp_src_proto_addr[0],arp->arp_src_proto_addr[1],arp->arp_src_proto_addr[2],arp->arp_src_proto_addr[3]);
//printf("\tDst IP: %d.%d.%d.%d\n", arp->arp_dst_proto_addr[0],arp->arp_dst_proto_addr[1],arp->arp_dst_proto_addr[2],arp->arp_dst_proto_addr[3]);
nARP++;
break;
case 0x800:
//decode IP packet header
ip = (struct sniff_ip*)(p + SIZE_ETHERNET);
printf("Payload = IP\n");
printf("\n\tIP Header\n\t-------------------\n");
printf("\tSrc: %d.%d.%d.%d\n", ip->ip_src[0],ip->ip_src[1],ip->ip_src[2],ip->ip_src[3]);
printf("\tDst: %d.%d.%d.%d\n", ip->ip_dst[0],ip->ip_dst[1],ip->ip_dst[2],ip->ip_dst[3]);
printf("\tIP Version: %x\n", (ip->ip_vhl) >> 4);
//printf("\tHeader Len: %x\n",(ip->ip_vhl) & 0x0F);
//printf("\tTOS: %x\n", ip->ip_tos);
printf("\tLength: %d\n", ntohs(ip->ip_len));
//printf("\tPacket ID: %d\n", ntohs(ip->ip_id));
//printf("\tOffset: %d\n", ntohs(ip->ip_off) & 0x1fff);
//printf("\tTTL: %d\n", ip->ip_ttl);
//printf("\tChecksum: %d\n", ntohs(ip->ip_sum));
nIP++;
break;
}
u_int length = h->len;
u_int caplen = h->caplen;
default_print(p, caplen);
putchar('\n');
}