Annotation of libaitio/src/bpf.c, revision 1.1.2.3
1.1.2.1 misho 1: #include "global.h"
2:
3:
1.1.2.2 misho 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
1.1.2.3 ! misho 29: * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL
1.1.2.2 misho 30: * return: none
31: */
32: void
1.1.2.3 ! misho 33: io_etherClose(int eth, void **zcbuf)
1.1.2.2 misho 34: {
1.1.2.3 ! misho 35: #ifdef __FreeBSD__
! 36: struct bpf_zbuf *zbuf = NULL;
! 37: #endif
! 38:
1.1.2.2 misho 39: if (eth > STDERR_FILENO)
40: close(eth);
1.1.2.3 ! misho 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;
1.1.2.2 misho 84: }
1.1.2.3 ! misho 85: #endif
1.1.2.2 misho 86:
87: /*
88: * io_etherOpen() - Open BPF interface to device
89: *
90: * @csIface = interface name
91: * @flags = open flags
1.1.2.3 ! misho 92: * @whdr = with complete headers
! 93: * @buflen = buffer length
! 94: * @zcbuf = zero copy buffer, if BPF supports it and isn't NULL
1.1.2.2 misho 95: * return: -1 error or >-1 bpf handle
96: */
97: int
1.1.2.3 ! misho 98: io_etherOpen(const char *csIface, int flags, int whdr, u_int buflen, void **zcbuf)
1.1.2.2 misho 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: }
1.1.2.3 ! misho 122: if (whdr && ioctl(eth, BIOCSHDRCMPLT, &n) == -1) {
1.1.2.2 misho 123: LOGERR;
124: close(eth);
125: return -1;
126: }
1.1.2.3 ! misho 127: if (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: }
! 147: if (!(*zcbuf = allocZCbuf(MIN(n, buflen)))) {
! 148: close(eth);
! 149: return -1;
! 150: }
! 151: if (ioctl(eth, BIOCSETZBUF, (struct bpf_zbuf*) *zcbuf) == -1) {
! 152: LOGERR;
! 153: io_etherClose(eth, zcbuf);
! 154: return -1;
! 155: }
! 156: #endif
! 157: }
! 158: }
1.1.2.2 misho 159: if (csIface)
160: strlcpy(szStr, csIface, sizeof szStr);
161: else if (io_get1stiface(szStr, sizeof szStr) == -1) {
1.1.2.3 ! misho 162: io_etherClose(eth, zcbuf);
1.1.2.2 misho 163: return -1;
164: }
165: strlcpy(ifr.ifr_name, szStr, sizeof ifr.ifr_name);
166: if (ioctl(eth, BIOCSETIF, &ifr) == -1) {
167: LOGERR;
1.1.2.3 ! misho 168: io_etherClose(eth, zcbuf);
1.1.2.2 misho 169: return -1;
170: }
171:
172: return eth;
173: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>