Diff for /libaitio/src/bpf.c between versions 1.2 and 1.7

version 1.2, 2013/06/26 22:48:53 version 1.7, 2015/01/19 23:32:30
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013Copyright 2004 - 2014
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 47  SUCH DAMAGE. Line 47  SUCH DAMAGE.
   
   
 /*  /*
  * io_get1stiface() - Get first interface of host  
  *  
  * @szIface = interface string buffer  
  * @iflen = size of interface buffer  
  * return: -1 error or 0 ok  
  */  
 int  
 io_get1stiface(char *szIface, int iflen)  
 {  
         struct ifaddrs *ifa;  
   
         if (!szIface || !iflen)  
                 return -1;  
   
         getifaddrs(&ifa);  
         strlcpy(szIface, ifa->ifa_name, iflen);  
         freeifaddrs(ifa);  
         return 0;  
 }  
   
 /*  
  * io_etherClose() - Close BPF interface   * io_etherClose() - Close BPF interface
  *   *
  * @eth = bpf handle   * @eth = bpf handle
Line 77  io_get1stiface(char *szIface, int iflen) Line 56  io_get1stiface(char *szIface, int iflen)
 void  void
 io_etherClose(int eth, void **zcbuf)  io_etherClose(int eth, void **zcbuf)
 {  {
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
         struct bpf_zbuf *zbuf = NULL;          struct bpf_zbuf *zbuf = NULL;
 #endif  #endif
   
Line 85  io_etherClose(int eth, void **zcbuf) Line 64  io_etherClose(int eth, void **zcbuf)
                 close(eth);                  close(eth);
   
         if (zcbuf && *zcbuf) {          if (zcbuf && *zcbuf) {
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
                 zbuf = *zcbuf;                  zbuf = *zcbuf;
                 munmap(zbuf->bz_bufb, zbuf->bz_buflen);                  munmap(zbuf->bz_bufb, zbuf->bz_buflen);
                 munmap(zbuf->bz_bufa, zbuf->bz_buflen);                  munmap(zbuf->bz_bufa, zbuf->bz_buflen);
Line 95  io_etherClose(int eth, void **zcbuf) Line 74  io_etherClose(int eth, void **zcbuf)
         }          }
 }  }
   
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
 static inline struct bpf_zbuf *  static inline struct bpf_zbuf *
 allocZCbuf(u_int len)  allocZCbuf(u_int len)
 {  {
Line 135  allocZCbuf(u_int len) Line 114  allocZCbuf(u_int len)
  * @csIface = interface name   * @csIface = interface name
  * @flags = open flags   * @flags = open flags
  * @whdr = with complete headers   * @whdr = with complete headers
    * @wdlt = with data link type
  * @buflen = buffer length   * @buflen = buffer length
  * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL   * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL
  * return: -1 error or >-1 bpf handle   * return: -1 error or >-1 bpf handle
  */   */
 int  int
io_etherOpen(const char *csIface, int flags, int whdr, u_int *buflen, void **zcbuf)io_etherOpen(const char *csIface, int flags, u_int whdr, u_int wdlt, 
                 u_int *buflen, void **zcbuf)
 {  {
         int eth = -1;          int eth = -1;
         register int i;          register int i;
Line 148  io_etherOpen(const char *csIface, int flags, int whdr, Line 129  io_etherOpen(const char *csIface, int flags, int whdr,
         struct ifreq ifr;          struct ifreq ifr;
         u_int n = 1;          u_int n = 1;
   
#ifndef __FreeBSD__#if !defined(__FreeBSD__) || !defined(ZCBUF_ENABLE)
         if (zcbuf) {          if (zcbuf) {
                 io_SetErr(ENOTSUP, "bpf zero copy buffer mode is not supported");                  io_SetErr(ENOTSUP, "bpf zero copy buffer mode is not supported");
                 return -1;                  return -1;
Line 167  io_etherOpen(const char *csIface, int flags, int whdr, Line 148  io_etherOpen(const char *csIface, int flags, int whdr,
                 return -1;                  return -1;
         }          }
   
           if (csIface)
                   strlcpy(szStr, csIface, sizeof szStr);
           else if (e_get1stiface(szStr, sizeof szStr) == -1) {
                   close(eth);
                   return -1;
           }
   
           n = 1;
           if (whdr && ioctl(eth, BIOCSHDRCMPLT, &n) == -1) {
                   LOGERR;
                   close(eth);
                   return -1;
           }
           if (ioctl(eth, BIOCIMMEDIATE, &n) == -1) {
                   LOGERR;
                   close(eth);
                   return -1;
           }
   
         if (!zcbuf) {          if (!zcbuf) {
                 if (ioctl(eth, BIOCGBLEN, &n) == -1) {                  if (ioctl(eth, BIOCGBLEN, &n) == -1) {
                         LOGERR;                          LOGERR;
                         close(eth);                          close(eth);
                         return -1;                          return -1;
                 } else                  } else
                        n = (buflen && *buflen) ? *buflen : n;                        n = (buflen && *buflen) ? *buflen : getpagesize();
 
                 if (ioctl(eth, BIOCSBLEN, &n) == -1) {                  if (ioctl(eth, BIOCSBLEN, &n) == -1) {
                         LOGERR;                          LOGERR;
                         close(eth);                          close(eth);
                         return -1;                          return -1;
                 }                  }
                if (buflen && *buflen)                if (buflen)
                         *buflen = n;                          *buflen = n;
         } else {          } else {
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
                 n = BPF_BUFMODE_ZBUF;                  n = BPF_BUFMODE_ZBUF;
                 if (ioctl(eth, BIOCSETBUFMODE, &n) == -1) {                  if (ioctl(eth, BIOCSETBUFMODE, &n) == -1) {
                         LOGERR;                          LOGERR;
Line 209  io_etherOpen(const char *csIface, int flags, int whdr, Line 210  io_etherOpen(const char *csIface, int flags, int whdr,
 #endif  #endif
         }          }
   
         if (csIface)  
                 strlcpy(szStr, csIface, sizeof szStr);  
         else if (io_get1stiface(szStr, sizeof szStr) == -1) {  
                 io_etherClose(eth, zcbuf);  
                 return -1;  
         }  
         memset(&ifr, 0, sizeof ifr);          memset(&ifr, 0, sizeof ifr);
         strlcpy(ifr.ifr_name, szStr, sizeof ifr.ifr_name);          strlcpy(ifr.ifr_name, szStr, sizeof ifr.ifr_name);
         if (ioctl(eth, BIOCSETIF, &ifr) == -1) {          if (ioctl(eth, BIOCSETIF, &ifr) == -1) {
Line 223  io_etherOpen(const char *csIface, int flags, int whdr, Line 218  io_etherOpen(const char *csIface, int flags, int whdr,
                 return -1;                  return -1;
         }          }
   
        n = 1;        n = wdlt;
        if (whdr && ioctl(eth, BIOCSHDRCMPLT, &n) == -1) {        if (wdlt && ioctl(eth, BIOCSDLT, &n) == -1) {
                 LOGERR;                  LOGERR;
                io_etherClose(eth, zcbuf);                close(eth);
                 return -1;                  return -1;
         }          }
         if (ioctl(eth, BIOCIMMEDIATE, &n) == -1) {  
                 LOGERR;  
                 io_etherClose(eth, zcbuf);  
                 return -1;  
         }  
   
         return eth;          return eth;
 }  }
Line 262  io_etherSend(int eth, const void *buf, size_t buflen) Line 252  io_etherSend(int eth, const void *buf, size_t buflen)
         return wlen;          return wlen;
 }  }
   
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
 static inline void  static inline void
 ackZCbuf(struct bpf_zbuf_header *bzh)  ackZCbuf(struct bpf_zbuf_header *bzh)
 {  {
Line 321  ssize_t Line 311  ssize_t
 io_etherRecv(int eth, void * __restrict buf, size_t buflen, void * __restrict zcbuf)  io_etherRecv(int eth, void * __restrict buf, size_t buflen, void * __restrict zcbuf)
 {  {
         ssize_t rlen = 0;          ssize_t rlen = 0;
           struct bpf_hdr *h;
   
         if (!buf || !buflen) {          if (!buf || !buflen) {
                 io_SetErr(EINVAL, "invalid arguments");                  io_SetErr(EINVAL, "invalid arguments");
Line 329  io_etherRecv(int eth, void * __restrict buf, size_t bu Line 320  io_etherRecv(int eth, void * __restrict buf, size_t bu
   
         if (!zcbuf) {          if (!zcbuf) {
                 rlen = read(eth, buf, buflen);                  rlen = read(eth, buf, buflen);
                if (rlen == -1)                if (rlen == -1) {
                         LOGERR;                          LOGERR;
                           return -1;
                   }
         } else {          } else {
#ifdef __FreeBSD__#if defined(__FreeBSD__) && defined(ZCBUF_ENABLE)
                 rlen = nextZCbuf(eth, (struct bpf_zbuf*) zcbuf, buf, buflen);                  rlen = nextZCbuf(eth, (struct bpf_zbuf*) zcbuf, buf, buflen);
                 if (!rlen)                  if (!rlen)
                         rlen = nextZCbuf(eth, (struct bpf_zbuf*) zcbuf, buf, buflen);                          rlen = nextZCbuf(eth, (struct bpf_zbuf*) zcbuf, buf, buflen);
Line 342  io_etherRecv(int eth, void * __restrict buf, size_t bu Line 335  io_etherRecv(int eth, void * __restrict buf, size_t bu
 #endif  #endif
         }          }
   
           h = (struct bpf_hdr*) buf;
           rlen -= h->bh_hdrlen;
   
           if (h->bh_caplen != rlen) {
                   if (h->bh_caplen < rlen)
                           rlen = h->bh_caplen;
                   else {
                           io_SetErr(EIO, "Captured %d bytes should be at most %d bytes", 
                                           h->bh_caplen, rlen);
                           return -1;
                   }
           }
   
           memmove(buf, buf + h->bh_hdrlen, rlen);
         return rlen;          return rlen;
   }
   
   /*
    * io_etherFilter() - BPF filter routine
    *
    * @eth = bpf handle
    * @io = filter direction 
    *  (IO_ETHER_FILTER_PROMISC|IO_ETHER_FILTER_NOTREAD|IO_ETHER_FILTER_READ|IO_ETHER_FILTER_WRITE)
    * @insn = BPF filter instruction array
    * @insnlen = Length of BPF filter instruction array
    * return: -1 error or 0 ok
    */
   int
   io_etherFilter(int eth, int io, struct bpf_insn * __restrict insn, size_t insnlen)
   {
           int ret = 0;
           struct bpf_program fcode = { 0 };
   
           if (io != IO_ETHER_FILTER_PROMISC && (!insn || !insnlen)) {
                   io_SetErr(EINVAL, "invalid arguments");
                   return -1;
           }
   
           switch (io) {
                   case IO_ETHER_FILTER_PROMISC:   /* promiscuous mode */
                           ret = ioctl(eth, BIOCPROMISC, NULL);
                           break;
                   case IO_ETHER_FILTER_NOTREAD:   /* read not filter */
                           fcode.bf_len = insnlen / sizeof(struct bpf_insn);
                           fcode.bf_insns = insn;
                           ret = ioctl(eth, BIOCSETFNR, &fcode);
                           break;
                   case IO_ETHER_FILTER_READ:      /* read filter */
                           fcode.bf_len = insnlen / sizeof(struct bpf_insn);
                           fcode.bf_insns = insn;
                           ret = ioctl(eth, BIOCSETF, &fcode);
                           break;
                   case IO_ETHER_FILTER_WRITE:     /* write filter */
                           fcode.bf_len = insnlen / sizeof(struct bpf_insn);
                           fcode.bf_insns = insn;
                           ret = ioctl(eth, BIOCSETWF, &fcode);
                           break;
           }
   
           if (ret == -1)
                   LOGERR;
           return ret;
 }  }

Removed from v.1.2  
changed lines
  Added in v.1.7


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>