version 1.2, 2013/06/26 22:48:53
|
version 1.6, 2014/02/08 22:06:17
|
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, 2013 | Copyright 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 68 io_get1stiface(char *szIface, int iflen)
|
Line 68 io_get1stiface(char *szIface, int iflen)
|
} |
} |
|
|
/* |
/* |
|
* io_getmaciface() - Get MAC address from interface name |
|
* |
|
* @csIface = interface name |
|
* @ea = ethernet address |
|
* return: -1 error, 0 ok or 1 not found |
|
*/ |
|
int |
|
io_getmaciface(const char *csIface, ether_addr_t * __restrict ea) |
|
{ |
|
struct ifaddrs *ifa, *ifp; |
|
struct sockaddr_dl *dl; |
|
int ret = 1; |
|
|
|
if (!csIface || !ea) |
|
return -1; |
|
else |
|
memset(ea, 0, sizeof(ether_addr_t)); |
|
|
|
getifaddrs(&ifa); |
|
for (ifp = ifa; ifp; ifp = ifp->ifa_next) |
|
if (!strcmp(csIface, ifp->ifa_name) && ifp->ifa_addr && |
|
ifp->ifa_addr->sa_family == AF_LINK) { |
|
dl = (struct sockaddr_dl*) ifp->ifa_addr; |
|
if ((dl->sdl_type == IFT_ETHER || dl->sdl_type == IFT_L2VLAN || |
|
dl->sdl_type == IFT_BRIDGE) && |
|
dl->sdl_alen == ETHER_ADDR_LEN) { |
|
memcpy(ea, LLADDR(dl), sizeof(ether_addr_t)); |
|
ret = 0; |
|
break; |
|
} |
|
} |
|
freeifaddrs(ifa); |
|
|
|
return ret; |
|
} |
|
|
|
/* |
* 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 114 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 122 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 132 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 172 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 187 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 206 io_etherOpen(const char *csIface, int flags, int whdr,
|
return -1; |
return -1; |
} |
} |
|
|
|
if (csIface) |
|
strlcpy(szStr, csIface, sizeof szStr); |
|
else if (io_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 268 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 276 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 310 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 369 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 378 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 393 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; |
} |
} |