some tun interface code

pull/13/head
Jeff Becker 6 years ago
parent 54f70f370a
commit 04bf8d6116
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -182,14 +182,14 @@ else()
endif(UNIX) endif(UNIX)
if(TUNTAP) if(TUNTAP)
set(LIBTUNTAP_SRC set(LIBTUNTAP_SRC_BASE
${TT_ROOT}/tuntap.c ${TT_ROOT}/tuntap.c
${TT_ROOT}/tuntap_log.cpp ${TT_ROOT}/tuntap_log.cpp
${LIBTUNTAP_IMPL}) ${LIBTUNTAP_IMPL})
if (UNIX) if (UNIX)
set(LIBTUNTAP_SRC set(LIBTUNTAP_SRC
${TT_ROOT}/tuntap-unix.c ${TT_ROOT}/tuntap-unix.c
${LIBTUNTAP_SRC}) ${LIBTUNTAP_SRC_BASE})
endif() endif()
else() else()
set(LIBTUNTAP_SRC "") set(LIBTUNTAP_SRC "")
@ -241,6 +241,8 @@ set(LIB_PLATFORM_SRC
llarp/threadpool.cpp llarp/threadpool.cpp
# for android shim # for android shim
${ANDROID_PLATFORM_SRC} ${ANDROID_PLATFORM_SRC}
# tun
${LIBTUNTAP_SRC}
# win32 inline procs # win32 inline procs
llarp/win32_inet.c llarp/win32_inet.c
llarp/win32_intrnl.c llarp/win32_intrnl.c
@ -356,7 +358,7 @@ set(LIB_SRC
llarp/service/protocol.cpp llarp/service/protocol.cpp
llarp/service/tag.cpp llarp/service/tag.cpp
llarp/service/info.cpp llarp/service/info.cpp
${LIBTUNTAP_SRC}
) )
set(DNS_SRC set(DNS_SRC

@ -8,13 +8,14 @@
#define ssize_t long #define ssize_t long
#endif #endif
#else #else
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif #endif
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <tuntap.h>
/** /**
* ev.h * ev.h
* *
@ -74,4 +75,29 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const struct sockaddr *to,
int int
llarp_ev_close_udp(struct llarp_udp_io *udp); llarp_ev_close_udp(struct llarp_udp_io *udp);
struct llarp_tun_io
{
// TODO: more info?
char ifaddr[128];
int netmask;
char ifname[IFNAMSIZ + 1];
void *user;
void *impl;
struct llarp_ev_loop *parent;
/// called every event loop tick after reads
void (*tick)(struct llarp_tun_io *);
void (*recvpkt)(struct llarp_tun_io *, const void *, ssize_t);
};
/// create tun interface with network interface name ifname
/// returns true on success otherwise returns false
bool
llarp_ev_add_tun(struct llarp_ev_loop *ev, struct llarp_tun_io *tun);
/// async write a packet on tun interface
/// returns true if queued, returns false on drop
bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz);
#endif #endif

@ -13,6 +13,7 @@ namespace llarp
~TunEndpoint(); ~TunEndpoint();
device* m_tunif; device* m_tunif;
std::string m_IfName;
}; };
} // namespace service } // namespace service
} // namespace llarp } // namespace llarp

@ -105,3 +105,15 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
} }
return ret; return ret;
} }
bool
llarp_ev_add_tun(struct llarp_ev_loop *loop, struct llarp_tun_io *tun)
{
return loop->create_tun(tun);
}
bool
llarp_ev_tun_async_write(struct llarp_tun_io *tun, const void *pkt, size_t sz)
{
return static_cast< llarp::ev_io * >(tun->impl)->queue_write(pkt, sz);
}

@ -5,7 +5,13 @@
#ifndef _MSC_VER #ifndef _MSC_VER
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <llarp/buffer.h>
#include <list> #include <list>
#include <llarp/codel.hpp>
#include <vector>
#ifndef MAX_WRITE_QUEUE_SIZE
#define MAX_WRITE_QUEUE_SIZE 1024
#endif
namespace llarp namespace llarp
{ {
@ -13,10 +19,10 @@ namespace llarp
{ {
#ifndef _WIN32 #ifndef _WIN32
int fd; int fd;
ev_io(int f) : fd(f){}; ev_io(int f) : fd(f), m_writeq("writequeue"){};
#else #else
SOCKET fd; SOCKET fd;
ev_io(SOCKET f) : fd(f){}; ev_io(SOCKET f) : fd(f), m_writeq("writequeue"){};
#endif #endif
virtual int virtual int
read(void* buf, size_t sz) = 0; read(void* buf, size_t sz) = 0;
@ -24,6 +30,79 @@ namespace llarp
virtual int virtual int
sendto(const sockaddr* dst, const void* data, size_t sz) = 0; sendto(const sockaddr* dst, const void* data, size_t sz) = 0;
/// used for tun interface
bool
queue_write(const void* data, size_t sz)
{
m_writeq.Put(new WriteBuffer(data, sz));
return m_writeq.Size() <= MAX_WRITE_QUEUE_SIZE;
}
/// called in event loop when fd is ready for writing
/// drops all buffers that cannot be written in this pump
/// this assumes fd is set to non blocking
void
flush_write()
{
std::queue< WriteBuffer* > send;
m_writeq.Process(send);
while(send.size())
{
auto& buffer = send.front();
if(write(fd, buffer->payload.data(), buffer->payload.size()) == -1)
{
// failed to write
// TODO: should we requeue this buffer?
}
delete buffer;
}
/// reset errno
errno = 0;
}
struct WriteBuffer
{
llarp_time_t timestamp = 0;
std::vector< byte_t > payload;
WriteBuffer(const void* ptr, size_t sz) : payload(sz)
{
memcpy(payload.data(), ptr, sz);
}
struct GetTime
{
llarp_time_t
operator()(const WriteBuffer* w) const
{
return w->timestamp;
}
};
struct PutTime
{
void
operator()(WriteBuffer*& w) const
{
w->timestamp = llarp_time_now_ms();
}
};
struct Compare
{
bool
operator()(const WriteBuffer* left, const WriteBuffer* right) const
{
return left->timestamp < right->timestamp;
}
};
};
llarp::util::CoDelQueue< WriteBuffer*, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
llarp::util::NullMutex, llarp::util::NullLock >
m_writeq;
virtual ~ev_io() virtual ~ev_io()
{ {
#ifndef _WIN32 #ifndef _WIN32
@ -33,6 +112,7 @@ namespace llarp
#endif #endif
}; };
}; };
}; // namespace llarp }; // namespace llarp
struct llarp_ev_loop struct llarp_ev_loop
@ -49,18 +129,44 @@ struct llarp_ev_loop
stop() = 0; stop() = 0;
virtual bool virtual bool
udp_listen(llarp_udp_io* l, const sockaddr* src) = 0; udp_listen(llarp_udp_io* l, const sockaddr* src)
{
auto ev = create_udp(l, src);
return ev && add_ev(ev);
}
virtual llarp::ev_io*
create_udp(llarp_udp_io* l, const sockaddr* src) = 0;
virtual bool virtual bool
udp_close(llarp_udp_io* l) = 0; udp_close(llarp_udp_io* l) = 0;
virtual bool virtual bool
close_ev(llarp::ev_io* ev) = 0; close_ev(llarp::ev_io* ev) = 0;
virtual llarp::ev_io*
create_tun(llarp_tun_io* tun) = 0;
virtual bool
add_ev(llarp::ev_io* ev) = 0;
virtual bool virtual bool
running() const = 0; running() const = 0;
virtual ~llarp_ev_loop(){}; virtual ~llarp_ev_loop(){};
std::list< llarp_udp_io* > udp_listeners; std::list< llarp_udp_io* > udp_listeners;
std::list< llarp_tun_io* > tun_listeners;
void
tick_listeners()
{
for(auto& l : udp_listeners)
if(l->tick)
l->tick(l);
for(auto& l : tun_listeners)
if(l->tick)
l->tick(l);
}
}; };
#endif #endif

@ -4,6 +4,7 @@
#include <llarp/net.h> #include <llarp/net.h>
#include <signal.h> #include <signal.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <tuntap.h>
#include <unistd.h> #include <unistd.h>
#include <cstdio> #include <cstdio>
#include "ev.hpp" #include "ev.hpp"
@ -58,6 +59,50 @@ namespace llarp
return sent; return sent;
} }
}; };
struct tun : public ev_io
{
llarp_tun_io* t;
device* tunif;
tun(llarp_tun_io* tio)
: ev_io(-1)
, t(tio)
, tunif(tuntap_init())
{
};
int
sendto(const sockaddr* to, const void* data, size_t sz)
{
// TODO: implement me
return -1;
}
int
read(void* buf, size_t sz)
{
return tuntap_read(tunif, buf, sz);
}
bool
setup()
{
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1)
return false;
if(tuntap_set_ifname(tunif, t->ifname) == -1)
return false;
if(tuntap_set_ip(tunif, t->ifaddr, t->netmask) == -1)
return false;
fd = tunif->tun_fd;
return false;
}
~tun()
{
}
};
}; // namespace llarp }; // namespace llarp
struct llarp_epoll_loop : public llarp_ev_loop struct llarp_epoll_loop : public llarp_ev_loop
@ -129,12 +174,14 @@ struct llarp_epoll_loop : public llarp_ev_loop
{ {
ev->read(readbuf, sizeof(readbuf)); ev->read(readbuf, sizeof(readbuf));
} }
if(events[idx].events & EPOLLOUT)
{
ev->flush_write();
}
++idx; ++idx;
} }
} }
for(auto& l : udp_listeners) tick_listeners();
if(l->tick)
l->tick(l);
return result; return result;
} }
@ -162,12 +209,14 @@ struct llarp_epoll_loop : public llarp_ev_loop
{ {
ev->read(readbuf, sizeof(readbuf)); ev->read(readbuf, sizeof(readbuf));
} }
if(events[idx].events & EPOLLOUT)
{
ev->flush_write();
}
++idx; ++idx;
} }
} }
for(auto& l : udp_listeners) tick_listeners();
if(l->tick)
l->tick(l);
} while(epollfd != -1); } while(epollfd != -1);
return result; return result;
} }
@ -224,23 +273,39 @@ struct llarp_epoll_loop : public llarp_ev_loop
return epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, nullptr) != -1; return epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, nullptr) != -1;
} }
bool llarp::ev_io*
udp_listen(llarp_udp_io* l, const sockaddr* src) create_tun(llarp_tun_io* tun)
{
llarp::tun* t = new llarp::tun(tun);
if(t->setup())
return t;
delete t;
return nullptr;
}
llarp::ev_io*
create_udp(llarp_udp_io* l, const sockaddr* src)
{ {
int fd = udp_bind(src); int fd = udp_bind(src);
if(fd == -1) if(fd == -1)
return false; return nullptr;
llarp::udp_listener* listener = new llarp::udp_listener(fd, l); llarp::udp_listener* listener = new llarp::udp_listener(fd, l);
l->impl = listener;
udp_listeners.push_back(l);
return listener;
}
bool
add_ev(llarp::ev_io* e)
{
epoll_event ev; epoll_event ev;
ev.data.ptr = listener; ev.data.ptr = e;
ev.events = EPOLLIN; ev.events = EPOLLIN | EPOLLOUT;
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) if(epoll_ctl(epollfd, EPOLL_CTL_ADD, e->fd, &ev) == -1)
{ {
delete listener; delete e;
return false; return false;
} }
l->impl = listener;
udp_listeners.push_back(l);
return true; return true;
} }

@ -125,9 +125,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
++idx; ++idx;
} }
} }
for(auto& l : udp_listeners) tick_listeners();
if(l->tick)
l->tick(l);
return result; return result;
} }
@ -162,9 +160,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
++idx; ++idx;
} }
} }
for(auto& l : udp_listeners) tick_listeners();
if(l->tick)
l->tick(l);
} while(result != -1); } while(result != -1);
return result; return result;
} }

@ -0,0 +1,20 @@
#include <llarp/service/tun.hpp>
namespace llarp
{
namespace service
{
TunEndpoint::TunEndpoint(const std::string &ifname, llarp_router *r)
: Endpoint("tunif-" + ifname, r)
, m_tunif(tuntap_init())
, m_IfName(ifname)
{
}
TunEndpoint::~TunEndpoint()
{
tuntap_destroy(m_tunif);
}
} // namespace service
} // namespace llarp

@ -25,24 +25,24 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h>
#if defined Linux #if defined Linux
# include <netinet/ether.h> #include <linux/if_tun.h>
# include <linux/if_tun.h> #include <netinet/ether.h>
#else #else
# include <net/if.h> #include <net/if.h>
# if defined DragonFly #if defined DragonFly
# include <net/tun/if_tun.h> #include <net/tun/if_tun.h>
# elif !defined Darwin #elif !defined Darwin
# include <net/if_tun.h> #include <net/if_tun.h>
# endif #endif
# include <netinet/in.h> #include <netinet/if_ether.h>
# include <netinet/if_ether.h> #include <netinet/in.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -51,310 +51,358 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "tuntap.h" #include <tuntap.h>
int int
tuntap_start(struct device *dev, int mode, int tun) { tuntap_start(struct device *dev, int mode, int tun)
int sock; {
int fd; int sock;
int fd;
fd = sock = -1;
fd = sock = -1;
/* Don't re-initialise a previously started device */
if (dev->tun_fd != -1) { /* Don't re-initialise a previously started device */
tuntap_log(TUNTAP_LOG_ERR, "Device is already started"); if(dev->tun_fd != -1)
return -1; {
} tuntap_log(TUNTAP_LOG_ERR, "Device is already started");
return -1;
sock = socket(AF_INET, SOCK_DGRAM, 0); }
if (sock == -1) {
goto clean; sock = socket(AF_INET, SOCK_DGRAM, 0);
} if(sock == -1)
dev->ctrl_sock = sock; {
goto clean;
if (mode & TUNTAP_MODE_PERSIST && tun == TUNTAP_ID_ANY) { }
goto clean; /* XXX: Explain why */ dev->ctrl_sock = sock;
}
if(mode & TUNTAP_MODE_PERSIST && tun == TUNTAP_ID_ANY)
fd = tuntap_sys_start(dev, mode, tun); {
if (fd == -1) { goto clean; /* XXX: Explain why */
goto clean; }
}
fd = tuntap_sys_start(dev, mode, tun);
dev->tun_fd = fd; if(fd == -1)
tuntap_set_debug(dev, 0); {
return 0; goto clean;
}
dev->tun_fd = fd;
tuntap_set_debug(dev, 0);
return 0;
clean: clean:
if (fd != -1) { if(fd != -1)
(void)close(fd); {
} (void)close(fd);
if (sock != -1) { }
(void)close(sock); if(sock != -1)
} {
return -1; (void)close(sock);
}
return -1;
} }
void void
tuntap_release(struct device *dev) { tuntap_release(struct device *dev)
(void)close(dev->tun_fd); {
(void)close(dev->ctrl_sock); (void)close(dev->tun_fd);
free(dev); (void)close(dev->ctrl_sock);
free(dev);
} }
int int
tuntap_set_descr(struct device *dev, const char *descr) { tuntap_set_descr(struct device *dev, const char *descr)
size_t len; {
size_t len;
if (descr == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'descr'"); if(descr == NULL)
return -1; {
} tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'descr'");
return -1;
len = strlen(descr); }
if (len > IF_DESCRSIZE) {
/* The value will be troncated */ len = strlen(descr);
tuntap_log(TUNTAP_LOG_WARN, "Parameter 'descr' is too long"); if(len > IF_DESCRSIZE)
} {
/* The value will be troncated */
if (tuntap_sys_set_descr(dev, descr, len) == -1) { tuntap_log(TUNTAP_LOG_WARN, "Parameter 'descr' is too long");
return -1; }
}
return 0; if(tuntap_sys_set_descr(dev, descr, len) == -1)
{
return -1;
}
return 0;
} }
int int
tuntap_set_ifname(struct device *dev, const char *ifname) { tuntap_set_ifname(struct device *dev, const char *ifname)
size_t len; {
size_t len;
if (ifname == NULL) {
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'ifname'"); if(ifname == NULL)
return -1; {
} tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'ifname'");
return -1;
len = strlen(ifname); }
if (len > IF_NAMESIZE) {
tuntap_log(TUNTAP_LOG_ERR, "Parameter 'ifname' is too long"); len = strlen(ifname);
return -1; if(len > IF_NAMESIZE)
} {
tuntap_log(TUNTAP_LOG_ERR, "Parameter 'ifname' is too long");
if (tuntap_sys_set_ifname(dev, ifname, len) == -1) { return -1;
return -1; }
}
if(tuntap_sys_set_ifname(dev, ifname, len) == -1)
(void)memset(dev->if_name, 0, IF_NAMESIZE); {
(void)strncpy(dev->if_name, ifname, len); return -1;
return 0; }
(void)memset(dev->if_name, 0, IF_NAMESIZE);
(void)strncpy(dev->if_name, ifname, len);
return 0;
} }
char * char *
tuntap_get_hwaddr(struct device *dev) { tuntap_get_hwaddr(struct device *dev)
struct ether_addr eth_attr; {
struct ether_addr eth_attr;
(void)memcpy(&eth_attr, dev->hwaddr, sizeof dev->hwaddr); (void)memcpy(&eth_attr, dev->hwaddr, sizeof dev->hwaddr);
return ether_ntoa(&eth_attr); return ether_ntoa(&eth_attr);
} }
int int
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) { tuntap_set_hwaddr(struct device *dev, const char *hwaddr)
struct ether_addr *eth_addr, eth_rand; {
struct ether_addr *eth_addr, eth_rand;
if (strcmp(hwaddr, "random") == 0) {
unsigned int i; if(strcmp(hwaddr, "random") == 0)
unsigned char *ptr; {
unsigned int i;
i = 0; unsigned char *ptr;
ptr = (unsigned char *)&eth_rand;
srandom((unsigned int)time(NULL)); i = 0;
for (; i < sizeof eth_rand; ++i) { ptr = (unsigned char *)&eth_rand;
*ptr = (unsigned char)random(); srandom((unsigned int)time(NULL));
ptr++; for(; i < sizeof eth_rand; ++i)
} {
ptr = (unsigned char *)&eth_rand; *ptr = (unsigned char)random();
*ptr &= 0xfc; ptr++;
eth_addr = &eth_rand; }
} else { ptr = (unsigned char *)&eth_rand;
eth_addr = ether_aton(hwaddr); *ptr &= 0xfc;
if (eth_addr == NULL) { eth_addr = &eth_rand;
return -1; }
} else
} {
(void)memcpy(dev->hwaddr, eth_addr, ETHER_ADDR_LEN); eth_addr = ether_aton(hwaddr);
if(eth_addr == NULL)
if (tuntap_sys_set_hwaddr(dev, eth_addr) == -1) {
return -1; return -1;
return 0; }
}
(void)memcpy(dev->hwaddr, eth_addr, ETHER_ADDR_LEN);
if(tuntap_sys_set_hwaddr(dev, eth_addr) == -1)
return -1;
return 0;
} }
int int
tuntap_up(struct device *dev) { tuntap_up(struct device *dev)
struct ifreq ifr; {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name); (void)memset(&ifr, '\0', sizeof ifr);
ifr.ifr_flags = (short int)dev->flags; (void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_flags |= IFF_UP; ifr.ifr_flags = (short int)dev->flags;
ifr.ifr_flags |= IFF_UP;
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
return -1; if(ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1)
} {
return -1;
dev->flags = ifr.ifr_flags; }
return 0;
dev->flags = ifr.ifr_flags;
return 0;
} }
int int
tuntap_down(struct device *dev) { tuntap_down(struct device *dev)
struct ifreq ifr; {
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name); (void)memset(&ifr, '\0', sizeof ifr);
ifr.ifr_flags = (short)dev->flags; (void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_flags &= ~IFF_UP; ifr.ifr_flags = (short)dev->flags;
ifr.ifr_flags &= ~IFF_UP;
if (ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1) {
return -1; if(ioctl(dev->ctrl_sock, SIOCSIFFLAGS, &ifr) == -1)
} {
return -1;
dev->flags = ifr.ifr_flags; }
return 0;
dev->flags = ifr.ifr_flags;
return 0;
} }
int int
tuntap_get_mtu(struct device *dev) { tuntap_get_mtu(struct device *dev)
struct ifreq ifr; {
struct ifreq ifr;
/* Only accept started device */
if (dev->tun_fd == -1) { /* Only accept started device */
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); if(dev->tun_fd == -1)
return 0; {
} tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
(void)memset(&ifr, '\0', sizeof ifr); }
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
(void)memset(&ifr, '\0', sizeof ifr);
if (ioctl(dev->ctrl_sock, SIOCGIFMTU, &ifr) == -1) { (void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
tuntap_log(TUNTAP_LOG_ERR, "Can't get MTU");
return -1; if(ioctl(dev->ctrl_sock, SIOCGIFMTU, &ifr) == -1)
} {
return ifr.ifr_mtu; tuntap_log(TUNTAP_LOG_ERR, "Can't get MTU");
return -1;
}
return ifr.ifr_mtu;
} }
int int
tuntap_set_mtu(struct device *dev, int mtu) { tuntap_set_mtu(struct device *dev, int mtu)
struct ifreq ifr; {
struct ifreq ifr;
/* Only accept started device */
if (dev->tun_fd == -1) { /* Only accept started device */
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); if(dev->tun_fd == -1)
return 0; {
} tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
(void)memset(&ifr, '\0', sizeof ifr); }
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
ifr.ifr_mtu = mtu; (void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
if (ioctl(dev->ctrl_sock, SIOCSIFMTU, &ifr) == -1) { ifr.ifr_mtu = mtu;
tuntap_log(TUNTAP_LOG_ERR, "Can't set MTU");
return -1; if(ioctl(dev->ctrl_sock, SIOCSIFMTU, &ifr) == -1)
} {
return 0; tuntap_log(TUNTAP_LOG_ERR, "Can't set MTU");
return -1;
}
return 0;
} }
int int
tuntap_read(struct device *dev, void *buf, size_t size) { tuntap_read(struct device *dev, void *buf, size_t size)
int n; {
int n;
/* Only accept started device */
if (dev->tun_fd == -1) { /* Only accept started device */
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); if(dev->tun_fd == -1)
return 0; {
} tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
n = read(dev->tun_fd, buf, size); }
if (n == -1) {
tuntap_log(TUNTAP_LOG_WARN, "Can't to read from device"); n = read(dev->tun_fd, buf, size);
return -1; if(n == -1)
} {
return n; tuntap_log(TUNTAP_LOG_WARN, "Can't to read from device");
return -1;
}
return n;
} }
int int
tuntap_write(struct device *dev, void *buf, size_t size) { tuntap_write(struct device *dev, void *buf, size_t size)
int n; {
int n;
/* Only accept started device */
if (dev->tun_fd == -1) { /* Only accept started device */
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); if(dev->tun_fd == -1)
return 0; {
} tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
n = write(dev->tun_fd, buf, size); }
if (n == -1) {
tuntap_log(TUNTAP_LOG_WARN, "Can't write to device"); n = write(dev->tun_fd, buf, size);
return -1; if(n == -1)
} {
return n; tuntap_log(TUNTAP_LOG_WARN, "Can't write to device");
return -1;
}
return n;
} }
int int
tuntap_get_readable(struct device *dev) { tuntap_get_readable(struct device *dev)
int n; {
int n;
n = 0;
if (ioctl(dev->tun_fd, FIONREAD, &n) == -1) { n = 0;
tuntap_log(TUNTAP_LOG_INFO, "Your system does not support" if(ioctl(dev->tun_fd, FIONREAD, &n) == -1)
" FIONREAD, fallback to MTU"); {
return tuntap_get_mtu(dev); tuntap_log(TUNTAP_LOG_INFO,
} "Your system does not support"
return n; " FIONREAD, fallback to MTU");
return tuntap_get_mtu(dev);
}
return n;
} }
int int
tuntap_set_nonblocking(struct device *dev, int set) { tuntap_set_nonblocking(struct device *dev, int set)
if (ioctl(dev->tun_fd, FIONBIO, &set) == -1) { {
switch(set) { if(ioctl(dev->tun_fd, FIONBIO, &set) == -1)
case 0: {
tuntap_log(TUNTAP_LOG_ERR, "Can't unset nonblocking"); switch(set)
break; {
case 1: case 0:
tuntap_log(TUNTAP_LOG_ERR, "Can't set nonblocking"); tuntap_log(TUNTAP_LOG_ERR, "Can't unset nonblocking");
break; break;
default: case 1:
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'"); tuntap_log(TUNTAP_LOG_ERR, "Can't set nonblocking");
} break;
return -1; default:
} tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
return 0; }
return -1;
}
return 0;
} }
int int
tuntap_set_debug(struct device *dev, int set) { tuntap_set_debug(struct device *dev, int set)
/* Only accept started device */ {
if (dev->tun_fd == -1) { /* Only accept started device */
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); if(dev->tun_fd == -1)
return 0; {
} tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
return 0;
}
#if !defined Darwin #if !defined Darwin
if (ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1) { if(ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1)
switch(set) { {
case 0: switch(set)
tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug"); {
break; case 0:
case 1: tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug");
tuntap_log(TUNTAP_LOG_WARN, "Can't set debug"); break;
break; case 1:
default: tuntap_log(TUNTAP_LOG_WARN, "Can't set debug");
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'"); break;
} default:
return -1; tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
} }
return 0; return -1;
}
return 0;
#else #else
tuntap_log(TUNTAP_LOG_NOTICE, tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_debug()"); "Your system does not support tuntap_set_debug()");
return -1; return -1;
#endif #endif
} }

@ -28,6 +28,8 @@
extern "C" extern "C"
{ {
t_tuntap_log tuntap_log = &tuntap_log_default;
void void
tuntap_log_set_cb(t_tuntap_log cb) tuntap_log_set_cb(t_tuntap_log cb)
{ {

Loading…
Cancel
Save