[BPF Read and Write] Strange behaviour?
gianz at security.dico.unimi.it
gianz at security.dico.unimi.it
Tue May 20 08:11:15 PDT 2003
Sorry...
that's the file:
#include "common.h"
#include "link_layer.h"
int LINK_LAYER_open_device(char *device, int to)
{
int i, fd;
struct ifreq ifr;
u_int t;
struct timeval tv;
char pf[sizeof "/dev/bpf0000000000"];
i = 0;
do {
(void)snprintf(pf, sizeof(pf), "/dev/bpf%d", i++);
fd = open(pf, O_RDWR);
} while (fd < 0 && errno == EBUSY);
if(fd >= 0)
{
for (t = 65536; t != 0; t >>= 1)
{
(void) ioctl(fd, BIOCSBLEN, &t);
(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
break;
if (errno != ENOBUFS) {
return EXIT_FAILURE;
}
}
if(verb)
{
printf("opening %s\n", device);
}
t=1;
if(ioctl(fd, BIOCPROMISC, &t)==-1)
{
perror("ioctl");
return EXIT_FAILURE;
}
if(ioctl(fd, BIOCSHDRCMPLT, &t)==-1)
{
perror("ioctl");
return EXIT_FAILURE;
}
if(to == 0)
{
if(ioctl(fd, BIOCIMMEDIATE, &t)==-1)
{
perror("ioctl");
return EXIT_FAILURE;
}
}
else
{
tv.tv_sec = to / 1000;
tv.tv_usec = (to % 1000) * 1000;
if(verb)
{
printf("timeout: %ld secs %ld usecs\n", tv.tv_sec, tv.tv_usec);
}
if(ioctl(fd, BIOCSRTIMEOUT, &tv)==-1)
{
perror("ioctl");
return EXIT_FAILURE;
}
}
}
else
{
printf("cannot open %s\n", device);
perror(pf);
return EXIT_FAILURE;
}
return fd;
}
int LINK_LAYER_read(
int readfd,
int writefd,
unsigned char *buf,
int len,
PACKET_DATA *p_data,
void (*do_nat)(PACKET_DATA *data, char *buf, int len, int fd)
)
{
int count;
struct bpf_hdr *p;
struct bpf_hdr *e;
again:
count = read(readfd, buf, len);
p = (struct bpf_hdr *)buf;
e = (struct bpf_hdr *)(buf + count);
if(count<0)
{
switch(errno)
{
case EINTR:
printf("read interrupted\n");
goto again;
case EAGAIN:
return 0;
default:
return -1;
}
}
if(count > 0)
{
while(p < e)
{
if(p->bh_caplen != p->bh_datalen)
{
printf("warning: truncated packet\n");
}
do_nat(p_data, (char *)p + p->bh_hdrlen, p->bh_caplen, writefd);
p = (struct bpf_hdr *)((char *)p + BPF_WORDALIGN(p->bh_hdrlen + p->bh_caplen));
}
}
return count;
}
unsigned char *LINK_LAYER_alloc_buffer(int fd, int *len)
{
if(ioctl(fd, BIOCGBLEN, len)==-1)
{
perror("ioctl");
return NULL;
}
return malloc(*len);
}
int LINK_LAYER_accept_from(int fd, unsigned char *mac)
{
unsigned long head;
unsigned short tail;
struct bpf_program bpfp;
((char *)(&head))[0] = mac[3];
((char *)(&head))[1] = mac[2];
((char *)(&head))[2] = mac[1];
((char *)(&head))[3] = mac[0];
mac += sizeof(unsigned long);
((char *)(&tail))[0] = mac[1];
((char *)(&tail))[1] = mac[0];
struct bpf_insn filter[] = {
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 6),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, head, 0, 3),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 10),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, tail, 0, 1),
BPF_STMT(BPF_RET+BPF_K, ((u_int)-1)),
BPF_STMT(BPF_RET+BPF_K, 0)
};
bpfp.bf_insns = filter;
bpfp.bf_len = 6;
if(ioctl(fd, BIOCSETF, &bpfp)==-1)
{
perror("BIOCSETF");
return -1;
}
return 1;
}
int LINK_LAYER_reject_from(int fd, unsigned char *mac)
{
unsigned long head;
unsigned short tail;
struct bpf_program bpfp;
((char *)(&head))[0] = mac[3];
((char *)(&head))[1] = mac[2];
((char *)(&head))[2] = mac[1];
((char *)(&head))[3] = mac[0];
mac += sizeof(unsigned long);
((char *)(&tail))[0] = mac[1];
((char *)(&tail))[1] = mac[0];
struct bpf_insn filter[] = {
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 6),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, head, 0, 3),
BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 10),
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, tail, 0, 1),
BPF_STMT(BPF_RET+BPF_K, 0),
BPF_STMT(BPF_RET+BPF_K, ((u_int)-1))
};
bpfp.bf_insns = filter;
bpfp.bf_len = 6;
if(ioctl(fd, BIOCSETF, &bpfp)==-1)
{
perror("BIOCSETF");
return -1;
}
return 1;
}
More information about the freebsd-net
mailing list