summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/anytun.cpp539
-rw-r--r--src/bsd/tunDevice.cpp255
-rw-r--r--src/bsd/tunDevice.h64
-rwxr-xr-xsrc/configure6
-rw-r--r--src/linux/tunDevice.cpp4
5 files changed, 612 insertions, 256 deletions
diff --git a/src/anytun.cpp b/src/anytun.cpp
index 7b03785..e3b3ce3 100644
--- a/src/anytun.cpp
+++ b/src/anytun.cpp
@@ -116,80 +116,88 @@ bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn)
void* sender(void* p)
{
- ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
-
- std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher()));
- std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
-
- PlainPacket plain_packet(MAX_PACKET_LENGTH);
- EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
-
- Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
- Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
- Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
+ try
+ {
+ ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
- //TODO replace mux
- u_int16_t mux = gOpt.getMux();
- while(1)
+ std::auto_ptr<Cipher> c(CipherFactory::create(gOpt.getCipher()));
+ std::auto_ptr<AuthAlgo> a(AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
+
+ PlainPacket plain_packet(MAX_PACKET_LENGTH);
+ EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
+
+ Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
+ Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
+ Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
+
+ //TODO replace mux
+ u_int16_t mux = gOpt.getMux();
+ while(1)
+ {
+ plain_packet.setLength(MAX_PACKET_LENGTH);
+ encrypted_packet.withAuthTag(false);
+ encrypted_packet.setLength(MAX_PACKET_LENGTH);
+
+ // read packet from device
+ u_int32_t len = param->dev.read(plain_packet.getPayload(), plain_packet.getPayloadLength());
+ plain_packet.setPayloadLength(len);
+ // set payload type
+ if(param->dev.getType() == TYPE_TUN)
+ plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
+ else if(param->dev.getType() == TYPE_TAP)
+ plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
+ else
+ plain_packet.setPayloadType(0);
+
+ if(param->cl.empty())
+ continue;
+ //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
+ mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
+ //std::cout << " -> "<<mux << std::endl;
+ ConnectionMap::iterator cit = param->cl.getConnection(mux);
+ if(cit==param->cl.getEnd())
+ continue;
+ ConnectionParam & conn = cit->second;
+
+ if(conn.remote_host_==""||!conn.remote_port_)
+ continue;
+ // generate packet-key TODO: do this only when needed
+ conn.kd_.generate(LABEL_SATP_ENCRYPTION, conn.seq_nr_, session_key);
+ conn.kd_.generate(LABEL_SATP_SALT, conn.seq_nr_, session_salt);
+
+ c->setKey(session_key);
+ c->setSalt(session_salt);
+
+ // encrypt packet
+ c->encrypt(plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
+
+ encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
+ conn.seq_nr_++;
+
+ // add authentication tag
+ if(a->getMaxLength()) {
+ encrypted_packet.addAuthTag();
+ conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
+ a->setKey(session_auth_key);
+ a->generate(encrypted_packet);
+ }
+ try
+ {
+ param->src.send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_host_, conn.remote_port_);
+ }
+ catch (std::exception e)
+ {
+ // ignoring icmp port unreachable :) and other socket errors :(
+ }
+ }
+ }
+ catch(std::exception e)
{
- plain_packet.setLength(MAX_PACKET_LENGTH);
- encrypted_packet.withAuthTag(false);
- encrypted_packet.setLength(MAX_PACKET_LENGTH);
-
- // read packet from device
- u_int32_t len = param->dev.read(plain_packet.getPayload(), plain_packet.getPayloadLength());
- plain_packet.setPayloadLength(len);
- // set payload type
- if(param->dev.getType() == TYPE_TUN)
- plain_packet.setPayloadType(PAYLOAD_TYPE_TUN);
- else if(param->dev.getType() == TYPE_TAP)
- plain_packet.setPayloadType(PAYLOAD_TYPE_TAP);
- else
- plain_packet.setPayloadType(0);
-
- if(param->cl.empty())
- continue;
- //std::cout << "got Packet for plain "<<plain_packet.getDstAddr().toString();
- mux = gRoutingTable.getRoute(plain_packet.getDstAddr());
- //std::cout << " -> "<<mux << std::endl;
- ConnectionMap::iterator cit = param->cl.getConnection(mux);
- if(cit==param->cl.getEnd())
- continue;
- ConnectionParam & conn = cit->second;
-
- if(conn.remote_host_==""||!conn.remote_port_)
- continue;
- // generate packet-key TODO: do this only when needed
- conn.kd_.generate(LABEL_SATP_ENCRYPTION, conn.seq_nr_, session_key);
- conn.kd_.generate(LABEL_SATP_SALT, conn.seq_nr_, session_salt);
-
- c->setKey(session_key);
- c->setSalt(session_salt);
-
- // encrypt packet
- c->encrypt(plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux);
-
- encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux);
- conn.seq_nr_++;
-
- // add authentication tag
- if(a->getMaxLength()) {
- encrypted_packet.addAuthTag();
- conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
- a->setKey(session_auth_key);
- a->generate(encrypted_packet);
- }
- try
- {
- param->src.send(encrypted_packet.getBuf(), encrypted_packet.getLength(), conn.remote_host_, conn.remote_port_);
- }
- catch (std::exception e)
- {
- }
+ cLog.msg(Log::PRIO_ERR) << "sender thread died due to an uncaught exception: " << e.what();
}
pthread_exit(NULL);
}
-
+
#ifndef ANYTUN_NOSYNC
void* syncConnector(void* p )
{
@@ -228,88 +236,96 @@ void* syncListener(void* p )
void* receiver(void* p)
{
- ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
-
- std::auto_ptr<Cipher> c( CipherFactory::create(gOpt.getCipher()) );
- std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
-
- EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
- PlainPacket plain_packet(MAX_PACKET_LENGTH);
-
- Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
- Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
- Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
-
- while(1)
+ try
{
- string remote_host;
- u_int16_t remote_port;
-
- plain_packet.setLength(MAX_PACKET_LENGTH);
- encrypted_packet.withAuthTag(false);
- encrypted_packet.setLength(MAX_PACKET_LENGTH);
-
- // read packet from socket
- u_int32_t len = param->src.recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_host, remote_port);
- encrypted_packet.setLength(len);
+ ThreadParam* param = reinterpret_cast<ThreadParam*>(p);
- mux_t mux = encrypted_packet.getMux();
- // autodetect peer
- if(gOpt.getRemoteAddr() == "" && param->cl.empty())
- {
- cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_host << ":" << remote_port;
- createConnection(remote_host, remote_port, param->cl, gOpt.getSeqWindowSize(),param->queue,mux);
- }
-
- ConnectionMap::iterator cit = param->cl.getConnection(mux);
- if (cit == param->cl.getEnd())
- continue;
- ConnectionParam & conn = cit->second;
-
- // check whether auth tag is ok or not
- if(a->getMaxLength()) {
- encrypted_packet.withAuthTag(true);
- conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
- a->setKey(session_auth_key);
- if(!a->checkTag(encrypted_packet)) {
- cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
- continue;
- }
- encrypted_packet.removeAuthTag();
- }
-
- //Allow dynamic IP changes
- //TODO: add command line option to turn this off
- if (remote_host != conn.remote_host_ || remote_port != conn.remote_port_)
- {
- cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed " << remote_host << ":" << remote_port;
- conn.remote_host_=remote_host;
- conn.remote_port_=remote_port;
- SyncCommand sc (param->cl,mux);
- param->queue.push(sc);
- }
-
- // Replay Protection
- if (!checkPacketSeqNr(encrypted_packet, conn))
- continue;
+ std::auto_ptr<Cipher> c( CipherFactory::create(gOpt.getCipher()) );
+ std::auto_ptr<AuthAlgo> a( AuthAlgoFactory::create(gOpt.getAuthAlgo()) );
+
+ EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH);
+ PlainPacket plain_packet(MAX_PACKET_LENGTH);
- // generate packet-key
- conn.kd_.generate(LABEL_SATP_ENCRYPTION, encrypted_packet.getSeqNr(), session_key);
- conn.kd_.generate(LABEL_SATP_SALT, encrypted_packet.getSeqNr(), session_salt);
- c->setKey(session_key);
- c->setSalt(session_salt);
-
- // decrypt packet
- c->decrypt(encrypted_packet, plain_packet);
+ Buffer session_key(u_int32_t(SESSION_KEYLEN_ENCR)); // TODO: hardcoded size
+ Buffer session_salt(u_int32_t(SESSION_KEYLEN_SALT)); // TODO: hardcoded size
+ Buffer session_auth_key(u_int32_t(SESSION_KEYLEN_AUTH)); // TODO: hardcoded size
- // check payload_type
- if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
- plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
- (param->dev.getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
- continue;
-
- // write it on the device
- param->dev.write(plain_packet.getPayload(), plain_packet.getLength());
+ while(1)
+ {
+ string remote_host;
+ u_int16_t remote_port;
+
+ plain_packet.setLength(MAX_PACKET_LENGTH);
+ encrypted_packet.withAuthTag(false);
+ encrypted_packet.setLength(MAX_PACKET_LENGTH);
+
+ // read packet from socket
+ u_int32_t len = param->src.recv(encrypted_packet.getBuf(), encrypted_packet.getLength(), remote_host, remote_port);
+ encrypted_packet.setLength(len);
+
+ mux_t mux = encrypted_packet.getMux();
+ // autodetect peer
+ if(gOpt.getRemoteAddr() == "" && param->cl.empty())
+ {
+ cLog.msg(Log::PRIO_NOTICE) << "autodetected remote host " << remote_host << ":" << remote_port;
+ createConnection(remote_host, remote_port, param->cl, gOpt.getSeqWindowSize(),param->queue,mux);
+ }
+
+ ConnectionMap::iterator cit = param->cl.getConnection(mux);
+ if (cit == param->cl.getEnd())
+ continue;
+ ConnectionParam & conn = cit->second;
+
+ // check whether auth tag is ok or not
+ if(a->getMaxLength()) {
+ encrypted_packet.withAuthTag(true);
+ conn.kd_.generate(LABEL_SATP_MSG_AUTH, encrypted_packet.getSeqNr(), session_auth_key);
+ a->setKey(session_auth_key);
+ if(!a->checkTag(encrypted_packet)) {
+ cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl;
+ continue;
+ }
+ encrypted_packet.removeAuthTag();
+ }
+
+ //Allow dynamic IP changes
+ //TODO: add command line option to turn this off
+ if (remote_host != conn.remote_host_ || remote_port != conn.remote_port_)
+ {
+ cLog.msg(Log::PRIO_NOTICE) << "connection "<< mux << " autodetected remote host ip changed "
+ << remote_host << ":" << remote_port;
+ conn.remote_host_=remote_host;
+ conn.remote_port_=remote_port;
+ SyncCommand sc (param->cl,mux);
+ param->queue.push(sc);
+ }
+
+ // Replay Protection
+ if (!checkPacketSeqNr(encrypted_packet, conn))
+ continue;
+
+ // generate packet-key
+ conn.kd_.generate(LABEL_SATP_ENCRYPTION, encrypted_packet.getSeqNr(), session_key);
+ conn.kd_.generate(LABEL_SATP_SALT, encrypted_packet.getSeqNr(), session_salt);
+ c->setKey(session_key);
+ c->setSalt(session_salt);
+
+ // decrypt packet
+ c->decrypt(encrypted_packet, plain_packet);
+
+ // check payload_type
+ if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 &&
+ plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN6) ||
+ (param->dev.getType() == TYPE_TAP && plain_packet.getPayloadType() != PAYLOAD_TYPE_TAP))
+ continue;
+
+ // write it on the device
+ param->dev.write(plain_packet.getPayload(), plain_packet.getLength());
+ }
+ }
+ catch(std::exception e)
+ {
+ cLog.msg(Log::PRIO_ERR) << "receiver thread died due to an uncaught exception: " << e.what();
}
pthread_exit(NULL);
}
@@ -427,122 +443,135 @@ int execScript(string const& script, string const& ifname)
int main(int argc, char* argv[])
{
-// std::cout << "anytun - secure anycast tunneling protocol" << std::endl;
- if(!gOpt.parse(argc, argv)) {
- gOpt.printUsage();
- exit(-1);
- }
-
- cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
+ bool daemonized=false;
+ try
+ {
- std::ofstream pidFile;
- if(gOpt.getPidFile() != "") {
- pidFile.open(gOpt.getPidFile().c_str());
- if(!pidFile.is_open()) {
- std::cout << "can't open pid file" << std::endl;
+// std::cout << "anytun - secure anycast tunneling protocol" << std::endl;
+ if(!gOpt.parse(argc, argv)) {
+ gOpt.printUsage();
+ exit(-1);
}
- }
-
- TunDevice dev(gOpt.getDevName() =="" ? NULL : gOpt.getDevName().c_str(),
- gOpt.getDevType() =="" ? NULL : gOpt.getDevType().c_str(),
- gOpt.getIfconfigParamLocal() =="" ? NULL : gOpt.getIfconfigParamLocal().c_str(),
- gOpt.getIfconfigParamRemoteNetmask() =="" ? NULL : gOpt.getIfconfigParamRemoteNetmask().c_str());
- cLog.msg(Log::PRIO_NOTICE) << "dev created (opened)";
- cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << dev.getActualName() << "'";
- cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
- if(gOpt.getPostUpScript() != "") {
- int postup_ret = execScript(gOpt.getPostUpScript(), dev.getActualName());
- cLog.msg(Log::PRIO_NOTICE) << "post up script '" << gOpt.getPostUpScript() << "' returned " << postup_ret;
- }
-
-
-// Buffer buff(u_int32_t(1600));
-// int len;
-// while(1)
-// {
-// len = dev.read(buff.getBuf(), buff.getLength());
-// std::cout << "read " << len << " bytes form interface " << dev.getActualName() << std::endl;
-// dev.write(buff.getBuf(), len);
-// }
-
-// exit(0);
-
-
-
-
- if(gOpt.getChroot())
- chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
- if(gOpt.getDaemonize())
- daemonize();
-
- if(pidFile.is_open()) {
- pid_t pid = getpid();
- pidFile << pid;
- pidFile.close();
- }
-
- SignalController sig;
- sig.init();
-
- PacketSource* src;
- if(gOpt.getLocalAddr() == "")
- src = new UDPPacketSource(gOpt.getLocalPort());
- else
- src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
-
- ConnectionList cl;
- ConnectToList connect_to = gOpt.getConnectTo();
- SyncQueue queue;
-
- if(gOpt.getRemoteAddr() != "")
- createConnection(gOpt.getRemoteAddr(),gOpt.getRemotePort(),cl,gOpt.getSeqWindowSize(), queue, gOpt.getMux());
-
- ThreadParam p(dev, *src, cl, queue,*(new OptionConnectTo()));
- // this must be called before any other libgcrypt call
- if(!initLibGCrypt())
- return -1;
-
- pthread_t senderThread;
- pthread_create(&senderThread, NULL, sender, &p);
- pthread_t receiverThread;
- pthread_create(&receiverThread, NULL, receiver, &p);
+ cLog.msg(Log::PRIO_NOTICE) << "anytun started...";
+
+ std::ofstream pidFile;
+ if(gOpt.getPidFile() != "") {
+ pidFile.open(gOpt.getPidFile().c_str());
+ if(!pidFile.is_open()) {
+ std::cout << "can't open pid file" << std::endl;
+ }
+ }
+
+ TunDevice dev(gOpt.getDevName() =="" ? NULL : gOpt.getDevName().c_str(),
+ gOpt.getDevType() =="" ? NULL : gOpt.getDevType().c_str(),
+ gOpt.getIfconfigParamLocal() =="" ? NULL : gOpt.getIfconfigParamLocal().c_str(),
+ gOpt.getIfconfigParamRemoteNetmask() =="" ? NULL : gOpt.getIfconfigParamRemoteNetmask().c_str());
+ cLog.msg(Log::PRIO_NOTICE) << "dev created (opened)";
+ cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << dev.getActualName() << "'";
+ cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << dev.getTypeString() << "'";
+ if(gOpt.getPostUpScript() != "") {
+ int postup_ret = execScript(gOpt.getPostUpScript(), dev.getActualName());
+ cLog.msg(Log::PRIO_NOTICE) << "post up script '" << gOpt.getPostUpScript() << "' returned " << postup_ret;
+ }
+
+
+// Buffer buff(u_int32_t(1600));
+// int len;
+// while(1)
+// {
+// len = dev.read(buff.getBuf(), buff.getLength());
+// std::cout << "read " << len << " bytes form interface " << dev.getActualName() << std::endl;
+// dev.write(buff.getBuf(), len);
+// }
+
+// return 0;
+
+
+
+ if(gOpt.getChroot())
+ chrootAndDrop(gOpt.getChrootDir(), gOpt.getUsername());
+ if(gOpt.getDaemonize())
+ daemonize();
+ daemonized = true;
+
+ if(pidFile.is_open()) {
+ pid_t pid = getpid();
+ pidFile << pid;
+ pidFile.close();
+ }
+
+ SignalController sig;
+ sig.init();
+
+ PacketSource* src;
+ if(gOpt.getLocalAddr() == "")
+ src = new UDPPacketSource(gOpt.getLocalPort());
+ else
+ src = new UDPPacketSource(gOpt.getLocalAddr(), gOpt.getLocalPort());
+
+ ConnectionList cl;
+ ConnectToList connect_to = gOpt.getConnectTo();
+ SyncQueue queue;
+
+ if(gOpt.getRemoteAddr() != "")
+ createConnection(gOpt.getRemoteAddr(),gOpt.getRemotePort(),cl,gOpt.getSeqWindowSize(), queue, gOpt.getMux());
+
+ ThreadParam p(dev, *src, cl, queue,*(new OptionConnectTo()));
+
+ // this must be called before any other libgcrypt call
+ if(!initLibGCrypt())
+ return -1;
+
+ pthread_t senderThread;
+ pthread_create(&senderThread, NULL, sender, &p);
+ pthread_t receiverThread;
+ pthread_create(&receiverThread, NULL, receiver, &p);
#ifndef ANYTUN_NOSYNC
- pthread_t syncListenerThread;
- if ( gOpt.getLocalSyncPort())
- pthread_create(&syncListenerThread, NULL, syncListener, &p);
-
- std::list<pthread_t> connectThreads;
- for(ConnectToList::iterator it = connect_to.begin() ;it != connect_to.end(); ++it) {
- connectThreads.push_back(pthread_t());
- ThreadParam * point = new ThreadParam(dev, *src, cl, queue,*it);
- pthread_create(& connectThreads.back(), NULL, syncConnector, point);
- }
+ pthread_t syncListenerThread;
+ if ( gOpt.getLocalSyncPort())
+ pthread_create(&syncListenerThread, NULL, syncListener, &p);
+
+ std::list<pthread_t> connectThreads;
+ for(ConnectToList::iterator it = connect_to.begin() ;it != connect_to.end(); ++it) {
+ connectThreads.push_back(pthread_t());
+ ThreadParam * point = new ThreadParam(dev, *src, cl, queue,*it);
+ pthread_create(& connectThreads.back(), NULL, syncConnector, point);
+ }
#endif
-
- int ret = sig.run();
-
- pthread_cancel(senderThread);
- pthread_cancel(receiverThread);
+
+ int ret = sig.run();
+
+ pthread_cancel(senderThread);
+ pthread_cancel(receiverThread);
#ifndef ANYTUN_NOSYNC
- if ( gOpt.getLocalSyncPort())
- pthread_cancel(syncListenerThread);
- for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
- pthread_cancel(*it);
+ if ( gOpt.getLocalSyncPort())
+ pthread_cancel(syncListenerThread);
+ for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
+ pthread_cancel(*it);
#endif
-
- pthread_join(senderThread, NULL);
- pthread_join(receiverThread, NULL);
+
+ pthread_join(senderThread, NULL);
+ pthread_join(receiverThread, NULL);
#ifndef ANYTUN_NOSYNC
- if ( gOpt.getLocalSyncPort())
- pthread_join(syncListenerThread, NULL);
-
- for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
- pthread_join(*it, NULL);
+ if ( gOpt.getLocalSyncPort())
+ pthread_join(syncListenerThread, NULL);
+
+ for( std::list<pthread_t>::iterator it = connectThreads.begin() ;it != connectThreads.end(); ++it)
+ pthread_join(*it, NULL);
#endif
- delete src;
- delete &p.connto;
+ delete src;
+ delete &p.connto;
- return ret;
+ return ret;
+ }
+ catch(std::exception e)
+ {
+ if(daemonized)
+ cLog.msg(Log::PRIO_ERR) << "uncaught exception, exiting: " << e.what();
+ else
+ std::cout << "uncaught exception, exiting: " << e.what() << std::endl;
+ }
}
-
+
+
diff --git a/src/bsd/tunDevice.cpp b/src/bsd/tunDevice.cpp
new file mode 100644
index 0000000..47558de
--- /dev/null
+++ b/src/bsd/tunDevice.cpp
@@ -0,0 +1,255 @@
+/*
+ * anytun
+ *
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007 anytun.org <satp@wirdorange.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_tun.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+
+#include <sstream>
+
+#include "tunDevice.h"
+#include "threadUtils.hpp"
+#define DEVICE_FILE_MAX 255
+
+#include <iostream>
+
+TunDevice::TunDevice(const char* dev_name, const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp) : conf_(dev_name, dev_type, ifcfg_lp, ifcfg_rnmp)
+{
+ std::string device_file = "/dev/";
+ bool dynamic = true;
+ if(dev_name) {
+ device_file.append(dev_name);
+ dynamic = false;
+ }
+ else if(conf_.type_ == TYPE_TUN) {
+ device_file.append("tun");
+ actual_name_ = "tun";
+ }
+ else if(conf_.type_ == TYPE_TAP) {
+ device_file.append("tap");
+ actual_name_ = "tap";
+ }
+ else
+ throw std::runtime_error("unable to recognize type of device (tun or tap)");
+
+ u_int32_t dev_id=0;
+ if(dynamic) {
+ for(; dev_id <= DEVICE_FILE_MAX; ++dev_id) {
+ std::ostringstream ds;
+ ds << device_file;
+ ds << dev_id;
+ fd_ = ::open(ds.str().c_str(), O_RDWR);
+ if(fd_ >= 0)
+ break;
+ }
+ }
+ else
+ fd_ = ::open(device_file.c_str(), O_RDWR);
+
+ if(fd_ < 0) {
+ std::string msg;
+ if(dynamic)
+ msg = "can't open device file dynamically: no unused node left";
+ else {
+ msg = "can't open device file (";
+ msg.append(device_file);
+ msg.append("): ");
+ msg.append(strerror(errno));
+ }
+ throw std::runtime_error(msg);
+ }
+
+ if(dynamic) {
+ std::stringstream s;
+ s << actual_name_;
+ s << dev_id;
+ actual_name_ = s.str();
+ }
+ else
+ actual_name_ = dev_name;
+
+ init_post();
+
+ if(ifcfg_lp && ifcfg_rnmp)
+ do_ifconfig();
+}
+
+TunDevice::~TunDevice()
+{
+ if(fd_ > 0)
+ ::close(fd_);
+}
+
+#if defined(__GNUC__) && defined(__OpenBSD__)
+
+void TunDevice::init_post()
+{
+ with_type_ = true;
+ if(conf_.type_ == TYPE_TAP)
+ with_type_ = false;
+
+ struct tuninfo ti;
+
+ if (ioctl(fd_, TUNGIFINFO, &ti) < 0)
+ throw std::runtime_error("can't enable multicast for interface");
+
+ ti.flags |= IFF_MULTICAST;
+
+ if (ioctl(fd_, TUNSIFINFO, &ti) < 0)
+ throw std::runtime_error("can't enable multicast for interface");
+}
+
+#elif defined(__GNUC__) && defined(__FreeBSD__)
+
+void TunDevice::init_post()
+{
+ with_type_ = true;
+ if(conf_.type_ == TYPE_TAP)
+ with_type_ = false;
+
+ int arg = 0;
+ ioctl(fd_, TUNSLMODE, &arg);
+ arg = 1;
+ ioctl(fd_, TUNSIFHEAD, &arg);
+}
+
+#elif defined(__GNUC__) && defined(__NetBSD__)
+
+void TunDevice::init_post()
+{
+ with_type_ = false;
+
+ int arg = IFF_POINTOPOINT|IFF_MULTICAST;
+ ioctl(fd_, TUNSIFMODE, &arg);
+ arg = 0;
+ ioctl(fd_, TUNSLMODE, &arg);
+}
+
+#else
+ #error Target not supported
+#endif
+
+
+short TunDevice::read(u_int8_t* buf, u_int32_t len)
+{
+ if(fd_ < 0)
+ return -1;
+
+ if(with_type_) {
+ struct iovec iov[2];
+ u_int32_t type;
+
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+ return(::readv(fd_, iov, 2) - sizeof(type));
+ }
+ else
+ return(::read(fd_, buf, len));
+}
+
+int TunDevice::write(u_int8_t* buf, u_int32_t len)
+{
+ if(fd_ < 0)
+ return -1;
+
+ if(with_type_) {
+ struct iovec iov[2];
+ u_int32_t type;
+ struct ip *hdr = reinterpret_cast<struct ip*>(buf);
+
+ type = 0;
+ if(hdr->ip_v == 4)
+ type = htonl(AF_INET);
+ else
+ type = htonl(AF_INET6);
+
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+ return(::writev(fd_, iov, 2) - sizeof(type));
+ }
+ else
+ return(::write(fd_, buf, len));
+}
+
+const char* TunDevice::getActualName()
+{
+ return actual_name_.c_str();
+}
+
+device_type_t TunDevice::getType()
+{
+ return conf_.type_;
+}
+
+const char* TunDevice::getTypeString()
+{
+ if(fd_ < 0)
+ return NULL;
+
+ switch(conf_.type_)
+ {
+ case TYPE_UNDEF: return "undef"; break;
+ case TYPE_TUN: return "tun"; break;
+ case TYPE_TAP: return "tap"; break;
+ }
+ return NULL;
+}
+
+void TunDevice::do_ifconfig()
+{
+// std::string command("/sbin/ifconfig ");
+// command.append(actual_name_);
+// command.append(" ");
+// command.append(conf_.local_.toString());
+// command.append(" ");
+
+// if(conf_.type_ == TYPE_TUN)
+// command.append("pointopoint ");
+// else
+// command.append("netmask ");
+
+// command.append(conf_.remote_netmask_.toString());
+// command.append(" mtu 1400");
+
+// system(command.c_str());
+}
diff --git a/src/bsd/tunDevice.h b/src/bsd/tunDevice.h
new file mode 100644
index 0000000..16408a2
--- /dev/null
+++ b/src/bsd/tunDevice.h
@@ -0,0 +1,64 @@
+/*
+ * anytun
+ *
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007 anytun.org <satp@wirdorange.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TUNDEVICE_H_
+#define _TUNDEVICE_H_
+
+#include "buffer.h"
+#include "deviceConfig.hpp"
+#include "threadUtils.hpp"
+
+class TunDevice
+{
+public:
+ TunDevice(const char* dev,const char* dev_type, const char* ifcfg_lp, const char* ifcfg_rnmp);
+ ~TunDevice();
+
+ short read(u_int8_t* buf, u_int32_t len);
+ int write(u_int8_t* buf, u_int32_t len);
+
+ const char* getActualName();
+ device_type_t getType();
+ const char* getTypeString();
+
+private:
+ void operator=(const TunDevice &src);
+ TunDevice(const TunDevice &src);
+
+ void init_post();
+ void do_ifconfig();
+
+ int fd_;
+ DeviceConfig conf_;
+ bool with_type_;
+ std::string actual_name_;
+};
+
+#endif
diff --git a/src/configure b/src/configure
index 9f6ff4b..054069e 100755
--- a/src/configure
+++ b/src/configure
@@ -12,6 +12,12 @@ case $TARGET in
ln -sf linux/tunDevice.cpp
ln -sf linux/tunDevice.h
;;
+ bsd)
+ rm -rf tunDevice.cpp
+ rm -rf tunDevice.h
+ ln -sf bsd/tunDevice.cpp
+ ln -sf bsd/tunDevice.h
+ ;;
ovpn)
rm -rf tunDevice.cpp
rm -rf tunDevice.cpp
diff --git a/src/linux/tunDevice.cpp b/src/linux/tunDevice.cpp
index 8548331..4185bef 100644
--- a/src/linux/tunDevice.cpp
+++ b/src/linux/tunDevice.cpp
@@ -46,7 +46,9 @@ TunDevice::TunDevice(const char* dev_name, const char* dev_type, const char* ifc
{
fd_ = ::open(DEFAULT_DEVICE, O_RDWR);
if(fd_ < 0) {
- std::string msg("can't open device file: ");
+ std::string msg("can't open device file (");
+ msg.append(DEFAULT_DEVICE);
+ msg.append("): ");
msg.append(strerror(errno));
throw std::runtime_error(msg);
}