
/* $Id: pcapops.c,v 1.8 2009/03/29 19:15:44 jayrfink Exp $ */

/* netward source file: pcap ops LICENSE: See COPYING for details */

#include "nw.h"

int hits; /* count this up til threshold is exceeded */

void pktinit (char *filter, int npolls)
{
        struct bpf_program program;    /* BPF filter program */
        char errbuf[PCAP_ERRBUF_SIZE]; /* pcap error buffer */
        pcap_t *handle;                /* pcap handle */
        bpf_u_int32 mask;              /* our netmask */
        bpf_u_int32 net;               /* our IP adx */

       /* Set up interface */
        if ((!dev)
            && ((dev = pcap_lookupdev(errbuf)) == NULL)) {
                fprintf(stderr, "error: unable to open device %s\n", errbuf);
                exit(-1);
        }
                                        
        if ((handle =
             pcap_open_live(dev, 68, 0, 0, errbuf)) == NULL) {
                fprintf(stderr, "error: cannot open device live %s\n", errbuf);
                exit(-1);
        }

        pcap_lookupnet(dev, &net, &mask, errbuf);
        if (filter) {
                if (pcap_compile(handle, &program, filter, 0, net) == -1) {
                        fprintf(stderr, "error: `pcap_compile()'\n");
                        exit (1);
                }

                if (pcap_setfilter(handle, &program) == -1) {
                        fprintf(stderr, "error: `pcap_setfilter()'\n");
                        exit (1);
                }
                        
                pcap_freecode(&program);
        }
                       
	hits = 0; /* Reset actual hits */ 
        pcap_loop(handle, npolls, pkthandler, NULL);
        pcap_close(handle);
}


void pkthandler(u_char * args, const struct pcap_pkthdr *header,
					const u_char * packet)
{
	eth_hdr *ethernet;          /* The ethernet header */
	ip_hdr *ip;                 /* The IP header */
	u_int id;                   /* Host id */
	u_int i;                    /* Counter */
	const struct tcphdr *tcp;   /* TCP Header */
	int len;                    /* real length */
	u_int off, version;         /* offset, version */
	u_int length = header->len; /* length from header */
	char *t;                    /* Temp time placeholder */
	time_t result;              /* Timeval result */
	char *msgbuf;               /* The message buffer */

	t = ""; /* empty */

	/* Extract ethernet and ip headers from packet */
	ethernet = (eth_hdr *) (packet); /* Pointer to ethernet header */
	ip = (ip_hdr *) (packet + sizeof(eth_hdr));
	tcp = (struct tcphdr *) (packet +
			sizeof(struct ether_header) +
			sizeof(struct ip));

	hits++;
	result = time(NULL);
	t = asctime(localtime(&result));
	t[strlen(t) - 1] = ' ';
	t[strlen(t)] = 0;
	if (hits >= threshold) {
		asprintf(&msgbuf, "%s: %s:", t, inet_ntoa(ip->ip_src));
		if (vflag) 
			printf("%s", msgbuf);
		else 
			logit(msgbuf, LOGFILE);

		asprintf(&msgbuf, "%u ", tcp->source);
		if (vflag)
			printf("%s", msgbuf);
		else 
			logit(msgbuf, LOGFILE);

		asprintf(&msgbuf, "-> %s:", inet_ntoa(ip->ip_dst));
		if (vflag)
			printf("%s", msgbuf);
		else 
			logit(msgbuf, LOGFILE);

		asprintf(&msgbuf, "%u ", tcp->dest);
		if (vflag)
			printf("%s", msgbuf);
		else  {
			logit(msgbuf, LOGFILE);
			logit("\n", LOGFILE);
		}

		if (vflag) 
		       	 fprintf(stdout,
				 "tos %u len %u off %u ttl %u prot %u cksum %u seq %u ack %u win %u\n",
				ip->ip_tos, len, off, ip->ip_ttl, ip->ip_p,
				ip->ip_sum, tcp->seq, tcp->ack, tcp->window);
	} /* end if hits vs threshold */

	/* packet diagnostics */
	length -= sizeof(struct ether_header);
	len = ntohs(ip->ip_len);
	off = ntohs(ip->ip_off);
	/* Check for truncated packet */
	if (length < sizeof(struct ip)) {
		asprintf(&msgbuf, "diagalert: truncated ip %d\n", length);
		if (vflag)
			printf("%s", msgbuf);
		else
			logit(msgbuf, LOGFILE);
	}
	
	/* Check for missing bytes */
	if (length < len) {
		asprintf(&msgbuf,"diagalert: %s truncated %d bytes missing\n",
			              inet_ntoa(ip->ip_src), len - length);
		if (vflag)
			printf("%s", msgbuf);
		else
			logit(msgbuf, LOGFILE);
	}

	/* aka no 1's in the first 13 bits */
	if ((off * 0x1fff) == 1) {
		asprintf(&msgbuf, "adminalert: non-contiguos header\n");
		if (vflag)
			printf("%s", msgbuf);
		else 
			logit(msgbuf, LOGFILE);
	}
}

