#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? RARP? 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 */
};
/* ICMP packet */
struct sniff_icmp {
u_char icmp_type;
u_char icmp_code;
u_short icmp_sum;
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) > 4)
/* TCP header */
struct sniff_tcp {
u_short srcprt; /* source port */
u_short destprt; /* destination port */
u_int seq; /* sequence number */
u_int ack; /* acknowledgement number */
u_char hdrlen; /* data offset, rsvd */
#define TH_OFF(th) (((th)->th_offx2 & 0xf0) > 4)
u_char flags;
#define TH_FIN 0x01
#define TH_SYN 0x02
#define TH_RST 0x04
#define TH_PUSH 0x08
#define TH_ACK 0x10
#define TH_URG 0x20
#define TH_ECE 0x40
#define TH_CWR 0x80
#define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
u_short win; /* window */
u_short sum; /* checksum */
u_short urp; /* urgent pointer */
};
/* UDP header */
struct sniff_udp {
u_short udp_srcprt;
u_short udp_destprt;
u_short udp_len;
u_short udp_sum;
};
/* DNS header */
struct sniff_dns {
u_short id;
u_short flags;
u_short numQuestions;
u_short numAnswers;
u_short numAA;
u_short numAddRecs;
};
int nPackets = 1;
int nARP = 0;
int nIP = 0;
int nBroadcast = 0;
int nICMP = 0;
int nTCP = 0;
int nDNS = 0;
int nUDP = 0;
int nPOP = 0;
int nSMTP = 0;
int nIMAP = 0;
int nHTML = 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_stats 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("\tICMP...... %d\n",nICMP);
printf("\tTCP...... %d\n",nTCP);
printf("\t\tPOP...... %d\n",nPOP);
printf("\t\tSMTP...... %d\n",nSMTP);
printf("\t\tIMAP...... %d\n",nIMAP);
printf("\t\tHTML...... %d\n",nHTML);
printf("\tUDP...... %d\n",nUDP);
printf("\t\tDNS...... %d\n",nDNS);
//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)
{
/*"u_" designates a variable as unsigned*/
register const u_short *sp;
register u_int i;
register int nshorts;
u_short packet[length/2];
if ((long)bp & 1) {
default_print_unaligned(bp, length);
return;
}
sp = (u_short *)bp; /*set pointer sp equal to (u_short *)bp*/
nshorts = (u_int) length / sizeof(u_short);
i = 0;
while (--nshorts >= 0) {
packet[i] = *sp;
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);
}
putchar('\n');
}
/*
insert your code in this routine
*/
void raw_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
{
u_short type;
int i=0, bcst=1;
u_char test;
/* 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 */
const struct sniff_icmp *icmp; /* The ICMP header */
const struct sniff_tcp *tcp; /* The TCP header */
const struct sniff_udp *udp; /* The UDP header */
const struct sniff_dns *dns; /* The DNS header */
char *payload; /* Packet payload */
char *options_ptr; /* TCP Options Ptr */
char data[1480];
int shoPayload = 0;
ethernet = (struct sniff_ethernet*)(p);
// if (size_ip < 20) {
// printf(" * Invalid IP header length: %u bytes\n", size_ip);
// return;
// }
// tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
// size_tcp = TH_OFF(tcp)*4;
// if (size_tcp < 20) {
// printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
// return;
// }
// payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
//decode ethernet packet header
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;
// }
// i++;
// }
// if (bcst == 1) {
// nBroadcast++;
// printf("Broadcast\n");
// }
type = ntohs(ethernet->ether_type);
printf("Type: %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);
switch (arp->arp_operation) {
case 0x100:
printf("\tOperation: ARP Request(0x100)\n");
break;
case 0x200:
printf("\tOperation: ARP Response(0x200)\n");
break;
case 0x300:
printf("\tOperation: RARP Request(0x300)\n");
break;
case 0x400:
printf("\tOperation: RARP Reply(0x400)\n");
break;
default:
printf("\tOperation: UNDEF(0x%04x)\n", arp->arp_operation);
break;
}
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));
switch (ntohs(ip->ip_off) > 13) {
case 0:
printf("\tFlags: None\n");
break;
case 1:
printf("\tFlags: More Fragments\n");
break;
case 2:
printf("\tFlags: Do not Fragment\n");
break;
}
printf("\tOffset: %d\n", ntohs(ip->ip_off) & 0x1fff);
printf("\tTTL: %d\n", ip->ip_ttl);
printf("\tChecksum: %d\n", ntohs(ip->ip_sum));
switch (ip->ip_p) {
case 1:
//decode ICMP packet header
printf("\tProtocol: ICMP (1)\n");
icmp = (struct sniff_icmp*)(p + SIZE_ETHERNET +20);
printf("\n\t\tICMP Decode\n\t\t------\n");
switch (icmp->icmp_type) {
case 0:
printf("\t\tType: Echo Reply(%d)\n",icmp->icmp_type);
break;
case 3:
printf("\t\tType: Destination Unreachable(3)\n");
break;
case 4:
printf("\t\tType: Source Quench(4)\n");
break;
case 5:
printf("\t\tType: Redirect(5)\n");
break;
case 8:
printf("\t\tType: Echo(8)\n");
break;
default:
printf("\t\tType: UNDEF\n");
break;
}
printf("\t\tCode: %x\n", icmp->icmp_code);
printf("\t\tChecksum: %d\n", icmp->icmp_sum);
nICMP++;
break;
case 6:
//decode TCP packet header
printf("\tProtocol: TCP(6)\n");
tcp = (struct sniff_tcp*)(p + SIZE_ETHERNET + 20);
printf("\n\t\tTCP Decode\n\t\t------\n");
printf("\t\tSource Port: %d\n", ntohs(tcp->srcprt));
printf("\t\tDest Port: %d\n", ntohs(tcp->destprt));
printf("\t\tSequence #: %d\n", ntohs(tcp->seq));
printf("\t\tAck #: %d\n", ntohs(tcp->ack));
printf("\t\tHdr Len: %d\n", (tcp->hdrlen) >4);
printf("\t\t\tFIN: %d\n", tcp->flags & TH_FIN );
printf("\t\t\tSYN: %d\n", ((tcp->flags) & TH_SYN) >1);
printf("\t\t\tRST: %d\n", ((tcp->flags) & TH_RST) >2);
printf("\t\t\tPSH: %d\n", ((tcp->flags) & TH_PUSH) >3);
printf("\t\t\tACK: %d\n", ((tcp->flags) & TH_ACK) >4);
printf("\t\t\tURG: %d\n", ((tcp->flags) & TH_URG) >5);
printf("\t\tWindow: %d\n", ntohs(tcp->win));
printf("\t\tChecksum: %d\n", ntohs(tcp->sum));
printf("\t\tUrgent Pointer: %x\n", ntohs(tcp->urp));
printf("\t\tOptions:");
//set the position of the options pointer and print any TCP packet Options
options_ptr = (u_char *)(p + SIZE_ETHERNET + SIZE_IPHDR + 20);
if ((tcp->hdrlen > 4) > 5) {
for( i = 0; i < (tcp->hdrlen > 4)*4 - 20; i++) {
printf(" %02x", options_ptr[i] );
}
}
nTCP++;
//increment TCP packet counters for POP, SMTP, and IMAP
if (ntohs(tcp->srcprt) == 110 | ntohs(tcp->destprt) == 110) {
nPOP++;
shoPayload = 1;
}
if (ntohs(tcp->srcprt) == 25 | ntohs(tcp->destprt) == 25) {
nSMTP++;
shoPayload = 1;
}
if (ntohs(tcp->srcprt) == 143 | ntohs(tcp->destprt) == 143) {
nIMAP++;
shoPayload = 1;
}
if (ntohs(tcp->srcprt) == 80 | ntohs(tcp->destprt) == 80) {
nHTML++;
shoPayload = 1;
}
//if the TCP packet is a PSH packet, print out the TCP packet Payload
if (shoPayload == 1) {
if (((tcp->flags) & TH_PUSH) >3 == 1) {
printf("\n");
payload = (u_char *)(p + SIZE_ETHERNET + SIZE_IPHDR + ((tcp->hdrlen) > 4)*4 );
printf("\nTCP Payload(%d)\n------\n",ntohs(ip->ip_len)-(((tcp->hdrlen) > 4)*4) );
for( i = 0; i < ntohs(ip->ip_len)-(((tcp->hdrlen)> 4)*4); i++) {
printf("%c", payload[i] );
}
}
}
printf("\n\n");
break;
case 17:
printf("\tProtocol: UDP(17)\n");
udp = (struct sniff_udp*)(p + SIZE_ETHERNET + 20);
printf("\n\t\tUDP Decode\n\t\t------\n");
printf("\t\tSource Port: %d\n", ntohs(udp->udp_srcprt));
printf("\t\tDest Port: %d\n", ntohs(udp->udp_destprt));
printf("\t\tLenth: %d\n", ntohs(udp->udp_len));
printf("\t\tChecksum: %d\n", ntohs(udp->udp_sum));
nUDP++;
if (ntohs(udp->udp_srcprt) == 53 | ntohs(udp->udp_destprt) == 53)
nDNS++;
break;
default:
printf("\tProtocol is UNDEF(%d)\n", ip->ip_p);
break;
}
nIP++;
break;
default:
printf("\tPayload is UNDEF");
break;
}
u_int length = h->len;
u_int caplen = h->caplen;
default_print(p, caplen);
putchar('\n');
}