File:  [ELWIX - Embedded LightWeight unIX -] / libaitio / src / bpf.c
Revision 1.1.2.5: download - view: text, annotated - select for diffs - revision graph
Mon Jun 24 14:48:04 2013 UTC (11 years ago) by misho
Branches: io5_4
change

    1: #include "global.h"
    2: 
    3: 
    4: /*
    5:  * io_get1stiface() - Get first interface of host
    6:  *
    7:  * @szIface = interface string buffer
    8:  * @iflen = size of interface buffer
    9:  * return: -1 error or 0 ok
   10:  */
   11: int
   12: io_get1stiface(char *szIface, int iflen)
   13: {
   14: 	struct ifaddrs *ifa;
   15: 
   16: 	if (!szIface || !iflen)
   17: 		return -1;
   18: 
   19: 	getifaddrs(&ifa);
   20: 	strlcpy(szIface, ifa->ifa_name, iflen);
   21: 	freeifaddrs(ifa);
   22: 	return 0;
   23: }
   24: 
   25: /*
   26:  * io_etherClose() - Close BPF interface
   27:  *
   28:  * @eth = bpf handle
   29:  * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL
   30:  * return: none
   31:  */
   32: void
   33: io_etherClose(int eth, void **zcbuf)
   34: {
   35: #ifdef __FreeBSD__
   36: 	struct bpf_zbuf *zbuf = NULL;
   37: #endif
   38: 
   39: 	if (eth > STDERR_FILENO)
   40: 		close(eth);
   41: 
   42: 	if (zcbuf && *zcbuf) {
   43: #ifdef __FreeBSD__
   44: 		zbuf = *zcbuf;
   45: 		munmap(zbuf->bz_bufb, zbuf->bz_buflen);
   46: 		munmap(zbuf->bz_bufa, zbuf->bz_buflen);
   47: 		e_free(*zcbuf);
   48: 		*zcbuf = NULL;
   49: #endif
   50: 	}
   51: }
   52: 
   53: #ifdef __FreeBSD__
   54: static inline struct bpf_zbuf *
   55: allocZCbuf(u_int len)
   56: {
   57: 	struct bpf_zbuf *zbuf = NULL;
   58: 
   59: 	zbuf = e_malloc(sizeof(struct bpf_zbuf));
   60: 	if (!zbuf) {
   61: 		io_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
   62: 		return NULL;
   63: 	} else
   64: 		memset(zbuf, 0, sizeof(struct bpf_zbuf));
   65: 
   66: 	zbuf->bz_buflen = roundup(len, getpagesize());
   67: 	zbuf->bz_bufa = mmap(NULL, zbuf->bz_buflen, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
   68: 	if (zbuf->bz_bufa == MAP_FAILED) {
   69: 		LOGERR;
   70: 		e_free(zbuf);
   71: 		return NULL;
   72: 	} else
   73: 		memset(zbuf->bz_bufa, 0, zbuf->bz_buflen);
   74: 	zbuf->bz_bufb = mmap(NULL, zbuf->bz_buflen, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0);
   75: 	if (zbuf->bz_bufb == MAP_FAILED) {
   76: 		LOGERR;
   77: 		munmap(zbuf->bz_bufa, zbuf->bz_buflen);
   78: 		e_free(zbuf);
   79: 		return NULL;
   80: 	} else
   81: 		memset(zbuf->bz_bufb, 0, zbuf->bz_buflen);
   82: 
   83: 	return zbuf;
   84: }
   85: #endif
   86: 
   87: /*
   88:  * io_etherOpen() - Open BPF interface to device
   89:  *
   90:  * @csIface = interface name
   91:  * @flags = open flags
   92:  * @whdr = with complete headers
   93:  * @buflen = buffer length
   94:  * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL
   95:  * return: -1 error or >-1 bpf handle
   96:  */
   97: int
   98: io_etherOpen(const char *csIface, int flags, int whdr, u_int *buflen, void **zcbuf)
   99: {
  100: 	int n = 1, eth = -1;
  101: 	register int i;
  102: 	char szStr[STRSIZ];
  103: 	struct ifreq ifr;
  104: 
  105: 	for (i = 0; i < BPF_DEV_MAX; i++) {
  106: 		memset(szStr, 0, sizeof szStr);
  107: 		snprintf(szStr, sizeof szStr, "/dev/bpf%d", i);
  108: 		eth = open(szStr, flags);
  109: 		if (eth > STDERR_FILENO)
  110: 			break;
  111: 	}
  112: 	if (eth < 3) {
  113: 		LOGERR;
  114: 		return -1;
  115: 	}
  116: 
  117: 	if (ioctl(eth, BIOCIMMEDIATE, &n) == -1) {
  118: 		LOGERR;
  119: 		close(eth);
  120: 		return -1;
  121: 	}
  122: 	if (whdr && ioctl(eth, BIOCSHDRCMPLT, &n) == -1) {
  123: 		LOGERR;
  124: 		close(eth);
  125: 		return -1;
  126: 	}
  127: 	if (buflen && *buflen) {
  128: 		if (!zcbuf) {
  129: 			if (ioctl(eth, BIOCSBLEN, buflen) == -1) {
  130: 				LOGERR;
  131: 				close(eth);
  132: 				return -1;
  133: 			}
  134: 		} else {
  135: #ifdef __FreeBSD__
  136: 			n = BPF_BUFMODE_ZBUF;
  137: 			if (ioctl(eth, BIOCSETBUFMODE, &n) == -1) {
  138: 				LOGERR;
  139: 				close(eth);
  140: 				return -1;
  141: 			}
  142: 			if (ioctl(eth, BIOCGETZMAX, &n) == -1) {
  143: 				LOGERR;
  144: 				close(eth);
  145: 				return -1;
  146: 			} else
  147: 				*buflen = MIN(n, *buflen);
  148: 			if (!(*zcbuf = allocZCbuf(*buflen))) {
  149: 				close(eth);
  150: 				return -1;
  151: 			}
  152: 			if (ioctl(eth, BIOCSETZBUF, (struct bpf_zbuf*) *zcbuf) == -1) {
  153: 				LOGERR;
  154: 				io_etherClose(eth, zcbuf);
  155: 				return -1;
  156: 			}
  157: #endif
  158: 		}
  159: 	}
  160: 	if (csIface)
  161: 		strlcpy(szStr, csIface, sizeof szStr);
  162: 	else if (io_get1stiface(szStr, sizeof szStr) == -1) {
  163: 		io_etherClose(eth, zcbuf);
  164: 		return -1;
  165: 	}
  166: 	strlcpy(ifr.ifr_name, szStr, sizeof ifr.ifr_name);
  167: 	if (ioctl(eth, BIOCSETIF, &ifr) == -1) {
  168: 		LOGERR;
  169: 		io_etherClose(eth, zcbuf);
  170: 		return -1;
  171: 	}
  172: 
  173: 	return eth;
  174: }

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