Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 20 May 2003 17:11:04 +0200
From:      gianz@security.dico.unimi.it
To:        freebsd-net@freebsd.org
Subject:   Re: [BPF Read and Write] Strange behaviour?
Message-ID:  <20030520151104.GA14857@idea.sec.dico.unimi.it>
In-Reply-To: <20030520132042.GA16689@radiance.it>
References:  <20030520132042.GA16689@radiance.it>

next in thread | previous in thread | raw e-mail | index | archive | help
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;
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030520151104.GA14857>