#ifndef lint
static  char rcsid[] =
    "@(#)$Header: pcap-linux.c,v 0.12 93/12/29 17:13:24 slouken Exp $ (LBL)";
#endif

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <linux/if.h>
#include <signal.h>
#include <stdio.h>

#include <net/bpf.h>

#include "interface.h"

#define SLIP_HACK		/* KEEP THIS LINE HERE!  It is needed for Linux slip support */

#define BUFLEN 8192
#define ETHLINKHDR 14

void
readloop(cnt, if_fd, fp, printit)
	int cnt;
	int if_fd;
	struct bpf_program *fp;
	void (*printit)();
{
	u_char buf[BUFLEN + ETHLINKHDR], *bufstart;
	struct bpf_insn *fcode;
	struct sockaddr dest;
	int cc, i, dlen;
	unsigned long now;

	fcode = fp->bf_insns;
	i = 0;

	while ((cc = recvfrom(if_fd, (char *)&buf[ETHLINKHDR], BUFLEN, 0, &dest, &dlen)) > 0) {
		register u_char *bp, *bstop;
		register u_char *sp;
		register struct nit_hdr *nh;
		register int datalen = 0;
		int caplen, j;
		
		bufstart = &buf[ETHLINKHDR];
		if (buf[ETHLINKHDR] == 0x45 &&
		    buf[ETHLINKHDR+1] == 0x00) {
		    /* Probably a SLIP packet */
		    /* backup buffer 14 bytes to simulate rest of eth header */
		    for (j = 0; j < 6; j++) {
			bufstart[j-14] = 0;
			bufstart[j-8] = 0;
		    }
		    bufstart[-2] = 0x08;
		    bufstart[-1] = 0x00;
		    bufstart -= ETHLINKHDR;
		    cc += ETHLINKHDR;
		}
		/*
		 * Loop through each packet.  The increment expression
		 * rounds up to the next int boundary past the end of
		 * the previous packet.
		 */
		bstop = bufstart + cc;
		for (bp = bufstart; bp < bstop; ++bp )
			/* Do Nothing */ ;
		(void) time(&now);
		sp=bufstart;
		caplen=cc;

		if (bpf_filter(fcode, sp, cc, caplen)) {
			(*printit)(sp, &now, cc, caplen);
/*
			if (cflag && ++i >= cnt) {
				wrapup(if_fd);
				return;
			}
*/
		}
	}
	perror("read");
	exit(-1);
}


wrapup(fd)
	int fd;
{
	close(fd);
}

int
initdevice(device, pflag, linktype)
	char *device;
	int pflag;
	int *linktype;
{
#define PROTO htons(0x0800)   /* Ethernet code for IP protocol */

	int if_fd=0;
	struct ifreq ifr;

	if ( (if_fd=socket(AF_INET,SOCK_PACKET,PROTO)) < 0 ) {
		perror("Can't get socket");
		exit(2);
	}

	strcpy(ifr.ifr_name, device);       /* interface we're gonna use */
	if( ioctl(if_fd, SIOCGIFFLAGS, &ifr) < 0 ) {    /* get flags */
		close(if_fd);
		perror("Can't get flags");
		exit(2);
	}
	if ( pflag )
		ifr.ifr_flags |= IFF_PROMISC;         /* set promiscuous mode */

	if( ioctl(if_fd, SIOCSIFFLAGS, &ifr) < 0 ) {    /* set flags */
		close(if_fd);
		perror("Can't set flags");
		exit(2);
	}
	if ( strncmp(device, "sl", 2) == 0 )
#ifdef SLIP_HACK
		*linktype = DLT_EN10MB;
#else
		*linktype = DLT_SLIP;
#endif
	else /* Assume ethernet */
		*linktype = DLT_EN10MB;

	return if_fd;
}
