// Copyright (C) FIT VUT
// Petr Lampa <lampa@fit.vutbr.cz>
// $Id$
// vi:set ts=8 sts=8 sw=8:
//
extern "C" {
#include <net/bpf.h>
}

class BPF
{
	int _fd;
	int _blen;
	struct bpf_hdr *_bfp_buf;
	Octet bpf_ptr *_bfp_ptr;
	int _len;

public:
	BPF(): fd(-1) { }
	bool open(string name) { 
		string buf("/dev/bpfXX");
		for (int i = 0; i < 20; i++) {
			buf = "/dev/bpf" + cvt_int(i);
			_fd = open(buf, buf.c_str());
			if (bpf >= 0) return true;
		}
		return false;
	}
	bool bind(string name) {
		struct ifreq bound_if;
		int bl;
		strcpy(bound_if.ifr_name, name.c_str());
		if (ioctl(_fd, BIOCSETIF, &bound_if) == -1) return false;
		// activate immediate mode
		bl = 1;
		if (ioctl(_fd, BIOCIMMEDIATE, &bl) == -1) return false;
		// get request buffer length
		if (ioctl(_fd, BIOCGBLEN, &_blen) == -1) return false;
		_bpf_buf = new Octet[_blen];	//XXX ??
		return false;
	}
	bool read(Packet &pkt)
	{
		struct bpf_hdr *bfp_hdr;
		pkt.clear();
		// something left from previous read?
		if (_bpf_ptr >= reinterpret_cast<Octet *>(_bpf_buf) + _len) {
			_len = read(_fd, _bpf_buf, _blen);
			Octet *_bpf_ptr = reinterpret_cast<Octet *>(_bpf_buf);
			if (_len <= 0) return false;
		}
		bpf_hdr = reinterpret_cast<bpf_hdr*>(_bpf_ptr);
		// move data
		pkt.buf(_bpf_ptr + bpf_hdr->bh_hdrlen);
		ptr += BPF_WORDALIGN(bpf_hdr->bh_hdrlen + bpf_hdr->bh_caplen);
		return true;
	}
	bool write(Packet &pkt)
	{
		if (write(_fd, pkt.buf(), pkt.length()) != pkt.length()) return false;
		return true;
	}
	void close() {
		close(_fd);
	}
	~BPF() { close(); }
};
