mirror of https://github.com/oxen-io/lokinet
some tun interface code
This commit is contained in:
parent
54f70f370a
commit
04bf8d6116
|
@ -182,14 +182,14 @@ else()
|
|||
endif(UNIX)
|
||||
|
||||
if(TUNTAP)
|
||||
set(LIBTUNTAP_SRC
|
||||
set(LIBTUNTAP_SRC_BASE
|
||||
${TT_ROOT}/tuntap.c
|
||||
${TT_ROOT}/tuntap_log.cpp
|
||||
${LIBTUNTAP_IMPL})
|
||||
if (UNIX)
|
||||
set(LIBTUNTAP_SRC
|
||||
${TT_ROOT}/tuntap-unix.c
|
||||
${LIBTUNTAP_SRC})
|
||||
${LIBTUNTAP_SRC_BASE})
|
||||
endif()
|
||||
else()
|
||||
set(LIBTUNTAP_SRC "")
|
||||
|
@ -241,6 +241,8 @@ set(LIB_PLATFORM_SRC
|
|||
llarp/threadpool.cpp
|
||||
# for android shim
|
||||
${ANDROID_PLATFORM_SRC}
|
||||
# tun
|
||||
${LIBTUNTAP_SRC}
|
||||
# win32 inline procs
|
||||
llarp/win32_inet.c
|
||||
llarp/win32_intrnl.c
|
||||
|
@ -356,7 +358,7 @@ set(LIB_SRC
|
|||
llarp/service/protocol.cpp
|
||||
llarp/service/tag.cpp
|
||||
llarp/service/info.cpp
|
||||
${LIBTUNTAP_SRC}
|
||||
|
||||
)
|
||||
|
||||
set(DNS_SRC
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
#define ssize_t long
|
||||
#endif
|
||||
#else
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <tuntap.h>
|
||||
/**
|
||||
* ev.h
|
||||
*
|
||||
|
@ -74,4 +75,29 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const struct sockaddr *to,
|
|||
int
|
||||
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
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace llarp
|
|||
~TunEndpoint();
|
||||
|
||||
device* m_tunif;
|
||||
std::string m_IfName;
|
||||
};
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
|
12
llarp/ev.cpp
12
llarp/ev.cpp
|
@ -105,3 +105,15 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to,
|
|||
}
|
||||
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);
|
||||
}
|
112
llarp/ev.hpp
112
llarp/ev.hpp
|
@ -5,7 +5,13 @@
|
|||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <llarp/buffer.h>
|
||||
#include <list>
|
||||
#include <llarp/codel.hpp>
|
||||
#include <vector>
|
||||
#ifndef MAX_WRITE_QUEUE_SIZE
|
||||
#define MAX_WRITE_QUEUE_SIZE 1024
|
||||
#endif
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -13,10 +19,10 @@ namespace llarp
|
|||
{
|
||||
#ifndef _WIN32
|
||||
int fd;
|
||||
ev_io(int f) : fd(f){};
|
||||
ev_io(int f) : fd(f), m_writeq("writequeue"){};
|
||||
#else
|
||||
SOCKET fd;
|
||||
ev_io(SOCKET f) : fd(f){};
|
||||
ev_io(SOCKET f) : fd(f), m_writeq("writequeue"){};
|
||||
#endif
|
||||
virtual int
|
||||
read(void* buf, size_t sz) = 0;
|
||||
|
@ -24,6 +30,79 @@ namespace llarp
|
|||
virtual int
|
||||
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()
|
||||
{
|
||||
#ifndef _WIN32
|
||||
|
@ -33,6 +112,7 @@ namespace llarp
|
|||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
}; // namespace llarp
|
||||
|
||||
struct llarp_ev_loop
|
||||
|
@ -49,18 +129,44 @@ struct llarp_ev_loop
|
|||
stop() = 0;
|
||||
|
||||
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
|
||||
udp_close(llarp_udp_io* l) = 0;
|
||||
virtual bool
|
||||
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
|
||||
running() const = 0;
|
||||
|
||||
virtual ~llarp_ev_loop(){};
|
||||
|
||||
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
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <llarp/net.h>
|
||||
#include <signal.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <tuntap.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
#include "ev.hpp"
|
||||
|
@ -58,6 +59,50 @@ namespace llarp
|
|||
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
|
||||
|
||||
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));
|
||||
}
|
||||
if(events[idx].events & EPOLLOUT)
|
||||
{
|
||||
ev->flush_write();
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
for(auto& l : udp_listeners)
|
||||
if(l->tick)
|
||||
l->tick(l);
|
||||
tick_listeners();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -162,12 +209,14 @@ struct llarp_epoll_loop : public llarp_ev_loop
|
|||
{
|
||||
ev->read(readbuf, sizeof(readbuf));
|
||||
}
|
||||
if(events[idx].events & EPOLLOUT)
|
||||
{
|
||||
ev->flush_write();
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
for(auto& l : udp_listeners)
|
||||
if(l->tick)
|
||||
l->tick(l);
|
||||
tick_listeners();
|
||||
} while(epollfd != -1);
|
||||
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;
|
||||
}
|
||||
|
||||
bool
|
||||
udp_listen(llarp_udp_io* l, const sockaddr* src)
|
||||
llarp::ev_io*
|
||||
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);
|
||||
if(fd == -1)
|
||||
return false;
|
||||
return nullptr;
|
||||
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;
|
||||
ev.data.ptr = listener;
|
||||
ev.events = EPOLLIN;
|
||||
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1)
|
||||
ev.data.ptr = e;
|
||||
ev.events = EPOLLIN | EPOLLOUT;
|
||||
if(epoll_ctl(epollfd, EPOLL_CTL_ADD, e->fd, &ev) == -1)
|
||||
{
|
||||
delete listener;
|
||||
delete e;
|
||||
return false;
|
||||
}
|
||||
l->impl = listener;
|
||||
udp_listeners.push_back(l);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,9 +125,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
|
|||
++idx;
|
||||
}
|
||||
}
|
||||
for(auto& l : udp_listeners)
|
||||
if(l->tick)
|
||||
l->tick(l);
|
||||
tick_listeners();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -162,9 +160,7 @@ struct llarp_kqueue_loop : public llarp_ev_loop
|
|||
++idx;
|
||||
}
|
||||
}
|
||||
for(auto& l : udp_listeners)
|
||||
if(l->tick)
|
||||
l->tick(l);
|
||||
tick_listeners();
|
||||
} while(result != -1);
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#if defined Linux
|
||||
# include <netinet/ether.h>
|
||||
# include <linux/if_tun.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <netinet/ether.h>
|
||||
#else
|
||||
# include <net/if.h>
|
||||
# if defined DragonFly
|
||||
# include <net/tun/if_tun.h>
|
||||
# elif !defined Darwin
|
||||
# include <net/if_tun.h>
|
||||
# endif
|
||||
# include <netinet/in.h>
|
||||
# include <netinet/if_ether.h>
|
||||
#include <net/if.h>
|
||||
#if defined DragonFly
|
||||
#include <net/tun/if_tun.h>
|
||||
#elif !defined Darwin
|
||||
#include <net/if_tun.h>
|
||||
#endif
|
||||
#include <netinet/if_ether.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -51,310 +51,358 @@
|
|||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tuntap.h"
|
||||
#include <tuntap.h>
|
||||
|
||||
int
|
||||
tuntap_start(struct device *dev, int mode, int tun) {
|
||||
int sock;
|
||||
int fd;
|
||||
tuntap_start(struct device *dev, int mode, int tun)
|
||||
{
|
||||
int sock;
|
||||
int fd;
|
||||
|
||||
fd = sock = -1;
|
||||
fd = sock = -1;
|
||||
|
||||
/* Don't re-initialise a previously started device */
|
||||
if (dev->tun_fd != -1) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Device is already started");
|
||||
return -1;
|
||||
}
|
||||
/* Don't re-initialise a previously started device */
|
||||
if(dev->tun_fd != -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Device is already started");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock == -1) {
|
||||
goto clean;
|
||||
}
|
||||
dev->ctrl_sock = sock;
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sock == -1)
|
||||
{
|
||||
goto clean;
|
||||
}
|
||||
dev->ctrl_sock = sock;
|
||||
|
||||
if (mode & TUNTAP_MODE_PERSIST && tun == TUNTAP_ID_ANY) {
|
||||
goto clean; /* XXX: Explain why */
|
||||
}
|
||||
if(mode & TUNTAP_MODE_PERSIST && tun == TUNTAP_ID_ANY)
|
||||
{
|
||||
goto clean; /* XXX: Explain why */
|
||||
}
|
||||
|
||||
fd = tuntap_sys_start(dev, mode, tun);
|
||||
if (fd == -1) {
|
||||
goto clean;
|
||||
}
|
||||
fd = tuntap_sys_start(dev, mode, tun);
|
||||
if(fd == -1)
|
||||
{
|
||||
goto clean;
|
||||
}
|
||||
|
||||
dev->tun_fd = fd;
|
||||
tuntap_set_debug(dev, 0);
|
||||
return 0;
|
||||
dev->tun_fd = fd;
|
||||
tuntap_set_debug(dev, 0);
|
||||
return 0;
|
||||
|
||||
clean:
|
||||
if (fd != -1) {
|
||||
(void)close(fd);
|
||||
}
|
||||
if (sock != -1) {
|
||||
(void)close(sock);
|
||||
}
|
||||
return -1;
|
||||
if(fd != -1)
|
||||
{
|
||||
(void)close(fd);
|
||||
}
|
||||
if(sock != -1)
|
||||
{
|
||||
(void)close(sock);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
tuntap_release(struct device *dev) {
|
||||
(void)close(dev->tun_fd);
|
||||
(void)close(dev->ctrl_sock);
|
||||
free(dev);
|
||||
tuntap_release(struct device *dev)
|
||||
{
|
||||
(void)close(dev->tun_fd);
|
||||
(void)close(dev->ctrl_sock);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_descr(struct device *dev, const char *descr) {
|
||||
size_t len;
|
||||
tuntap_set_descr(struct device *dev, const char *descr)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (descr == NULL) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'descr'");
|
||||
return -1;
|
||||
}
|
||||
if(descr == NULL)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'descr'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = strlen(descr);
|
||||
if (len > IF_DESCRSIZE) {
|
||||
/* The value will be troncated */
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Parameter 'descr' is too long");
|
||||
}
|
||||
len = strlen(descr);
|
||||
if(len > IF_DESCRSIZE)
|
||||
{
|
||||
/* The value will be troncated */
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Parameter 'descr' is too long");
|
||||
}
|
||||
|
||||
if (tuntap_sys_set_descr(dev, descr, len) == -1) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if(tuntap_sys_set_descr(dev, descr, len) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_ifname(struct device *dev, const char *ifname) {
|
||||
size_t len;
|
||||
tuntap_set_ifname(struct device *dev, const char *ifname)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (ifname == NULL) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'ifname'");
|
||||
return -1;
|
||||
}
|
||||
if(ifname == NULL)
|
||||
{
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
len = strlen(ifname);
|
||||
if(len > IF_NAMESIZE)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Parameter 'ifname' is too long");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tuntap_sys_set_ifname(dev, ifname, len) == -1) {
|
||||
return -1;
|
||||
}
|
||||
if(tuntap_sys_set_ifname(dev, ifname, len) == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
(void)memset(dev->if_name, 0, IF_NAMESIZE);
|
||||
(void)strncpy(dev->if_name, ifname, len);
|
||||
return 0;
|
||||
(void)memset(dev->if_name, 0, IF_NAMESIZE);
|
||||
(void)strncpy(dev->if_name, ifname, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
tuntap_get_hwaddr(struct device *dev) {
|
||||
struct ether_addr eth_attr;
|
||||
tuntap_get_hwaddr(struct device *dev)
|
||||
{
|
||||
struct ether_addr eth_attr;
|
||||
|
||||
(void)memcpy(ð_attr, dev->hwaddr, sizeof dev->hwaddr);
|
||||
return ether_ntoa(ð_attr);
|
||||
(void)memcpy(ð_attr, dev->hwaddr, sizeof dev->hwaddr);
|
||||
return ether_ntoa(ð_attr);
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_hwaddr(struct device *dev, const char *hwaddr) {
|
||||
struct ether_addr *eth_addr, eth_rand;
|
||||
tuntap_set_hwaddr(struct device *dev, const char *hwaddr)
|
||||
{
|
||||
struct ether_addr *eth_addr, eth_rand;
|
||||
|
||||
if (strcmp(hwaddr, "random") == 0) {
|
||||
unsigned int i;
|
||||
unsigned char *ptr;
|
||||
if(strcmp(hwaddr, "random") == 0)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned char *ptr;
|
||||
|
||||
i = 0;
|
||||
ptr = (unsigned char *)ð_rand;
|
||||
srandom((unsigned int)time(NULL));
|
||||
for (; i < sizeof eth_rand; ++i) {
|
||||
*ptr = (unsigned char)random();
|
||||
ptr++;
|
||||
}
|
||||
ptr = (unsigned char *)ð_rand;
|
||||
*ptr &= 0xfc;
|
||||
eth_addr = ð_rand;
|
||||
} else {
|
||||
eth_addr = ether_aton(hwaddr);
|
||||
if (eth_addr == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
(void)memcpy(dev->hwaddr, eth_addr, ETHER_ADDR_LEN);
|
||||
i = 0;
|
||||
ptr = (unsigned char *)ð_rand;
|
||||
srandom((unsigned int)time(NULL));
|
||||
for(; i < sizeof eth_rand; ++i)
|
||||
{
|
||||
*ptr = (unsigned char)random();
|
||||
ptr++;
|
||||
}
|
||||
ptr = (unsigned char *)ð_rand;
|
||||
*ptr &= 0xfc;
|
||||
eth_addr = ð_rand;
|
||||
}
|
||||
else
|
||||
{
|
||||
eth_addr = ether_aton(hwaddr);
|
||||
if(eth_addr == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
(void)memcpy(dev->hwaddr, eth_addr, ETHER_ADDR_LEN);
|
||||
|
||||
if (tuntap_sys_set_hwaddr(dev, eth_addr) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
if(tuntap_sys_set_hwaddr(dev, eth_addr) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_up(struct device *dev) {
|
||||
struct ifreq ifr;
|
||||
tuntap_up(struct device *dev)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
(void)memset(&ifr, '\0', sizeof ifr);
|
||||
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
|
||||
ifr.ifr_flags = (short int)dev->flags;
|
||||
ifr.ifr_flags |= IFF_UP;
|
||||
(void)memset(&ifr, '\0', sizeof ifr);
|
||||
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
|
||||
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
|
||||
tuntap_down(struct device *dev) {
|
||||
struct ifreq ifr;
|
||||
tuntap_down(struct device *dev)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
(void)memset(&ifr, '\0', sizeof ifr);
|
||||
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
|
||||
ifr.ifr_flags = (short)dev->flags;
|
||||
ifr.ifr_flags &= ~IFF_UP;
|
||||
(void)memset(&ifr, '\0', sizeof ifr);
|
||||
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
|
||||
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
|
||||
tuntap_get_mtu(struct device *dev) {
|
||||
struct ifreq ifr;
|
||||
tuntap_get_mtu(struct device *dev)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
/* Only accept started device */
|
||||
if (dev->tun_fd == -1) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
/* Only accept started device */
|
||||
if(dev->tun_fd == -1)
|
||||
{
|
||||
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);
|
||||
(void)memcpy(ifr.ifr_name, dev->if_name, sizeof dev->if_name);
|
||||
|
||||
if (ioctl(dev->ctrl_sock, SIOCGIFMTU, &ifr) == -1) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't get MTU");
|
||||
return -1;
|
||||
}
|
||||
return ifr.ifr_mtu;
|
||||
if(ioctl(dev->ctrl_sock, SIOCGIFMTU, &ifr) == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't get MTU");
|
||||
return -1;
|
||||
}
|
||||
return ifr.ifr_mtu;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_mtu(struct device *dev, int mtu) {
|
||||
struct ifreq ifr;
|
||||
tuntap_set_mtu(struct device *dev, int mtu)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
/* Only accept started device */
|
||||
if (dev->tun_fd == -1) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
/* Only accept started device */
|
||||
if(dev->tun_fd == -1)
|
||||
{
|
||||
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);
|
||||
ifr.ifr_mtu = mtu;
|
||||
|
||||
if (ioctl(dev->ctrl_sock, SIOCSIFMTU, &ifr) == -1) {
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't set MTU");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if(ioctl(dev->ctrl_sock, SIOCSIFMTU, &ifr) == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't set MTU");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_read(struct device *dev, void *buf, size_t size) {
|
||||
int n;
|
||||
tuntap_read(struct device *dev, void *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* Only accept started device */
|
||||
if (dev->tun_fd == -1) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
/* Only accept started device */
|
||||
if(dev->tun_fd == -1)
|
||||
{
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
n = read(dev->tun_fd, buf, size);
|
||||
if(n == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't to read from device");
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_write(struct device *dev, void *buf, size_t size) {
|
||||
int n;
|
||||
tuntap_write(struct device *dev, void *buf, size_t size)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* Only accept started device */
|
||||
if (dev->tun_fd == -1) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
/* Only accept started device */
|
||||
if(dev->tun_fd == -1)
|
||||
{
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
n = write(dev->tun_fd, buf, size);
|
||||
if(n == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't write to device");
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_get_readable(struct device *dev) {
|
||||
int n;
|
||||
tuntap_get_readable(struct device *dev)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
if (ioctl(dev->tun_fd, FIONREAD, &n) == -1) {
|
||||
tuntap_log(TUNTAP_LOG_INFO, "Your system does not support"
|
||||
" FIONREAD, fallback to MTU");
|
||||
return tuntap_get_mtu(dev);
|
||||
}
|
||||
return n;
|
||||
n = 0;
|
||||
if(ioctl(dev->tun_fd, FIONREAD, &n) == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_INFO,
|
||||
"Your system does not support"
|
||||
" FIONREAD, fallback to MTU");
|
||||
return tuntap_get_mtu(dev);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_nonblocking(struct device *dev, int set) {
|
||||
if (ioctl(dev->tun_fd, FIONBIO, &set) == -1) {
|
||||
switch(set) {
|
||||
case 0:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't unset nonblocking");
|
||||
break;
|
||||
case 1:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't set nonblocking");
|
||||
break;
|
||||
default:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
tuntap_set_nonblocking(struct device *dev, int set)
|
||||
{
|
||||
if(ioctl(dev->tun_fd, FIONBIO, &set) == -1)
|
||||
{
|
||||
switch(set)
|
||||
{
|
||||
case 0:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't unset nonblocking");
|
||||
break;
|
||||
case 1:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Can't set nonblocking");
|
||||
break;
|
||||
default:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
tuntap_set_debug(struct device *dev, int set) {
|
||||
/* Only accept started device */
|
||||
if (dev->tun_fd == -1) {
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
tuntap_set_debug(struct device *dev, int set)
|
||||
{
|
||||
/* Only accept started device */
|
||||
if(dev->tun_fd == -1)
|
||||
{
|
||||
tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if !defined Darwin
|
||||
if (ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1) {
|
||||
switch(set) {
|
||||
case 0:
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug");
|
||||
break;
|
||||
case 1:
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't set debug");
|
||||
break;
|
||||
default:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
if(ioctl(dev->tun_fd, TUNSDEBUG, &set) == -1)
|
||||
{
|
||||
switch(set)
|
||||
{
|
||||
case 0:
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't unset debug");
|
||||
break;
|
||||
case 1:
|
||||
tuntap_log(TUNTAP_LOG_WARN, "Can't set debug");
|
||||
break;
|
||||
default:
|
||||
tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'set'");
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_debug()");
|
||||
return -1;
|
||||
tuntap_log(TUNTAP_LOG_NOTICE,
|
||||
"Your system does not support tuntap_set_debug()");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
extern "C"
|
||||
{
|
||||
t_tuntap_log tuntap_log = &tuntap_log_default;
|
||||
|
||||
void
|
||||
tuntap_log_set_cb(t_tuntap_log cb)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue