4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methods used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007-2014 Markus Grüneis, Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
19 * Anytun is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, either version 3 of the License, or
24 * Anytun is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with Anytun. If not, see <http://www.gnu.org/licenses/>.
32 * In addition, as a special exception, the copyright holders give
33 * permission to link the code of portions of this program with the
34 * OpenSSL library under certain conditions as described in each
35 * individual source file, and distribute linked combinations
37 * You must obey the GNU General Public License in all respects
38 * for all of the code used other than OpenSSL. If you modify
39 * file(s) with this exception, you may extend this exception to your
40 * version of the file(s), but you are not obligated to do so. If you
41 * do not wish to do so, delete this exception statement from your
42 * version. If you delete this exception statement from all source
43 * files in the program, then also delete it here.
46 #include <boost/asio.hpp>
47 #include <boost/bind.hpp>
48 #include <boost/thread.hpp>
50 #include "datatypes.h"
51 #include "packetSource.h"
55 #include "signalController.h"
56 #include "anytunError.h"
58 void PacketSource::waitUntilReady()
63 UDPPacketSource::UDPPacketSource(std::string localaddr, std::string port)
65 gResolver.resolveUdp(localaddr, port, boost::bind(&UDPPacketSource::onResolve, this, _1), boost::bind(&UDPPacketSource::onError, this, _1), gOpt.getResolvAddrType());
68 UDPPacketSource::~UDPPacketSource()
70 std::list<SocketsElement>::iterator it = sockets_.begin();
71 for(; it != sockets_.end(); ++it) {
72 /// this might be a needed by the receiver thread, TODO cleanup
73 // delete[](it->buf_);
79 void UDPPacketSource::onResolve(PacketSourceResolverIt it)
81 while(it != PacketSourceResolverIt()) {
82 PacketSourceEndpoint e = *it;
83 cLog.msg(Log::PRIO_NOTICE) << "opening socket: " << e;
89 sock.sock_ = new proto::socket(io_service_);
91 AnytunError::throwErr() << "memory error";
94 sock.sock_->open(e.protocol());
95 #if !defined(_MSC_VER) && !defined(MINGW)
96 if(e.protocol() == proto::v6()) {
97 sock.sock_->set_option(boost::asio::ip::v6_only(true));
101 sockets_.push_back(sock);
106 // prepare multi-socket recv
107 if(sockets_.size() > 1) {
108 std::list<SocketsElement>::iterator it = sockets_.begin();
109 for(; it != sockets_.end(); ++it) {
110 it->len_ = MAX_PACKET_LENGTH;
111 it->buf_ = new uint8_t[it->len_];
113 AnytunError::throwErr() << "memory error";
116 it->sem_ = new Semaphore();
119 AnytunError::throwErr() << "memory error";
122 boost::thread(boost::bind(&UDPPacketSource::recv_thread, this, it));
131 void UDPPacketSource::onError(const std::runtime_error& e)
133 gSignalController.inject(SIGERROR, e.what());
136 void UDPPacketSource::recv_thread(std::list<SocketsElement>::iterator it)
138 cLog.msg(Log::PRIO_INFO) << "started receiver thread for " << it->sock_->local_endpoint();
144 result.len_ = static_cast<uint32_t>(it->sock_->receive_from(boost::asio::buffer(it->buf_, it->len_), result.remote_));
146 Lock lock(thread_result_mutex_);
147 thread_result_queue_.push(result);
149 thread_result_sem_.up();
153 uint32_t UDPPacketSource::recv(uint8_t* buf, uint32_t len, PacketSourceEndpoint& remote)
155 if(sockets_.size() == 1) {
156 return static_cast<uint32_t>(sockets_.front().sock_->receive_from(boost::asio::buffer(buf, len), remote));
159 thread_result_sem_.down();
162 Lock lock(thread_result_mutex_);
163 result = thread_result_queue_.front();
164 thread_result_queue_.pop();
166 remote = result.remote_;
167 std::memcpy(buf, result.it_->buf_, (len < result.len_) ? len : result.len_);
168 len = (len < result.len_) ? len : result.len_;
169 result.it_->sem_->up();
174 void UDPPacketSource::send(uint8_t* buf, uint32_t len, PacketSourceEndpoint remote)
176 std::list<SocketsElement>::iterator it = sockets_.begin();
177 for(; it != sockets_.end(); ++it) {
178 if(it->sock_->local_endpoint().protocol() == remote.protocol()) {
179 it->sock_->send_to(boost::asio::buffer(buf, len), remote);
183 cLog.msg(Log::PRIO_WARNING) << "no suitable socket found for remote endpoint protocol: " << remote;