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>