diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ab825b5b..4d3fd1aad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,7 +185,7 @@ endif(UNIX) if(TUNTAP) set(LIBTUNTAP_SRC_BASE - ${TT_ROOT}/tuntap.c + ${TT_ROOT}/tuntap.cpp ${TT_ROOT}/tuntap_log.cpp ${LIBTUNTAP_IMPL}) if (UNIX) diff --git a/include/llarp/buffer.hpp b/include/llarp/buffer.hpp index fc1da19e4..cb6b37096 100644 --- a/include/llarp/buffer.hpp +++ b/include/llarp/buffer.hpp @@ -16,6 +16,19 @@ namespace llarp return buff; } + /** initialize llarp_buffer_t from raw memory */ + template < typename T > + llarp_buffer_t + InitBuffer(T buf, size_t sz) + { + byte_t* ptr = (byte_t*)buf; + llarp_buffer_t ret; + ret.cur = ptr; + ret.base = ptr; + ret.sz = sz; + return ret; + } + /** initialize llarp_buffer_t from container */ template < typename T > llarp_buffer_t diff --git a/include/llarp/codel.hpp b/include/llarp/codel.hpp index a4e64aea2..b1d243f82 100644 --- a/include/llarp/codel.hpp +++ b/include/llarp/codel.hpp @@ -8,6 +8,7 @@ #endif #include #include +#include #include #include @@ -69,14 +70,47 @@ namespace llarp return m_Queue.size(); } + template < typename... Args > + bool + EmplaceIf(std::function< bool(T*) > pred, Args&&... args) + { + std::unique_ptr< T > ptr = std::make_unique< T >(args...); + if(!pred(ptr.get())) + return false; + PutTime()(ptr.get()); + { + Lock_t lock(m_QueueMutex); + if(firstPut == 0) + firstPut = GetTime()(ptr.get()); + m_Queue.push(std::move(ptr)); + } + return true; + } + + template < typename... Args > + void + Emplace(Args&&... args) + { + std::unique_ptr< T > ptr = std::make_unique< T >(args...); + PutTime()(ptr.get()); + { + Lock_t lock(m_QueueMutex); + if(firstPut == 0) + firstPut = GetTime()(ptr.get()); + m_Queue.push(std::move(ptr)); + } + } + void Put(std::unique_ptr< T >& ptr) { - Lock_t lock(m_QueueMutex); PutTime()(ptr.get()); - if(firstPut == 0) - firstPut = GetTime()(ptr.get()); - m_Queue.push(std::move(ptr)); + { + Lock_t lock(m_QueueMutex); + if(firstPut == 0) + firstPut = GetTime()(ptr.get()); + m_Queue.push(std::move(ptr)); + } } template < typename Func > @@ -90,9 +124,9 @@ namespace llarp auto start = firstPut; while(m_Queue.size()) { - // llarp::LogInfo("CoDelQueue::Process - queue has ", m_Queue.size()); - auto& item = m_Queue.top(); - auto dlt = start - GetTime()(item.get()); + llarp::LogDebug("CoDelQueue::Process - queue has ", m_Queue.size()); + const auto& item = m_Queue.top(); + auto dlt = start - GetTime()(item.get()); // llarp::LogInfo("CoDelQueue::Process - dlt ", dlt); lowest = std::min(dlt, lowest); if(m_Queue.size() == 1) diff --git a/include/llarp/handlers/tun.hpp b/include/llarp/handlers/tun.hpp index 2f2cc8c00..53a6e61ce 100644 --- a/include/llarp/handlers/tun.hpp +++ b/include/llarp/handlers/tun.hpp @@ -74,14 +74,18 @@ namespace llarp PacketQueue_t m_NetworkToUserPktQueue; /// return true if we have a remote loki address for this ip address bool - HasRemoteForIP(const uint32_t& ipv4) - { - return m_IPs.find(ipv4) != m_IPs.end(); - } + HasRemoteForIP(const uint32_t& ipv4) const; + + uint32_t + ObtainIPForAddr(const service::Address& addr); private: std::promise< bool > m_TunSetupResult; - std::unordered_map< uint32_t, service::Address > m_IPs; + std::unordered_map< uint32_t, service::Address > m_IPToAddr; + std::unordered_map< service::Address, uint32_t, service::Address::Hash > + m_AddrToIP; + uint32_t m_OurIP; + uint32_t m_NextIP; }; } // namespace handlers } // namespace llarp diff --git a/include/llarp/ip.hpp b/include/llarp/ip.hpp index e7183f2ae..8f03f1583 100644 --- a/include/llarp/ip.hpp +++ b/include/llarp/ip.hpp @@ -51,9 +51,12 @@ namespace llarp struct IPv4Packet { static constexpr size_t MaxSize = 1500; - llarp_time_t timestamp; - size_t sz; - byte_t buf[MaxSize]; + llarp_time_t timestamp = 0; + size_t sz = 0; + byte_t buf[MaxSize] = {0}; + + bool + Load(llarp_buffer_t buf); struct GetTime { @@ -95,44 +98,35 @@ namespace llarp return (iphdr*)buf; } - uint32_t& + uint32_t src() { - return Header()->saddr; + return ntohs(Header()->saddr); } - uint32_t& + uint32_t dst() { - return Header()->daddr; + return ntohs(Header()->daddr); } - const uint32_t& - src() const + void + src(uint32_t ip) { - return Header()->saddr; + Header()->saddr = htons(ip); } - const uint32_t& - dst() const + void + dst(uint32_t ip) { - return Header()->daddr; + Header()->daddr = htons(ip); } - /// put the payload of an ip packet - /// recalculate all fields - /// return true on success - /// return false if the payload doesn't fit - bool - PutPayload(llarp_buffer_t buf); + // update ip packet checksum + void + UpdateChecksum(); }; - /// parse an ipv4 packet - /// returns nullptr if invalid data - /// copies buffer into return value - std::unique_ptr< IPv4Packet > - ParseIPv4Packet(const void* buf, size_t sz); - } // namespace net } // namespace llarp diff --git a/include/llarp/mem.hpp b/include/llarp/mem.hpp index 67cfa310d..4e85e4e0d 100644 --- a/include/llarp/mem.hpp +++ b/include/llarp/mem.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace llarp { @@ -57,4 +58,15 @@ namespace llarp } // namespace llarp +#if __cplusplus < 201402L +namespace std +{ + template < typename T, typename... Args > + std::unique_ptr< T > + make_unique(Args &&... args) + { + return std::unique_ptr< T >(new T(std::forward< Args >(args)...)); + } +} // namespace std +#endif #endif diff --git a/include/llarp/service/endpoint.hpp b/include/llarp/service/endpoint.hpp index 134a96ec5..d4dbca434 100644 --- a/include/llarp/service/endpoint.hpp +++ b/include/llarp/service/endpoint.hpp @@ -252,7 +252,7 @@ namespace llarp OnOutboundLookup(const IntroSet* i); /* */ static bool - SetupIsolatedNetwork(void* user, bool failed); + SetupIsolatedNetwork(void* user, bool success); bool DoNetworkIsolation(bool failed); diff --git a/include/tuntap.h b/include/tuntap.h index 8199f4d76..979b93642 100644 --- a/include/tuntap.h +++ b/include/tuntap.h @@ -37,8 +37,8 @@ #else #include #endif -#include #include +#include #endif #include @@ -154,8 +154,14 @@ extern "C" }; /* User definable log callback */ - typedef void (*t_tuntap_log)(int, const char *); - TUNTAP_EXPORT t_tuntap_log tuntap_log; + typedef void (*t_tuntap_log)(int, int, const char *, const char *); + TUNTAP_EXPORT t_tuntap_log __tuntap_log; + +#ifndef LOG_TAG +#define LOG_TAG "tuntap" +#endif + +#define tuntap_log(lvl, msg) __tuntap_log(lvl, __LINE__, LOG_TAG, msg) /* Portable "public" functions */ TUNTAP_EXPORT struct device * @@ -214,7 +220,7 @@ extern "C" TUNTAP_EXPORT void tuntap_log_set_cb(t_tuntap_log cb); void - tuntap_log_default(int, const char *); + tuntap_log_default(int, int, const char *, const char *); void tuntap_log_hexdump(void *, size_t); void diff --git a/llarp/ev.cpp b/llarp/ev.cpp index 67d4ec255..1ab547cb3 100644 --- a/llarp/ev.cpp +++ b/llarp/ev.cpp @@ -104,7 +104,10 @@ llarp_ev_udp_sendto(struct llarp_udp_io *udp, const sockaddr *to, bool llarp_ev_add_tun(struct llarp_ev_loop *loop, struct llarp_tun_io *tun) { - return loop->create_tun(tun); + auto dev = loop->create_tun(tun); + if(dev) + return loop->add_ev(dev, false); + return false; } bool diff --git a/llarp/ev.hpp b/llarp/ev.hpp index 46cdea5e6..4a552ac79 100644 --- a/llarp/ev.hpp +++ b/llarp/ev.hpp @@ -39,9 +39,7 @@ namespace llarp bool queue_write(const void* data, size_t sz) { - std::unique_ptr< WriteBuffer > buf = - std::unique_ptr< WriteBuffer >(new WriteBuffer(data, sz)); - m_writeq.Put(buf); + m_writeq.Emplace(data, sz); return m_writeq.Size() <= MAX_WRITE_QUEUE_SIZE; } @@ -143,7 +141,7 @@ struct llarp_ev_loop udp_listen(llarp_udp_io* l, const sockaddr* src) { auto ev = create_udp(l, src); - return ev && add_ev(ev); + return ev && add_ev(ev, false); } virtual llarp::ev_io* @@ -158,7 +156,7 @@ struct llarp_ev_loop create_tun(llarp_tun_io* tun) = 0; virtual bool - add_ev(llarp::ev_io* ev, bool write = true) = 0; + add_ev(llarp::ev_io* ev, bool write = false) = 0; virtual bool running() const = 0; diff --git a/llarp/ev_epoll.hpp b/llarp/ev_epoll.hpp index 29d0b282d..a9cdbbf3a 100644 --- a/llarp/ev_epoll.hpp +++ b/llarp/ev_epoll.hpp @@ -85,8 +85,8 @@ namespace llarp if(t->before_write) { t->before_write(t); + ev_io::flush_write(); } - ev_io::flush_write(); } int @@ -101,12 +101,16 @@ namespace llarp bool setup() { - if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, TUNTAP_ID_ANY) == -1) + llarp::LogDebug("set up tunif"); + if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1) return false; + llarp::LogDebug("set ifname to ", t->ifname); if(tuntap_set_ifname(tunif, t->ifname) == -1) return false; if(tuntap_set_ip(tunif, t->ifaddr, t->netmask) == -1) return false; + if(tuntap_up(tunif) == -1) + return false; fd = tunif->tun_fd; return fd != -1; } @@ -185,10 +189,8 @@ struct llarp_epoll_loop : public llarp_ev_loop if(events[idx].events & EPOLLIN) { ev->read(readbuf, sizeof(readbuf)); - } - if(events[idx].events & EPOLLOUT) - { - ev->flush_write(); + if(events[idx].events & EPOLLOUT) + ev->flush_write(); } ++idx; } @@ -221,10 +223,8 @@ struct llarp_epoll_loop : public llarp_ev_loop if(events[idx].events & EPOLLIN) { ev->read(readbuf, sizeof(readbuf)); - } - if(events[idx].events & EPOLLOUT) - { - ev->flush_write(); + if(events[idx].events & EPOLLOUT) + ev->flush_write(); } ++idx; } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 5f4380e86..0ffffa6e6 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -77,7 +77,17 @@ namespace llarp bool TunEndpoint::SetupTun() { - return llarp_ev_add_tun(EndpointNetLoop(), &tunif); + if(!llarp_ev_add_tun(EndpointNetLoop(), &tunif)) + { + llarp::LogError(Name(), " failed to set up tun interface"); + return false; + } + m_OurIP = inet_addr(tunif.ifaddr); + m_NextIP = m_OurIP; + char buf[128] = {0}; + llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", + inet_ntop(AF_INET, &m_OurIP, buf, sizeof(buf))); + return true; } bool @@ -100,7 +110,48 @@ namespace llarp void TunEndpoint::HandleDataMessage(service::ProtocolMessage *msg) { - // TODO: implement me + if(msg->proto != service::eProtocolTraffic) + { + llarp::LogWarn("dropping unwarrented message, not ip traffic, proto=", + msg->proto); + return; + } + uint32_t themIP = ObtainIPForAddr(msg->sender.Addr()); + uint32_t usIP = m_OurIP; + auto buf = llarp::Buffer(msg->payload); + if(!m_NetworkToUserPktQueue.EmplaceIf( + [buf, themIP, usIP](net::IPv4Packet *pkt) -> bool { + // do packet info rewrite here + // TODO: don't truncate packet here + memcpy(pkt->buf, buf.base, std::min(buf.sz, sizeof(pkt->buf))); + pkt->src(themIP); + pkt->dst(usIP); + pkt->UpdateChecksum(); + return true; + })) + { + llarp::LogWarn("failed to parse buffer for ip traffic"); + llarp::DumpBuffer(buf); + } + } + + uint32_t + TunEndpoint::ObtainIPForAddr(const service::Address &addr) + { + auto itr = m_AddrToIP.find(addr); + if(itr != m_AddrToIP.end()) + return itr->second; + + uint32_t nextIP = ++m_NextIP; + m_AddrToIP.insert(std::make_pair(addr, nextIP)); + m_IPToAddr.insert(std::make_pair(nextIP, addr)); + return nextIP; + } + + bool + TunEndpoint::HasRemoteForIP(const uint32_t &ip) const + { + return m_IPToAddr.find(ip) != m_IPToAddr.end(); } void @@ -121,6 +172,7 @@ namespace llarp TunEndpoint::tunifBeforeWrite(llarp_tun_io *tun) { TunEndpoint *self = static_cast< TunEndpoint * >(tun->user); + llarp::LogDebug("tunifBeforeWrite"); self->m_NetworkToUserPktQueue.Process( [tun](const std::unique_ptr< net::IPv4Packet > &pkt) { if(!llarp_ev_tun_async_write(tun, pkt->buf, pkt->sz)) @@ -133,10 +185,12 @@ namespace llarp { // called for every packet read from user in isolated network thread TunEndpoint *self = static_cast< TunEndpoint * >(tun->user); - - std::unique_ptr< net::IPv4Packet > pkt = net::ParseIPv4Packet(buf, sz); - if(pkt) - self->m_UserToNetworkPktQueue.Put(pkt); + llarp::LogDebug("got pkt ", sz, " bytes"); + if(!self->m_UserToNetworkPktQueue.EmplaceIf( + [buf, sz](net::IPv4Packet *pkt) -> bool { + return pkt->Load(llarp::InitBuffer(buf, sz)); + })) + llarp::LogError("Failed to parse ipv4 packet"); } TunEndpoint::~TunEndpoint() diff --git a/llarp/ip.cpp b/llarp/ip.cpp index 3899a2cb9..261730cf2 100644 --- a/llarp/ip.cpp +++ b/llarp/ip.cpp @@ -5,14 +5,37 @@ namespace llarp { namespace net { - std::unique_ptr< IPv4Packet > - ParseIPv4Packet(const void* buf, size_t sz) + bool + IPv4Packet::Load(llarp_buffer_t pkt) { - if(sz < 16 || sz > IPv4Packet::MaxSize) - return nullptr; - IPv4Packet* pkt = new IPv4Packet(); - memcpy(pkt->buf, buf, sz); - return std::unique_ptr< IPv4Packet >(pkt); + memcpy(buf, pkt.base, std::min(pkt.sz, sizeof(buf))); + return true; } + + void + IPv4Packet::UpdateChecksum() + { + auto hdr = Header(); + hdr->check = 0; + + size_t count = hdr->ihl; + uint32_t sum = 0; + byte_t *addr = buf; + + while(count > 1) + { + sum += ntohs(*(uint16_t *)addr); + count -= sizeof(uint16_t); + addr += sizeof(uint16_t); + } + if(count > 0) + sum += *(byte_t *)addr; + + while(sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + hdr->check = htons(~sum); + } + } // namespace net } // namespace llarp diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 2b885a42a..1dff0771e 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -95,7 +95,7 @@ namespace llarp bool Endpoint::SetupIsolatedNetwork(void* user, bool failed) { - return static_cast< Endpoint* >(user)->DoNetworkIsolation(failed); + return static_cast< Endpoint* >(user)->DoNetworkIsolation(!failed); } bool diff --git a/vendor/libtuntap-master/tuntap.c b/vendor/libtuntap-master/tuntap.c deleted file mode 100644 index f537e0e5e..000000000 --- a/vendor/libtuntap-master/tuntap.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2012 Tristan Le Guern - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * Copyright (c) 2016 Mahdi Mokhtari - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#if defined Windows -#include -#include -#include -#else -#include -#include -#endif - -#include -#include -#include -#include -#include - -#include - -#include "tuntap.h" - -struct device * -tuntap_init(void) -{ - struct device *dev = NULL; - - if((dev = (struct device *)malloc(sizeof(*dev))) == NULL) - return NULL; - - (void)memset(dev->if_name, '\0', sizeof(dev->if_name)); - (void)memset(dev->hwaddr, '\0', sizeof(dev->hwaddr)); - dev->tun_fd = TUNFD_INVALID_VALUE; - dev->ctrl_sock = -1; - dev->flags = 0; - - tuntap_log = tuntap_log_default; - return dev; -} - -void -tuntap_destroy(struct device *dev) -{ - tuntap_sys_destroy(dev); - tuntap_release(dev); -} - -char * -tuntap_get_ifname(struct device *dev) -{ - return dev->if_name; -} - -int -tuntap_version(void) -{ - return TUNTAP_VERSION; -} - -#if !defined(FreeBSD) -int -tuntap_set_ip_old(struct device *dev, const char *addr, int netmask) -{ - t_tun_in_addr baddr4; - t_tun_in6_addr baddr6; - uint32_t mask; - int errval; - - /* Only accept started device */ - if(dev->tun_fd == TUNFD_INVALID_VALUE) - { - tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); - return 0; - } - - if(addr == NULL) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'addr'"); - return -1; - } - - if(netmask < 0 || netmask > 128) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'netmask'"); - return -1; - } - - /* Netmask */ - mask = ~0; - mask = ~(mask >> netmask); - mask = htonl(mask); - - /* - * Destination address parsing: we try IPv4 first and fall back to - * IPv6 if inet_pton return 0 - */ - (void)memset(&baddr4, '\0', sizeof(baddr4)); - (void)memset(&baddr6, '\0', sizeof(baddr6)); - - errval = inet_pton(AF_INET, addr, &(baddr4)); - if(errval == 1) - { - return tuntap_sys_set_ipv4(dev, &baddr4, mask); - } - else if(errval == 0) - { - if(inet_pton(AF_INET6, addr, &(baddr6)) == -1) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters"); - return -1; - } - return tuntap_sys_set_ipv6(dev, &baddr6, mask); - } - else if(errval == -1) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters"); - return -1; - } - - /* NOTREACHED */ - return -1; -} -#endif - -int -tuntap_set_ip(struct device *dev, ...) -{ - va_list vl; - char *saddr; - char *daddr; - int netmask; - t_tun_in_addr sbaddr4; - t_tun_in6_addr sbaddr6; -#if defined(FreeBSD) - t_tun_in_addr dbaddr4; - t_tun_in6_addr dbaddr6; -#endif - uint32_t mask; - int errval; - - saddr = daddr = NULL; - netmask = -1; - - va_start(vl, dev); - saddr = va_arg(vl, char *); - netmask = va_arg(vl, int); -#if defined(FreeBSD) - if(dev->mode == TUNTAP_MODE_TUNNEL) - daddr = va_arg(vl, char *); -#endif - va_end(vl); - - /* Only accept started device */ - if(dev->tun_fd == TUNFD_INVALID_VALUE) - { - tuntap_log(TUNTAP_LOG_NOTICE, "Device is not started"); - return 0; - } - - if(saddr == NULL) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'saddr'"); - return -1; - } - - if(netmask < 0 || netmask > 128) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'netmask'"); - return -1; - } - - /* Netmask */ - mask = ~0; - mask = ~(mask >> netmask); - mask = htonl(mask); - - /* - * Destination address parsing: we try IPv4 first and fall back to - * IPv6 if inet_pton return 0 - */ - (void)memset(&sbaddr4, 0, sizeof(sbaddr4)); - (void)memset(&sbaddr6, 0, sizeof(sbaddr6)); - - errval = inet_pton(AF_INET, saddr, &(sbaddr4)); - if(errval == 1) - { -#if defined(FreeBSD) -#define tuntap_sys_set_ipv4 tuntap_sys_set_ipv4_tap - if(dev->mode == TUNTAP_MODE_TUNNEL) - { - if(daddr == NULL) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameter 'daddr'"); - return -1; - } - (void)memset(&dbaddr4, 0, sizeof(dbaddr4)); - (void)inet_pton(AF_INET, daddr, &(dbaddr4)); - return tuntap_sys_set_ipv4_tun(dev, &sbaddr4, &dbaddr4, mask); - } - else -#endif - { - return tuntap_sys_set_ipv4(dev, &sbaddr4, mask); - } - } - else if(errval == 0) - { -#if !defined(FreeBSD) /* No IPV6 tests YET */ - if(inet_pton(AF_INET6, saddr, &(sbaddr6)) == -1) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters"); - return -1; - } - return tuntap_sys_set_ipv6(dev, &sbaddr6, mask); - } - else if(errval == -1) - { - tuntap_log(TUNTAP_LOG_ERR, "Invalid parameters"); - return -1; -#endif - } - - /* NOTREACHED */ - return -1; -} diff --git a/vendor/libtuntap-master/tuntap.cpp b/vendor/libtuntap-master/tuntap.cpp new file mode 100644 index 000000000..567c84847 --- /dev/null +++ b/vendor/libtuntap-master/tuntap.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2012 Tristan Le Guern + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * Copyright (c) 2016 Mahdi Mokhtari + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#if defined Windows +#include +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include + +#include + +#include "tuntap.h" + +extern "C" +{ + struct device * + tuntap_init(void) + { + struct device *dev = NULL; + + if((dev = (struct device *)malloc(sizeof(*dev))) == NULL) + return NULL; + + (void)memset(dev->if_name, '\0', sizeof(dev->if_name)); + (void)memset(dev->hwaddr, '\0', sizeof(dev->hwaddr)); + dev->tun_fd = TUNFD_INVALID_VALUE; + dev->ctrl_sock = -1; + dev->flags = 0; + + __tuntap_log = &tuntap_log_default; + return dev; + } + + void + tuntap_destroy(struct device *dev) + { + tuntap_sys_destroy(dev); + tuntap_release(dev); + } + + char * + tuntap_get_ifname(struct device *dev) + { + return dev->if_name; + } + + int + tuntap_version(void) + { + return TUNTAP_VERSION; + } + +#if !defined(FreeBSD) + int + tuntap_set_ip_old(struct device *dev, const char *addr, int netmask) + { + t_tun_in_addr baddr4; + t_tun_in6_addr baddr6; + uint32_t mask; + int errval; + + /* Only accept started device */ + if(dev->tun_fd == TUNFD_INVALID_VALUE) + { + llarp::LogInfo("device not started"); + return 0; + } + + if(addr == NULL) + { + llarp::LogError("Invalid address"); + return -1; + } + + if(netmask < 0 || netmask > 128) + { + llarp::LogError("Invalid netmask"); + return -1; + } + + /* Netmask */ + mask = ~0; + mask = ~(mask >> netmask); + mask = htonl(mask); + + /* + * Destination address parsing: we try IPv4 first and fall back to + * IPv6 if inet_pton return 0 + */ + (void)memset(&baddr4, '\0', sizeof(baddr4)); + (void)memset(&baddr6, '\0', sizeof(baddr6)); + + errval = inet_pton(AF_INET, addr, &(baddr4)); + if(errval == 1) + { + return tuntap_sys_set_ipv4(dev, &baddr4, mask); + } + else if(errval == 0) + { + if(inet_pton(AF_INET6, addr, &(baddr6)) == -1) + { + llarp::LogError("invalid ipv6 address: ", addr); + return -1; + } + return tuntap_sys_set_ipv6(dev, &baddr6, mask); + } + else if(errval == -1) + { + llarp::LogError("invalid address: ", addr); + return -1; + } + + /* NOTREACHED */ + return -1; + } +#endif + + int + tuntap_set_ip(struct device *dev, ...) + { + va_list vl; + char *saddr; + char *daddr; + int netmask; + t_tun_in_addr sbaddr4; + t_tun_in6_addr sbaddr6; +#if defined(FreeBSD) + t_tun_in_addr dbaddr4; + t_tun_in6_addr dbaddr6; +#endif + uint32_t mask; + int errval; + + saddr = daddr = NULL; + netmask = -1; + + va_start(vl, dev); + saddr = va_arg(vl, char *); + netmask = va_arg(vl, int); +#if defined(FreeBSD) + if(dev->mode == TUNTAP_MODE_TUNNEL) + daddr = va_arg(vl, char *); +#endif + va_end(vl); + + /* Only accept started device */ + if(dev->tun_fd == TUNFD_INVALID_VALUE) + { + llarp::LogWarn("device not started"); + return 0; + } + + if(saddr == NULL) + { + llarp::LogWarn("invalid source addr"); + return -1; + } + + if(netmask < 0 || netmask > 128) + { + llarp::LogWarn("invalid netmask"); + return -1; + } + + /* Netmask */ + mask = ~0; + mask = ~(mask >> netmask); + mask = htonl(mask); + + /* + * Destination address parsing: we try IPv4 first and fall back to + * IPv6 if inet_pton return 0 + */ + (void)memset(&sbaddr4, 0, sizeof(sbaddr4)); + (void)memset(&sbaddr6, 0, sizeof(sbaddr6)); + + errval = inet_pton(AF_INET, saddr, &(sbaddr4)); + if(errval == 1) + { +#if defined(FreeBSD) +#define tuntap_sys_set_ipv4 tuntap_sys_set_ipv4_tap + if(dev->mode == TUNTAP_MODE_TUNNEL) + { + if(daddr == NULL) + { + llarp::LogWarn("invalid destination address"); + return -1; + } + (void)memset(&dbaddr4, 0, sizeof(dbaddr4)); + (void)inet_pton(AF_INET, daddr, &(dbaddr4)); + return tuntap_sys_set_ipv4_tun(dev, &sbaddr4, &dbaddr4, mask); + } + else +#endif + { + return tuntap_sys_set_ipv4(dev, &sbaddr4, mask); + } + } + else if(errval == 0) + { +#if !defined(FreeBSD) /* No IPV6 tests YET */ + if(inet_pton(AF_INET6, saddr, &(sbaddr6)) == -1) + { + llarp::LogWarn("invalid ip6 source address: ", saddr); + return -1; + } + return tuntap_sys_set_ipv6(dev, &sbaddr6, mask); + } + else if(errval == -1) + { + llarp::LogWarn("invalid ip6 source address: ", saddr); + return -1; +#endif + } + + /* NOTREACHED */ + return -1; + } +} \ No newline at end of file diff --git a/vendor/libtuntap-master/tuntap_log.cpp b/vendor/libtuntap-master/tuntap_log.cpp index da13b3176..ee41e6507 100644 --- a/vendor/libtuntap-master/tuntap_log.cpp +++ b/vendor/libtuntap-master/tuntap_log.cpp @@ -28,37 +28,37 @@ extern "C" { - t_tuntap_log tuntap_log = &tuntap_log_default; + t_tuntap_log __tuntap_log = &tuntap_log_default; void tuntap_log_set_cb(t_tuntap_log cb) { if(cb == NULL) { - tuntap_log = tuntap_log_default; + __tuntap_log = tuntap_log_default; } - tuntap_log = cb; + __tuntap_log = cb; } void - tuntap_log_default(int level, const char *errmsg) + tuntap_log_default(int level, int line, const char *tag, const char *errmsg) { switch(level) { case TUNTAP_LOG_DEBUG: - llarp::LogDebug(errmsg); + llarp::_Log(llarp::eLogDebug, tag, line, errmsg); break; case TUNTAP_LOG_INFO: - llarp::LogInfo(errmsg); + llarp::_Log(llarp::eLogInfo, tag, line, errmsg); break; case TUNTAP_LOG_NOTICE: - llarp::LogInfo(errmsg); + llarp::_Log(llarp::eLogInfo, tag, line, errmsg); break; case TUNTAP_LOG_WARN: - llarp::LogWarn(errmsg); + llarp::_Log(llarp::eLogWarn, tag, line, errmsg); break; case TUNTAP_LOG_ERR: - llarp::LogError(errmsg); + llarp::_Log(llarp::eLogError, tag, line, errmsg); break; case TUNTAP_LOG_NONE: default: