mirror of
https://github.com/norohind/hans.git
synced 2025-06-05 18:03:11 +03:00
finished polling system change
This commit is contained in:
parent
63209c41df
commit
e8d388515f
2
Makefile
2
Makefile
@ -58,7 +58,7 @@ server.o: server.cpp server.h client.h utility.h config.h worker.h auth.h time.h
|
|||||||
auth.o: auth.cpp auth.h sha1.h utility.h
|
auth.o: auth.cpp auth.h sha1.h utility.h
|
||||||
g++ -c auth.cpp $(CFLAGS)
|
g++ -c auth.cpp $(CFLAGS)
|
||||||
|
|
||||||
worker.o: worker.cpp worker.h tun.h exception.h time.h echo.h tun_dev.h
|
worker.o: worker.cpp worker.h tun.h exception.h time.h echo.h tun_dev.h config.h
|
||||||
g++ -c worker.cpp $(CFLAGS)
|
g++ -c worker.cpp $(CFLAGS)
|
||||||
|
|
||||||
time.o: time.cpp time.h
|
time.o: time.cpp time.h
|
||||||
|
26
client.cpp
26
client.cpp
@ -31,12 +31,16 @@ using namespace std;
|
|||||||
|
|
||||||
const Worker::TunnelHeader::Magic Client::magic("9967");
|
const Worker::TunnelHeader::Magic Client::magic("9967");
|
||||||
|
|
||||||
Client::Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, int maxPolls, const char *passphrase, uid_t uid, gid_t gid)
|
Client::Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, int maxPolls,
|
||||||
|
const char *passphrase, uid_t uid, gid_t gid, bool changeEchoId, bool changeEchoSeq)
|
||||||
: Worker(tunnelMtu, deviceName, false, uid, gid), auth(passphrase)
|
: Worker(tunnelMtu, deviceName, false, uid, gid), auth(passphrase)
|
||||||
{
|
{
|
||||||
this->serverIp = serverIp;
|
this->serverIp = serverIp;
|
||||||
this->maxPolls = maxPolls;
|
this->maxPolls = maxPolls;
|
||||||
this->nextEchoId = Utility::rand();
|
this->nextEchoId = Utility::rand();
|
||||||
|
this->changeEchoId = changeEchoId;
|
||||||
|
this->changeEchoSeq = changeEchoSeq;
|
||||||
|
this->nextEchoSequence = Utility::rand();
|
||||||
|
|
||||||
state = STATE_CLOSED;
|
state = STATE_CLOSED;
|
||||||
}
|
}
|
||||||
@ -48,7 +52,7 @@ Client::~Client()
|
|||||||
|
|
||||||
void Client::sendConnectionRequest()
|
void Client::sendConnectionRequest()
|
||||||
{
|
{
|
||||||
Server::ClientConnectData *connectData = (Server::ClientConnectData *)payloadBuffer();
|
Server::ClientConnectData *connectData = (Server::ClientConnectData *)echoSendPayloadBuffer();
|
||||||
connectData->maxPolls = maxPolls;
|
connectData->maxPolls = maxPolls;
|
||||||
|
|
||||||
syslog(LOG_DEBUG, "sending connection request");
|
syslog(LOG_DEBUG, "sending connection request");
|
||||||
@ -70,11 +74,11 @@ void Client::sendChallengeResponse(int dataLength)
|
|||||||
|
|
||||||
vector<char> challenge;
|
vector<char> challenge;
|
||||||
challenge.resize(dataLength);
|
challenge.resize(dataLength);
|
||||||
memcpy(&challenge[0], payloadBuffer(), dataLength);
|
memcpy(&challenge[0], echoReceivePayloadBuffer(), dataLength);
|
||||||
|
|
||||||
Auth::Response response = auth.getResponse(challenge);
|
Auth::Response response = auth.getResponse(challenge);
|
||||||
|
|
||||||
memcpy(payloadBuffer(), (char *)&response, sizeof(Auth::Response));
|
memcpy(echoSendPayloadBuffer(), (char *)&response, sizeof(Auth::Response));
|
||||||
sendEchoToServer(TunnelHeader::TYPE_CHALLENGE_RESPONSE, sizeof(Auth::Response));
|
sendEchoToServer(TunnelHeader::TYPE_CHALLENGE_RESPONSE, sizeof(Auth::Response));
|
||||||
|
|
||||||
setTimeout(5000);
|
setTimeout(5000);
|
||||||
@ -123,7 +127,7 @@ bool Client::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t
|
|||||||
|
|
||||||
syslog(LOG_INFO, "connection established");
|
syslog(LOG_INFO, "connection established");
|
||||||
|
|
||||||
tun->setIp(ntohl(*(uint32_t *)payloadBuffer()));
|
tun->setIp(ntohl(*(uint32_t *)echoReceivePayloadBuffer()));
|
||||||
state = STATE_ESTABLISHED;
|
state = STATE_ESTABLISHED;
|
||||||
|
|
||||||
dropPrivileges();
|
dropPrivileges();
|
||||||
@ -157,10 +161,12 @@ void Client::sendEchoToServer(int type, int dataLength)
|
|||||||
if (maxPolls == 0 && state == STATE_ESTABLISHED)
|
if (maxPolls == 0 && state == STATE_ESTABLISHED)
|
||||||
setTimeout(KEEP_ALIVE_INTERVAL);
|
setTimeout(KEEP_ALIVE_INTERVAL);
|
||||||
|
|
||||||
sendEcho(magic, type, dataLength, serverIp, false, nextEchoId, 0);
|
sendEcho(magic, type, dataLength, serverIp, false, nextEchoId, nextEchoSequence);
|
||||||
|
|
||||||
if (maxPolls > 0)
|
if (changeEchoId)
|
||||||
nextEchoId = nextEchoId + 38543; // some random prime
|
nextEchoId = nextEchoId + 38543; // some random prime
|
||||||
|
if (changeEchoSeq)
|
||||||
|
nextEchoSequence = nextEchoSequence + 38543; // some random prime
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::startPolling()
|
void Client::startPolling()
|
||||||
@ -179,6 +185,12 @@ void Client::startPolling()
|
|||||||
|
|
||||||
void Client::handleDataFromServer(int dataLength)
|
void Client::handleDataFromServer(int dataLength)
|
||||||
{
|
{
|
||||||
|
if (dataLength == 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING, "received empty data packet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sendToTun(dataLength);
|
sendToTun(dataLength);
|
||||||
|
|
||||||
if (maxPolls != 0)
|
if (maxPolls != 0)
|
||||||
|
6
client.h
6
client.h
@ -28,7 +28,8 @@
|
|||||||
class Client : public Worker
|
class Client : public Worker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, int maxPolls, const char *passphrase, uid_t uid, gid_t gid);
|
Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, int maxPolls,
|
||||||
|
const char *passphrase, uid_t uid, gid_t gid, bool changeEchoId, bool changeEchoSeq);
|
||||||
virtual ~Client();
|
virtual ~Client();
|
||||||
|
|
||||||
virtual void run();
|
virtual void run();
|
||||||
@ -62,7 +63,10 @@ protected:
|
|||||||
int maxPolls;
|
int maxPolls;
|
||||||
int pollTimeoutNr;
|
int pollTimeoutNr;
|
||||||
|
|
||||||
|
bool changeEchoId, changeEchoSeq;
|
||||||
|
|
||||||
uint16_t nextEchoId;
|
uint16_t nextEchoId;
|
||||||
|
uint16_t nextEchoSequence;
|
||||||
|
|
||||||
State state;
|
State state;
|
||||||
};
|
};
|
||||||
|
3
config.h
3
config.h
@ -23,3 +23,6 @@
|
|||||||
#define POLL_INTERVAL 2000
|
#define POLL_INTERVAL 2000
|
||||||
|
|
||||||
#define CHALLENGE_SIZE 20
|
#define CHALLENGE_SIZE 20
|
||||||
|
|
||||||
|
//#define DEBUG_ONLY(a) a
|
||||||
|
#define DEBUG_ONLY(a)
|
||||||
|
17
echo.cpp
17
echo.cpp
@ -31,13 +31,16 @@ Echo::Echo(int maxPayloadSize)
|
|||||||
throw Exception("creating icmp socket", true);
|
throw Exception("creating icmp socket", true);
|
||||||
|
|
||||||
bufferSize = maxPayloadSize + headerSize();
|
bufferSize = maxPayloadSize + headerSize();
|
||||||
buffer = new char[bufferSize];
|
sendBuffer = new char[bufferSize];
|
||||||
|
receiveBuffer = new char[bufferSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
Echo::~Echo()
|
Echo::~Echo()
|
||||||
{
|
{
|
||||||
close(fd);
|
close(fd);
|
||||||
delete[] buffer;
|
|
||||||
|
delete[] sendBuffer;
|
||||||
|
delete[] receiveBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Echo::headerSize()
|
int Echo::headerSize()
|
||||||
@ -54,15 +57,15 @@ void Echo::send(int payloadLength, uint32_t realIp, bool reply, uint16_t id, uin
|
|||||||
if (payloadLength + sizeof(IpHeader) + sizeof(EchoHeader) > bufferSize)
|
if (payloadLength + sizeof(IpHeader) + sizeof(EchoHeader) > bufferSize)
|
||||||
throw Exception("packet too big");
|
throw Exception("packet too big");
|
||||||
|
|
||||||
EchoHeader *header = (EchoHeader *)(buffer + sizeof(IpHeader));
|
EchoHeader *header = (EchoHeader *)(sendBuffer + sizeof(IpHeader));
|
||||||
header->type = reply ? 0: 8;
|
header->type = reply ? 0: 8;
|
||||||
header->code = 0;
|
header->code = 0;
|
||||||
header->id = htons(id);
|
header->id = htons(id);
|
||||||
header->seq = htons(seq);
|
header->seq = htons(seq);
|
||||||
header->chksum = 0;
|
header->chksum = 0;
|
||||||
header->chksum = icmpChecksum(buffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader));
|
header->chksum = icmpChecksum(sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader));
|
||||||
|
|
||||||
int result = sendto(fd, buffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader), 0, (struct sockaddr *)&target, sizeof(struct sockaddr_in));
|
int result = sendto(fd, sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader), 0, (struct sockaddr *)&target, sizeof(struct sockaddr_in));
|
||||||
if (result == -1)
|
if (result == -1)
|
||||||
throw Exception("sendto", true);
|
throw Exception("sendto", true);
|
||||||
}
|
}
|
||||||
@ -72,14 +75,14 @@ int Echo::receive(uint32_t &realIp, bool &reply, uint16_t &id, uint16_t &seq)
|
|||||||
struct sockaddr_in source;
|
struct sockaddr_in source;
|
||||||
int source_addr_len = sizeof(struct sockaddr_in);
|
int source_addr_len = sizeof(struct sockaddr_in);
|
||||||
|
|
||||||
int dataLength = recvfrom(fd, buffer, bufferSize, 0, (struct sockaddr *)&source, (socklen_t *)&source_addr_len);
|
int dataLength = recvfrom(fd, receiveBuffer, bufferSize, 0, (struct sockaddr *)&source, (socklen_t *)&source_addr_len);
|
||||||
if (dataLength == -1)
|
if (dataLength == -1)
|
||||||
throw Exception("recvfrom", true);
|
throw Exception("recvfrom", true);
|
||||||
|
|
||||||
if (dataLength < sizeof(IpHeader) + sizeof(EchoHeader))
|
if (dataLength < sizeof(IpHeader) + sizeof(EchoHeader))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
EchoHeader *header = (EchoHeader *)(buffer + sizeof(IpHeader));
|
EchoHeader *header = (EchoHeader *)(receiveBuffer + sizeof(IpHeader));
|
||||||
if ((header->type != 0 && header->type != 8) || header->code != 0)
|
if ((header->type != 0 && header->type != 8) || header->code != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
5
echo.h
5
echo.h
@ -34,7 +34,8 @@ public:
|
|||||||
void send(int payloadLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq);
|
void send(int payloadLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq);
|
||||||
int receive(uint32_t &realIp, bool &reply, uint16_t &id, uint16_t &seq);
|
int receive(uint32_t &realIp, bool &reply, uint16_t &id, uint16_t &seq);
|
||||||
|
|
||||||
char *payloadBuffer() { return buffer + headerSize(); }
|
char *sendPayloadBuffer() { return sendBuffer + headerSize(); }
|
||||||
|
char *receivePayloadBuffer() { return receiveBuffer + headerSize(); }
|
||||||
|
|
||||||
static int headerSize();
|
static int headerSize();
|
||||||
protected:
|
protected:
|
||||||
@ -51,7 +52,7 @@ protected:
|
|||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
int bufferSize;
|
int bufferSize;
|
||||||
char *buffer;
|
char *sendBuffer, *receiveBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
30
main.cpp
30
main.cpp
@ -43,20 +43,17 @@ void usage()
|
|||||||
" -c server Connect to a server.\n"
|
" -c server Connect to a server.\n"
|
||||||
" -f Run in foreground.\n"
|
" -f Run in foreground.\n"
|
||||||
" -r Respond to ordinary pings. Only in server mode.\n"
|
" -r Respond to ordinary pings. Only in server mode.\n"
|
||||||
" Use this when you disable echo replies of your operating system, which is a good idea.\n"
|
|
||||||
" -p password Use a password.\n"
|
" -p password Use a password.\n"
|
||||||
" -u username Set the user under which the program should run.\n"
|
" -u username Set the user under which the program should run.\n"
|
||||||
" -d device Use the given tun device.\n"
|
" -d device Use the given tun device.\n"
|
||||||
" -m mtu Use this mtu to calculate the tunnel mtu.\n"
|
" -m mtu Use this mtu to calculate the tunnel mtu.\n"
|
||||||
" The generated ICMP packets will not be bigger than this value.\n"
|
" The generated ICMP packets will not be bigger than this value.\n"
|
||||||
" Has to be the same on client and server.\n"
|
" Has to be the same on client and server. Defaults to 1500.\n"
|
||||||
" In most cases you don't want to set this. Defaults to 1500.\n"
|
|
||||||
" -w polls Number of echo requests the client sends to the server for polling.\n"
|
" -w polls Number of echo requests the client sends to the server for polling.\n"
|
||||||
" If your network allows unlimited echo replies set this to 0 to disable polling.\n"
|
" 0 disables polling. Defaults to 10.\n"
|
||||||
" The default value of 10 is regarded as pretty high.\n"
|
" -i Change the echo id for every packet.\n"
|
||||||
" Set this to a lower value if you experience packet loss through the tunnel.\n"
|
" -q Change the echo sequence number for every packet.\n"
|
||||||
" Set this to 1 in extreme cases, when your network allows only one echo reply per request.\n"
|
);
|
||||||
" A low value will decrease the performance of the tunnel.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -74,11 +71,13 @@ int main(int argc, char *argv[])
|
|||||||
bool answerPing = false;
|
bool answerPing = false;
|
||||||
uid_t uid = 0;
|
uid_t uid = 0;
|
||||||
gid_t gid = 0;
|
gid_t gid = 0;
|
||||||
|
bool changeEchoId = false;
|
||||||
|
bool changeEchoSeq = false;
|
||||||
|
|
||||||
openlog(argv[0], LOG_PERROR, LOG_DAEMON);
|
openlog(argv[0], LOG_PERROR, LOG_DAEMON);
|
||||||
|
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt(argc, argv, "fru:d:p:s:c:m:w:")) != -1)
|
while ((c = getopt(argc, argv, "fru:d:p:s:c:m:w:qi")) != -1)
|
||||||
{
|
{
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
@ -101,6 +100,8 @@ int main(int argc, char *argv[])
|
|||||||
case 's':
|
case 's':
|
||||||
isServer = true;
|
isServer = true;
|
||||||
network = ntohl(inet_addr(optarg));
|
network = ntohl(inet_addr(optarg));
|
||||||
|
if (network == INADDR_NONE)
|
||||||
|
printf("invalid network\n");
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
mtu = atoi(optarg);
|
mtu = atoi(optarg);
|
||||||
@ -111,6 +112,12 @@ int main(int argc, char *argv[])
|
|||||||
case 'r':
|
case 'r':
|
||||||
answerPing = true;
|
answerPing = true;
|
||||||
break;
|
break;
|
||||||
|
case 'q':
|
||||||
|
changeEchoSeq = true;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
changeEchoId = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
return 1;
|
return 1;
|
||||||
@ -128,7 +135,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if ((isClient == isServer) ||
|
if ((isClient == isServer) ||
|
||||||
(isServer && network == INADDR_NONE) ||
|
(isServer && network == INADDR_NONE) ||
|
||||||
(maxPolls < 0 || maxPolls > 255))
|
(maxPolls < 0 || maxPolls > 255) ||
|
||||||
|
(isServer && (changeEchoSeq || changeEchoId)))
|
||||||
{
|
{
|
||||||
usage();
|
usage();
|
||||||
return 1;
|
return 1;
|
||||||
@ -173,7 +181,7 @@ int main(int argc, char *argv[])
|
|||||||
serverIp = *(uint32_t *)he->h_addr;
|
serverIp = *(uint32_t *)he->h_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
worker = new Client(mtu, device, ntohl(serverIp), maxPolls, password, uid, gid);
|
worker = new Client(mtu, device, ntohl(serverIp), maxPolls, password, uid, gid, changeEchoId, changeEchoSeq);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foreground)
|
if (!foreground)
|
||||||
|
46
server.cpp
46
server.cpp
@ -28,9 +28,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
//#define DEBUG_ONLY(a) a
|
|
||||||
#define DEBUG_ONLY(a)
|
|
||||||
|
|
||||||
const Worker::TunnelHeader::Magic Server::magic("9973");
|
const Worker::TunnelHeader::Magic Server::magic("9973");
|
||||||
|
|
||||||
Server::Server(int tunnelMtu, const char *deviceName, const char *passphrase, uint32_t network, bool answerEcho, uid_t uid, gid_t gid, int pollTimeout)
|
Server::Server(int tunnelMtu, const char *deviceName, const char *passphrase, uint32_t network, bool answerEcho, uid_t uid, gid_t gid, int pollTimeout)
|
||||||
@ -49,13 +46,13 @@ Server::~Server()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId)
|
void Server::handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId, uint16_t echoSeq)
|
||||||
{
|
{
|
||||||
ClientData client;
|
ClientData client;
|
||||||
client.realIp = realIp;
|
client.realIp = realIp;
|
||||||
client.maxPolls = 1;
|
client.maxPolls = 1;
|
||||||
|
|
||||||
pollReceived(&client, echoId);
|
pollReceived(&client, echoId, echoSeq);
|
||||||
|
|
||||||
if (header.type != TunnelHeader::TYPE_CONNECTION_REQUEST || dataLength != sizeof(ClientConnectData))
|
if (header.type != TunnelHeader::TYPE_CONNECTION_REQUEST || dataLength != sizeof(ClientConnectData))
|
||||||
{
|
{
|
||||||
@ -64,7 +61,7 @@ void Server::handleUnknownClient(const TunnelHeader &header, int dataLength, uin
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientConnectData *connectData = (ClientConnectData *)payloadBuffer();
|
ClientConnectData *connectData = (ClientConnectData *)echoReceivePayloadBuffer();
|
||||||
|
|
||||||
client.maxPolls = connectData->maxPolls;
|
client.maxPolls = connectData->maxPolls;
|
||||||
client.state = ClientData::STATE_NEW;
|
client.state = ClientData::STATE_NEW;
|
||||||
@ -93,7 +90,7 @@ void Server::sendChallenge(ClientData *client)
|
|||||||
{
|
{
|
||||||
syslog(LOG_DEBUG, "sending challenge to: %s\n", Utility::formatIp(client->realIp).c_str());
|
syslog(LOG_DEBUG, "sending challenge to: %s\n", Utility::formatIp(client->realIp).c_str());
|
||||||
|
|
||||||
memcpy(payloadBuffer(), &client->challenge[0], client->challenge.size());
|
memcpy(echoSendPayloadBuffer(), &client->challenge[0], client->challenge.size());
|
||||||
sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE, client->challenge.size());
|
sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE, client->challenge.size());
|
||||||
|
|
||||||
client->state = ClientData::STATE_CHALLENGE_SENT;
|
client->state = ClientData::STATE_CHALLENGE_SENT;
|
||||||
@ -117,7 +114,7 @@ void Server::checkChallenge(ClientData *client, int length)
|
|||||||
{
|
{
|
||||||
Auth::Response rightResponse = auth.getResponse(client->challenge);
|
Auth::Response rightResponse = auth.getResponse(client->challenge);
|
||||||
|
|
||||||
if (length != sizeof(Auth::Response) || memcmp(&rightResponse, payloadBuffer(), length) != 0)
|
if (length != sizeof(Auth::Response) || memcmp(&rightResponse, echoReceivePayloadBuffer(), length) != 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_DEBUG, "wrong challenge response\n");
|
syslog(LOG_DEBUG, "wrong challenge response\n");
|
||||||
|
|
||||||
@ -127,7 +124,7 @@ void Server::checkChallenge(ClientData *client, int length)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t *ip = (uint32_t *)payloadBuffer();
|
uint32_t *ip = (uint32_t *)echoSendPayloadBuffer();
|
||||||
*ip = htonl(client->tunnelIp);
|
*ip = htonl(client->tunnelIp);
|
||||||
|
|
||||||
sendEchoToClient(client, TunnelHeader::TYPE_CONNECTION_ACCEPT, sizeof(uint32_t));
|
sendEchoToClient(client, TunnelHeader::TYPE_CONNECTION_ACCEPT, sizeof(uint32_t));
|
||||||
@ -154,11 +151,11 @@ bool Server::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t
|
|||||||
ClientData *client = getClientByRealIp(realIp);
|
ClientData *client = getClientByRealIp(realIp);
|
||||||
if (client == NULL)
|
if (client == NULL)
|
||||||
{
|
{
|
||||||
handleUnknownClient(header, dataLength, realIp, id);
|
handleUnknownClient(header, dataLength, realIp, id, seq);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pollReceived(client, id);
|
pollReceived(client, id, seq);
|
||||||
|
|
||||||
switch (header.type)
|
switch (header.type)
|
||||||
{
|
{
|
||||||
@ -186,6 +183,13 @@ bool Server::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t
|
|||||||
case TunnelHeader::TYPE_DATA:
|
case TunnelHeader::TYPE_DATA:
|
||||||
if (client->state == ClientData::STATE_ESTABLISHED)
|
if (client->state == ClientData::STATE_ESTABLISHED)
|
||||||
{
|
{
|
||||||
|
if (dataLength == 0)
|
||||||
|
{
|
||||||
|
syslog(LOG_WARNING, "received empty data packet");
|
||||||
|
throw 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
sendToTun(dataLength);
|
sendToTun(dataLength);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -230,19 +234,19 @@ void Server::handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp)
|
|||||||
sendEchoToClient(client, TunnelHeader::TYPE_DATA, dataLength);
|
sendEchoToClient(client, TunnelHeader::TYPE_DATA, dataLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::pollReceived(ClientData *client, uint16_t echoId)
|
void Server::pollReceived(ClientData *client, uint16_t echoId, uint16_t echoSeq)
|
||||||
{
|
{
|
||||||
unsigned int maxSavedPolls = client->maxPolls != 0 ? client->maxPolls : 1;
|
unsigned int maxSavedPolls = client->maxPolls != 0 ? client->maxPolls : 1;
|
||||||
|
|
||||||
client->pollIds.push(echoId);
|
client->pollIds.push(ClientData::EchoId(echoId, echoSeq));
|
||||||
if (client->pollIds.size() > maxSavedPolls)
|
if (client->pollIds.size() > maxSavedPolls)
|
||||||
client->pollIds.pop();
|
client->pollIds.pop();
|
||||||
DEBUG_ONLY(printf("poll (%d) -> %d\n", echoId, client->pollIds.size()));
|
DEBUG_ONLY(printf("poll -> %d\n", client->pollIds.size()));
|
||||||
|
|
||||||
if (client->pendingPackets.size() > 0)
|
if (client->pendingPackets.size() > 0)
|
||||||
{
|
{
|
||||||
Packet &packet = client->pendingPackets.front();
|
Packet &packet = client->pendingPackets.front();
|
||||||
memcpy(payloadBuffer(), &packet.data[0], packet.data.size());
|
memcpy(echoSendPayloadBuffer(), &packet.data[0], packet.data.size());
|
||||||
client->pendingPackets.pop();
|
client->pendingPackets.pop();
|
||||||
|
|
||||||
DEBUG_ONLY(printf("pending packet: %d bytes\n", packet.data.size()));
|
DEBUG_ONLY(printf("pending packet: %d bytes\n", packet.data.size()));
|
||||||
@ -256,22 +260,20 @@ void Server::sendEchoToClient(ClientData *client, int type, int dataLength)
|
|||||||
{
|
{
|
||||||
if (client->maxPolls == 0)
|
if (client->maxPolls == 0)
|
||||||
{
|
{
|
||||||
sendEcho(magic, type, dataLength, client->realIp, true, client->pollIds.front(), 0);
|
sendEcho(magic, type, dataLength, client->realIp, true, client->pollIds.front().id, client->pollIds.front().seq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->pollIds.size() != 0)
|
if (client->pollIds.size() != 0)
|
||||||
{
|
{
|
||||||
uint16_t id = client->pollIds.front();
|
ClientData::EchoId echoId = client->pollIds.front();
|
||||||
client->pollIds.pop();
|
client->pollIds.pop();
|
||||||
|
|
||||||
DEBUG_ONLY(printf("sending (%d) -> %d\n", id, client->pollIds.size()));
|
DEBUG_ONLY(printf("sending -> %d\n", client->pollIds.size()));
|
||||||
sendEcho(magic, type, dataLength, client->realIp, true, id, 0);
|
sendEcho(magic, type, dataLength, client->realIp, true, echoId.id, echoId.seq);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_ONLY(printf("queuing -> %d\n", client->pollIds.size()));
|
|
||||||
|
|
||||||
if (client->pendingPackets.size() == MAX_BUFFERED_PACKETS)
|
if (client->pendingPackets.size() == MAX_BUFFERED_PACKETS)
|
||||||
{
|
{
|
||||||
client->pendingPackets.pop();
|
client->pendingPackets.pop();
|
||||||
@ -284,7 +286,7 @@ void Server::sendEchoToClient(ClientData *client, int type, int dataLength)
|
|||||||
Packet &packet = client->pendingPackets.back();
|
Packet &packet = client->pendingPackets.back();
|
||||||
packet.type = type;
|
packet.type = type;
|
||||||
packet.data.resize(dataLength);
|
packet.data.resize(dataLength);
|
||||||
memcpy(&packet.data[0], payloadBuffer(), dataLength);
|
memcpy(&packet.data[0], echoReceivePayloadBuffer(), dataLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::releaseTunnelIp(uint32_t tunnelIp)
|
void Server::releaseTunnelIp(uint32_t tunnelIp)
|
||||||
|
14
server.h
14
server.h
@ -57,13 +57,21 @@ protected:
|
|||||||
STATE_ESTABLISHED
|
STATE_ESTABLISHED
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct EchoId
|
||||||
|
{
|
||||||
|
EchoId(uint16_t id, uint16_t seq) { this->id = id; this->seq = seq; }
|
||||||
|
|
||||||
|
uint16_t id;
|
||||||
|
uint16_t seq;
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t realIp;
|
uint32_t realIp;
|
||||||
uint32_t tunnelIp;
|
uint32_t tunnelIp;
|
||||||
|
|
||||||
std::queue<Packet> pendingPackets;
|
std::queue<Packet> pendingPackets;
|
||||||
|
|
||||||
int maxPolls;
|
int maxPolls;
|
||||||
std::queue<uint16_t> pollIds;
|
std::queue<EchoId> pollIds;
|
||||||
Time lastActivity;
|
Time lastActivity;
|
||||||
|
|
||||||
State state;
|
State state;
|
||||||
@ -82,7 +90,7 @@ protected:
|
|||||||
|
|
||||||
void serveTun(ClientData *client);
|
void serveTun(ClientData *client);
|
||||||
|
|
||||||
void handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId);
|
void handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId, uint16_t echoSeq);
|
||||||
void removeClient(ClientData *client);
|
void removeClient(ClientData *client);
|
||||||
|
|
||||||
void sendChallenge(ClientData *client);
|
void sendChallenge(ClientData *client);
|
||||||
@ -91,7 +99,7 @@ protected:
|
|||||||
|
|
||||||
void sendEchoToClient(ClientData *client, int type, int dataLength);
|
void sendEchoToClient(ClientData *client, int type, int dataLength);
|
||||||
|
|
||||||
void pollReceived(ClientData *client, uint16_t echoId);
|
void pollReceived(ClientData *client, uint16_t echoId, uint16_t echoSeq);
|
||||||
|
|
||||||
uint32_t reserveTunnelIp();
|
uint32_t reserveTunnelIp();
|
||||||
void releaseTunnelIp(uint32_t tunnelIp);
|
void releaseTunnelIp(uint32_t tunnelIp);
|
||||||
|
20
worker.cpp
20
worker.cpp
@ -20,6 +20,7 @@
|
|||||||
#include "worker.h"
|
#include "worker.h"
|
||||||
#include "tun.h"
|
#include "tun.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
@ -78,16 +79,18 @@ void Worker::sendEcho(const TunnelHeader::Magic &magic, int type, int length, ui
|
|||||||
if (length > payloadBufferSize())
|
if (length > payloadBufferSize())
|
||||||
throw Exception("packet too big");
|
throw Exception("packet too big");
|
||||||
|
|
||||||
TunnelHeader *header = (TunnelHeader *)echo->payloadBuffer();
|
TunnelHeader *header = (TunnelHeader *)echo->sendPayloadBuffer();
|
||||||
header->magic = magic;
|
header->magic = magic;
|
||||||
header->type = type;
|
header->type = type;
|
||||||
|
|
||||||
|
DEBUG_ONLY(printf("sending: type %d, length %d, id %d, seq %d\n", type, length, id, seq));
|
||||||
|
|
||||||
echo->send(length + sizeof(TunnelHeader), realIp, reply, id, seq);
|
echo->send(length + sizeof(TunnelHeader), realIp, reply, id, seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::sendToTun(int length)
|
void Worker::sendToTun(int length)
|
||||||
{
|
{
|
||||||
tun->write(payloadBuffer(), length);
|
tun->write(echoReceivePayloadBuffer(), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Worker::setTimeout(Time delta)
|
void Worker::setTimeout(Time delta)
|
||||||
@ -145,19 +148,28 @@ void Worker::run()
|
|||||||
bool valid = dataLength >= sizeof(TunnelHeader);
|
bool valid = dataLength >= sizeof(TunnelHeader);
|
||||||
|
|
||||||
if (valid)
|
if (valid)
|
||||||
valid = handleEchoData(*(TunnelHeader *)(echo->payloadBuffer()), dataLength - sizeof(TunnelHeader), ip, reply, id, seq);
|
{
|
||||||
|
TunnelHeader header = *(TunnelHeader *)echo->receivePayloadBuffer(); // make a copy!
|
||||||
|
|
||||||
|
DEBUG_ONLY(printf("received: type %d, length %d, id %d, seq %d\n", header.type, dataLength - sizeof(TunnelHeader), id, seq));
|
||||||
|
|
||||||
|
valid = handleEchoData(header, dataLength - sizeof(TunnelHeader), ip, reply, id, seq);
|
||||||
|
}
|
||||||
|
|
||||||
if (!valid && !reply && answerEcho)
|
if (!valid && !reply && answerEcho)
|
||||||
|
{
|
||||||
|
memcpy(echo->sendPayloadBuffer(), echo->receivePayloadBuffer(), dataLength);
|
||||||
echo->send(dataLength, ip, true, id, seq);
|
echo->send(dataLength, ip, true, id, seq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// data from tun
|
// data from tun
|
||||||
if (FD_ISSET(tun->getFd(), &fs))
|
if (FD_ISSET(tun->getFd(), &fs))
|
||||||
{
|
{
|
||||||
uint32_t sourceIp, destIp;
|
uint32_t sourceIp, destIp;
|
||||||
|
|
||||||
int dataLength = tun->read(payloadBuffer(), sourceIp, destIp);
|
int dataLength = tun->read(echoSendPayloadBuffer(), sourceIp, destIp);
|
||||||
|
|
||||||
if (dataLength == 0)
|
if (dataLength == 0)
|
||||||
throw Exception("tunnel closed");
|
throw Exception("tunnel closed");
|
||||||
|
8
worker.h
8
worker.h
@ -68,15 +68,17 @@ protected:
|
|||||||
}; // size = 5
|
}; // size = 5
|
||||||
|
|
||||||
virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { return true; }
|
virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { return true; }
|
||||||
virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp) { }
|
virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp) { } // to echoSendPayloadBuffer
|
||||||
virtual void handleTimeout() { }
|
virtual void handleTimeout() { }
|
||||||
|
|
||||||
void sendEcho(const TunnelHeader::Magic &magic, int type, int length, uint32_t realIp, bool reply, uint16_t id, uint16_t seq);
|
void sendEcho(const TunnelHeader::Magic &magic, int type, int length, uint32_t realIp, bool reply, uint16_t id, uint16_t seq);
|
||||||
void sendToTun(int length);
|
void sendToTun(int length); // from echoReceivePayloadBuffer
|
||||||
|
|
||||||
void setTimeout(Time delta);
|
void setTimeout(Time delta);
|
||||||
|
|
||||||
char *payloadBuffer() { return echo->payloadBuffer() + sizeof(TunnelHeader); }
|
char *echoSendPayloadBuffer() { return echo->sendPayloadBuffer() + sizeof(TunnelHeader); }
|
||||||
|
char *echoReceivePayloadBuffer() { return echo->receivePayloadBuffer() + sizeof(TunnelHeader); }
|
||||||
|
|
||||||
int payloadBufferSize() { return tunnelMtu; }
|
int payloadBufferSize() { return tunnelMtu; }
|
||||||
|
|
||||||
void dropPrivileges();
|
void dropPrivileges();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user