diff --git a/Makefile b/Makefile index 7f6e5d1..ab853d0 100644 --- a/Makefile +++ b/Makefile @@ -7,47 +7,47 @@ GPP = g++ all: hans hans: tun.o sha1.o main.o client.o server.o auth.o worker.o time.o tun_dev.o echo.o exception.o utility.o - $(GPP) -o hans tun.o sha1.o main.o client.o server.o auth.o worker.o time.o tun_dev.o echo.o exception.o utility.o $(LDFLAGS) + $(GPP) -o hans tun.o sha1.o main.o client.o server.o auth.o worker.o time.o tun_dev.o echo.o exception.o utility.o $(LDFLAGS) utility.o: utility.cpp utility.h - $(GPP) -c utility.cpp $(CFLAGS) + $(GPP) -c utility.cpp $(CFLAGS) exception.o: exception.cpp exception.h - $(GPP) -c exception.cpp $(CFLAGS) + $(GPP) -c exception.cpp $(CFLAGS) echo.o: echo.cpp echo.h exception.h - $(GPP) -c echo.cpp $(CFLAGS) + $(GPP) -c echo.cpp $(CFLAGS) tun.o: tun.cpp tun.h exception.h utility.h tun_dev.h - $(GPP) -c tun.cpp $(CFLAGS) + $(GPP) -c tun.cpp $(CFLAGS) tun_dev.o: - $(GCC) -c $(TUN_DEV_FILE) -o tun_dev.o $(CFLAGS) + $(GCC) -c $(TUN_DEV_FILE) -o tun_dev.o $(CFLAGS) sha1.o: sha1.cpp sha1.h - $(GPP) -c sha1.cpp $(CFLAGS) + $(GPP) -c sha1.cpp $(CFLAGS) main.o: main.cpp client.h server.h exception.h worker.h auth.h time.h echo.h tun.h tun_dev.h - $(GPP) -c main.cpp $(CFLAGS) + $(GPP) -c main.cpp $(CFLAGS) client.o: client.cpp client.h server.h exception.h config.h worker.h auth.h time.h echo.h tun.h tun_dev.h - $(GPP) -c client.cpp $(CFLAGS) + $(GPP) -c client.cpp $(CFLAGS) server.o: server.cpp server.h client.h utility.h config.h worker.h auth.h time.h echo.h tun.h tun_dev.h - $(GPP) -c server.cpp $(CFLAGS) + $(GPP) -c server.cpp $(CFLAGS) auth.o: auth.cpp auth.h sha1.h utility.h - $(GPP) -c auth.cpp $(CFLAGS) + $(GPP) -c auth.cpp $(CFLAGS) worker.o: worker.cpp worker.h tun.h exception.h time.h echo.h tun_dev.h config.h - $(GPP) -c worker.cpp $(CFLAGS) + $(GPP) -c worker.cpp $(CFLAGS) time.o: time.cpp time.h - $(GPP) -c time.cpp $(CFLAGS) + $(GPP) -c time.cpp $(CFLAGS) clean: - rm -f tun.o sha1.o main.o client.o server.o auth.o worker.o time.o tun_dev.o echo.o exception.o utility.o tunemu.o hans + rm -f tun.o sha1.o main.o client.o server.o auth.o worker.o time.o tun_dev.o echo.o exception.o utility.o tunemu.o hans tunemu.o: tunemu.h tunemu.c - $(GCC) -c tunemu.c -o tunemu.o + $(GCC) -c tunemu.c -o tunemu.o diff --git a/auth.cpp b/auth.cpp index 2721c7a..f015616 100644 --- a/auth.cpp +++ b/auth.cpp @@ -25,33 +25,33 @@ Auth::Auth(const char *passphrase) { - this->passphrase = passphrase; + this->passphrase = passphrase; } Auth::Response Auth::getResponse(const Challenge &challenge) const { - SHA1 hasher; + SHA1 hasher; - Response response; + Response response; - hasher << passphrase.c_str(); - hasher.Input(&challenge[0], challenge.size()); + hasher << passphrase.c_str(); + hasher.Input(&challenge[0], challenge.size()); - hasher.Result((unsigned int *)response.data); - - for (int i = 0; i < 5; i++) - response.data[i] = htonl(response.data[i]); + hasher.Result((unsigned int *)response.data); + + for (int i = 0; i < 5; i++) + response.data[i] = htonl(response.data[i]); - return response; + return response; } Auth::Challenge Auth::generateChallenge(int length) const { - Challenge challenge; - challenge.resize(length); + Challenge challenge; + challenge.resize(length); - for (int i = 0; i < length; i++) - challenge[i] = Utility::rand(); + for (int i = 0; i < length; i++) + challenge[i] = Utility::rand(); - return challenge; + return challenge; } diff --git a/auth.h b/auth.h index b49ec59..e0bc444 100644 --- a/auth.h +++ b/auth.h @@ -28,22 +28,22 @@ class Auth { public: - typedef std::vector Challenge; + typedef std::vector Challenge; - struct Response - { - uint32_t data[5]; - bool operator==(const Response &other) const { return memcmp(this, &other, sizeof(Response)) == 0; } - }; + struct Response + { + uint32_t data[5]; + bool operator==(const Response &other) const { return memcmp(this, &other, sizeof(Response)) == 0; } + }; - Auth(const char *passphrase); + Auth(const char *passphrase); - Challenge generateChallenge(int length) const; - Response getResponse(const Challenge &challenge) const; + Challenge generateChallenge(int length) const; + Response getResponse(const Challenge &challenge) const; protected: - std::string passphrase; - std::string challenge; + std::string passphrase; + std::string challenge; }; #endif diff --git a/client.cpp b/client.cpp index 5f841c5..4aedcfe 100644 --- a/client.cpp +++ b/client.cpp @@ -36,16 +36,16 @@ Client::Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, bool changeEchoId, bool changeEchoSeq, uint32_t desiredIp) : Worker(tunnelMtu, deviceName, false, uid, gid), auth(passphrase) { - this->serverIp = serverIp; + this->serverIp = serverIp; this->clientIp = INADDR_NONE; this->desiredIp = desiredIp; - this->maxPolls = maxPolls; - this->nextEchoId = Utility::rand(); - this->changeEchoId = changeEchoId; - this->changeEchoSeq = changeEchoSeq; - this->nextEchoSequence = Utility::rand(); + this->maxPolls = maxPolls; + this->nextEchoId = Utility::rand(); + this->changeEchoId = changeEchoId; + this->changeEchoSeq = changeEchoSeq; + this->nextEchoSequence = Utility::rand(); - state = STATE_CLOSED; + state = STATE_CLOSED; } Client::~Client() @@ -55,82 +55,82 @@ Client::~Client() void Client::sendConnectionRequest() { - Server::ClientConnectData *connectData = (Server::ClientConnectData *)echoSendPayloadBuffer(); - connectData->maxPolls = maxPolls; + Server::ClientConnectData *connectData = (Server::ClientConnectData *)echoSendPayloadBuffer(); + connectData->maxPolls = maxPolls; connectData->desiredIp = desiredIp; - syslog(LOG_DEBUG, "sending connection request"); + syslog(LOG_DEBUG, "sending connection request"); - sendEchoToServer(TunnelHeader::TYPE_CONNECTION_REQUEST, sizeof(Server::ClientConnectData)); + sendEchoToServer(TunnelHeader::TYPE_CONNECTION_REQUEST, sizeof(Server::ClientConnectData)); - state = STATE_CONNECTION_REQUEST_SENT; - setTimeout(5000); + state = STATE_CONNECTION_REQUEST_SENT; + setTimeout(5000); } void Client::sendChallengeResponse(int dataLength) { - if (dataLength != CHALLENGE_SIZE) - throw Exception("invalid challenge received"); + if (dataLength != CHALLENGE_SIZE) + throw Exception("invalid challenge received"); - state = STATE_CHALLENGE_RESPONSE_SENT; + state = STATE_CHALLENGE_RESPONSE_SENT; - syslog(LOG_DEBUG, "sending challenge response"); + syslog(LOG_DEBUG, "sending challenge response"); - vector challenge; - challenge.resize(dataLength); - memcpy(&challenge[0], echoReceivePayloadBuffer(), dataLength); + vector challenge; + challenge.resize(dataLength); + memcpy(&challenge[0], echoReceivePayloadBuffer(), dataLength); - Auth::Response response = auth.getResponse(challenge); + Auth::Response response = auth.getResponse(challenge); - memcpy(echoSendPayloadBuffer(), (char *)&response, sizeof(Auth::Response)); - sendEchoToServer(TunnelHeader::TYPE_CHALLENGE_RESPONSE, sizeof(Auth::Response)); + memcpy(echoSendPayloadBuffer(), (char *)&response, sizeof(Auth::Response)); + sendEchoToServer(TunnelHeader::TYPE_CHALLENGE_RESPONSE, sizeof(Auth::Response)); - setTimeout(5000); + setTimeout(5000); } bool Client::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { - if (realIp != serverIp || !reply) - return false; + if (realIp != serverIp || !reply) + return false; - if (header.magic != Server::magic) - return false; + if (header.magic != Server::magic) + return false; - switch (header.type) - { - case TunnelHeader::TYPE_RESET_CONNECTION: - syslog(LOG_DEBUG, "reset reveiced"); + switch (header.type) + { + case TunnelHeader::TYPE_RESET_CONNECTION: + syslog(LOG_DEBUG, "reset reveiced"); - sendConnectionRequest(); - return true; - case TunnelHeader::TYPE_SERVER_FULL: - if (state == STATE_CONNECTION_REQUEST_SENT) - { - throw Exception("server full"); - } - break; - case TunnelHeader::TYPE_CHALLENGE: - if (state == STATE_CONNECTION_REQUEST_SENT) - { - syslog(LOG_DEBUG, "challenge received"); - sendChallengeResponse(dataLength); - return true; - } - break; - case TunnelHeader::TYPE_CONNECTION_ACCEPT: - if (state == STATE_CHALLENGE_RESPONSE_SENT) - { - if (dataLength != sizeof(uint32_t)) - { - throw Exception("invalid ip received"); - return true; - } + sendConnectionRequest(); + return true; + case TunnelHeader::TYPE_SERVER_FULL: + if (state == STATE_CONNECTION_REQUEST_SENT) + { + throw Exception("server full"); + } + break; + case TunnelHeader::TYPE_CHALLENGE: + if (state == STATE_CONNECTION_REQUEST_SENT) + { + syslog(LOG_DEBUG, "challenge received"); + sendChallengeResponse(dataLength); + return true; + } + break; + case TunnelHeader::TYPE_CONNECTION_ACCEPT: + if (state == STATE_CHALLENGE_RESPONSE_SENT) + { + if (dataLength != sizeof(uint32_t)) + { + throw Exception("invalid ip received"); + return true; + } - syslog(LOG_INFO, "connection established"); + syslog(LOG_INFO, "connection established"); - uint32_t ip = ntohl(*(uint32_t *)echoReceivePayloadBuffer()); + uint32_t ip = ntohl(*(uint32_t *)echoReceivePayloadBuffer()); if (ip != clientIp) - { + { if (privilegesDropped) throw Exception("could not get the same ip address, so root privileges are required to change it"); @@ -138,106 +138,106 @@ bool Client::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t desiredIp = ip; tun->setIp(ip, (ip & 0xffffff00) + 1, false); } - state = STATE_ESTABLISHED; + state = STATE_ESTABLISHED; - dropPrivileges(); - startPolling(); + dropPrivileges(); + startPolling(); - return true; - } - break; - case TunnelHeader::TYPE_CHALLENGE_ERROR: - if (state == STATE_CHALLENGE_RESPONSE_SENT) - { - throw Exception("password error"); - } - break; - case TunnelHeader::TYPE_DATA: - if (state == STATE_ESTABLISHED) - { - handleDataFromServer(dataLength); - return true; - } - break; - } + return true; + } + break; + case TunnelHeader::TYPE_CHALLENGE_ERROR: + if (state == STATE_CHALLENGE_RESPONSE_SENT) + { + throw Exception("password error"); + } + break; + case TunnelHeader::TYPE_DATA: + if (state == STATE_ESTABLISHED) + { + handleDataFromServer(dataLength); + return true; + } + break; + } - syslog(LOG_DEBUG, "invalid packet type: %d, state: %d", header.type, state); + syslog(LOG_DEBUG, "invalid packet type: %d, state: %d", header.type, state); - return true; + return true; } void Client::sendEchoToServer(int type, int dataLength) { - if (maxPolls == 0 && state == STATE_ESTABLISHED) - setTimeout(KEEP_ALIVE_INTERVAL); + if (maxPolls == 0 && state == STATE_ESTABLISHED) + setTimeout(KEEP_ALIVE_INTERVAL); - sendEcho(magic, type, dataLength, serverIp, false, nextEchoId, nextEchoSequence); + sendEcho(magic, type, dataLength, serverIp, false, nextEchoId, nextEchoSequence); - if (changeEchoId) - nextEchoId = nextEchoId + 38543; // some random prime - if (changeEchoSeq) - nextEchoSequence = nextEchoSequence + 38543; // some random prime + if (changeEchoId) + nextEchoId = nextEchoId + 38543; // some random prime + if (changeEchoSeq) + nextEchoSequence = nextEchoSequence + 38543; // some random prime } void Client::startPolling() { - if (maxPolls == 0) - { - setTimeout(KEEP_ALIVE_INTERVAL); - } - else - { - for (int i = 0; i < maxPolls; i++) - sendEchoToServer(TunnelHeader::TYPE_POLL, 0); - setTimeout(POLL_INTERVAL); - } + if (maxPolls == 0) + { + setTimeout(KEEP_ALIVE_INTERVAL); + } + else + { + for (int i = 0; i < maxPolls; i++) + sendEchoToServer(TunnelHeader::TYPE_POLL, 0); + setTimeout(POLL_INTERVAL); + } } void Client::handleDataFromServer(int dataLength) { - if (dataLength == 0) - { - syslog(LOG_WARNING, "received empty data packet"); - return; - } + if (dataLength == 0) + { + syslog(LOG_WARNING, "received empty data packet"); + return; + } - sendToTun(dataLength); + sendToTun(dataLength); - if (maxPolls != 0) - sendEchoToServer(TunnelHeader::TYPE_POLL, 0); + if (maxPolls != 0) + sendEchoToServer(TunnelHeader::TYPE_POLL, 0); } void Client::handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp) { - if (state != STATE_ESTABLISHED) - return; + if (state != STATE_ESTABLISHED) + return; - sendEchoToServer(TunnelHeader::TYPE_DATA, dataLength); + sendEchoToServer(TunnelHeader::TYPE_DATA, dataLength); } void Client::handleTimeout() { - switch (state) - { - case STATE_CONNECTION_REQUEST_SENT: - case STATE_CHALLENGE_RESPONSE_SENT: - sendConnectionRequest(); - break; + switch (state) + { + case STATE_CONNECTION_REQUEST_SENT: + case STATE_CHALLENGE_RESPONSE_SENT: + sendConnectionRequest(); + break; - case STATE_ESTABLISHED: - sendEchoToServer(TunnelHeader::TYPE_POLL, 0); - setTimeout(maxPolls == 0 ? KEEP_ALIVE_INTERVAL : POLL_INTERVAL); - break; - case STATE_CLOSED: - break; - } + case STATE_ESTABLISHED: + sendEchoToServer(TunnelHeader::TYPE_POLL, 0); + setTimeout(maxPolls == 0 ? KEEP_ALIVE_INTERVAL : POLL_INTERVAL); + break; + case STATE_CLOSED: + break; + } } void Client::run() { - now = Time::now(); + now = Time::now(); - sendConnectionRequest(); + sendConnectionRequest(); - Worker::run(); + Worker::run(); } diff --git a/client.h b/client.h index beee329..cd886c3 100644 --- a/client.h +++ b/client.h @@ -28,50 +28,50 @@ class Client : public Worker { public: - Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, + Client(int tunnelMtu, const char *deviceName, uint32_t serverIp, int maxPolls, const char *passphrase, uid_t uid, gid_t gid, bool changeEchoId, bool changeEchoSeq, uint32_t desiredIp); - virtual ~Client(); + virtual ~Client(); - virtual void run(); + virtual void run(); - static const Worker::TunnelHeader::Magic magic; + static const Worker::TunnelHeader::Magic magic; protected: - enum State - { - STATE_CLOSED, - STATE_CONNECTION_REQUEST_SENT, - STATE_CHALLENGE_RESPONSE_SENT, - STATE_ESTABLISHED - }; + enum State + { + STATE_CLOSED, + STATE_CONNECTION_REQUEST_SENT, + STATE_CHALLENGE_RESPONSE_SENT, + STATE_ESTABLISHED + }; - virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq); - virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); - virtual void handleTimeout(); + virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq); + virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); + virtual void handleTimeout(); - void handleDataFromServer(int length); + void handleDataFromServer(int length); - void startPolling(); + void startPolling(); - void sendEchoToServer(int type, int dataLength); - void sendChallengeResponse(int dataLength); - void sendConnectionRequest(); + void sendEchoToServer(int type, int dataLength); + void sendChallengeResponse(int dataLength); + void sendConnectionRequest(); - Auth auth; + Auth auth; - uint32_t serverIp; + uint32_t serverIp; uint32_t clientIp; uint32_t desiredIp; - int maxPolls; - int pollTimeoutNr; + int maxPolls; + int pollTimeoutNr; - bool changeEchoId, changeEchoSeq; + bool changeEchoId, changeEchoSeq; - uint16_t nextEchoId; - uint16_t nextEchoSequence; + uint16_t nextEchoId; + uint16_t nextEchoSequence; - State state; + State state; }; #endif diff --git a/echo.cpp b/echo.cpp index ec8fd94..e12f64a 100644 --- a/echo.cpp +++ b/echo.cpp @@ -34,88 +34,88 @@ typedef ip IpHeader; Echo::Echo(int maxPayloadSize) { - fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - if (fd == -1) - throw Exception("creating icmp socket", true); + fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (fd == -1) + throw Exception("creating icmp socket", true); - bufferSize = maxPayloadSize + headerSize(); - sendBuffer = new char[bufferSize]; - receiveBuffer = new char[bufferSize]; + bufferSize = maxPayloadSize + headerSize(); + sendBuffer = new char[bufferSize]; + receiveBuffer = new char[bufferSize]; } Echo::~Echo() { - close(fd); + close(fd); - delete[] sendBuffer; - delete[] receiveBuffer; + delete[] sendBuffer; + delete[] receiveBuffer; } int Echo::headerSize() { - return sizeof(IpHeader) + sizeof(EchoHeader); + return sizeof(IpHeader) + sizeof(EchoHeader); } void Echo::send(int payloadLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { - struct sockaddr_in target; - target.sin_family = AF_INET; - target.sin_addr.s_addr = htonl(realIp); + struct sockaddr_in target; + target.sin_family = AF_INET; + target.sin_addr.s_addr = htonl(realIp); - if (payloadLength + sizeof(IpHeader) + sizeof(EchoHeader) > bufferSize) - throw Exception("packet too big"); + if (payloadLength + sizeof(IpHeader) + sizeof(EchoHeader) > bufferSize) + throw Exception("packet too big"); - EchoHeader *header = (EchoHeader *)(sendBuffer + sizeof(IpHeader)); - header->type = reply ? 0: 8; - header->code = 0; - header->id = htons(id); - header->seq = htons(seq); - header->chksum = 0; - header->chksum = icmpChecksum(sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader)); + EchoHeader *header = (EchoHeader *)(sendBuffer + sizeof(IpHeader)); + header->type = reply ? 0: 8; + header->code = 0; + header->id = htons(id); + header->seq = htons(seq); + header->chksum = 0; + header->chksum = icmpChecksum(sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader)); - int result = sendto(fd, sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader), 0, (struct sockaddr *)&target, sizeof(struct sockaddr_in)); - if (result == -1) + int result = sendto(fd, sendBuffer + sizeof(IpHeader), payloadLength + sizeof(EchoHeader), 0, (struct sockaddr *)&target, sizeof(struct sockaddr_in)); + if (result == -1) syslog(LOG_ERR, "error sending icmp packet: %s", strerror(errno)); } int Echo::receive(uint32_t &realIp, bool &reply, uint16_t &id, uint16_t &seq) { - struct sockaddr_in source; - int source_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in source; + int source_addr_len = sizeof(struct sockaddr_in); - int dataLength = recvfrom(fd, receiveBuffer, bufferSize, 0, (struct sockaddr *)&source, (socklen_t *)&source_addr_len); - if (dataLength == -1) + int dataLength = recvfrom(fd, receiveBuffer, bufferSize, 0, (struct sockaddr *)&source, (socklen_t *)&source_addr_len); + if (dataLength == -1) { syslog(LOG_ERR, "error receiving icmp packet: %s", strerror(errno)); return -1; } - if (dataLength < sizeof(IpHeader) + sizeof(EchoHeader)) - return -1; + if (dataLength < sizeof(IpHeader) + sizeof(EchoHeader)) + return -1; - EchoHeader *header = (EchoHeader *)(receiveBuffer + sizeof(IpHeader)); - if ((header->type != 0 && header->type != 8) || header->code != 0) - return -1; + EchoHeader *header = (EchoHeader *)(receiveBuffer + sizeof(IpHeader)); + if ((header->type != 0 && header->type != 8) || header->code != 0) + return -1; - realIp = ntohl(source.sin_addr.s_addr); - reply = header->type == 0; - id = ntohs(header->id); - seq = ntohs(header->seq); + realIp = ntohl(source.sin_addr.s_addr); + reply = header->type == 0; + id = ntohs(header->id); + seq = ntohs(header->seq); - return dataLength - sizeof(IpHeader) - sizeof(EchoHeader); + return dataLength - sizeof(IpHeader) - sizeof(EchoHeader); } uint16_t Echo::icmpChecksum(const char *data, int length) { - uint16_t *data16 = (uint16_t *)data; - uint32_t sum = 0; - - for (sum = 0; length > 1; length -= 2) - sum += *data16++; - if (length == 1) - sum += *(unsigned char *)data16; - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - return ~sum; + uint16_t *data16 = (uint16_t *)data; + uint32_t sum = 0; + + for (sum = 0; length > 1; length -= 2) + sum += *data16++; + if (length == 1) + sum += *(unsigned char *)data16; + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; } diff --git a/echo.h b/echo.h index a5ff724..a683698 100644 --- a/echo.h +++ b/echo.h @@ -26,33 +26,33 @@ class Echo { public: - Echo(int maxPayloadSize); - ~Echo(); + Echo(int maxPayloadSize); + ~Echo(); - int getFd() { return fd; } + int getFd() { return fd; } - 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); + 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); - char *sendPayloadBuffer() { return sendBuffer + headerSize(); } - char *receivePayloadBuffer() { return receiveBuffer + headerSize(); } + char *sendPayloadBuffer() { return sendBuffer + headerSize(); } + char *receivePayloadBuffer() { return receiveBuffer + headerSize(); } - static int headerSize(); + static int headerSize(); protected: - struct EchoHeader - { - uint8_t type; - uint8_t code; - uint16_t chksum; - uint16_t id; - uint16_t seq; - }; // size = 8 + struct EchoHeader + { + uint8_t type; + uint8_t code; + uint16_t chksum; + uint16_t id; + uint16_t seq; + }; // size = 8 - uint16_t icmpChecksum(const char *data, int length); + uint16_t icmpChecksum(const char *data, int length); - int fd; - int bufferSize; - char *sendBuffer, *receiveBuffer; + int fd; + int bufferSize; + char *sendBuffer, *receiveBuffer; }; #endif diff --git a/exception.cpp b/exception.cpp index 02fa026..96d6d4e 100644 --- a/exception.cpp +++ b/exception.cpp @@ -26,13 +26,13 @@ using namespace std; Exception::Exception(const char *msg) { - this->msg = msg; + this->msg = msg; } Exception::Exception(const char *msg, bool appendSystemError) { - if (appendSystemError) - this->msg = string(msg) + ": " + strerror(errno); - else - this->msg = msg; + if (appendSystemError) + this->msg = string(msg) + ": " + strerror(errno); + else + this->msg = msg; } diff --git a/exception.h b/exception.h index e103206..46f9c71 100644 --- a/exception.h +++ b/exception.h @@ -22,10 +22,10 @@ class Exception { public: - Exception(const char *msg); - Exception(const char *msg, bool appendSystemError); - - const char *errorMessage() const { return msg.c_str(); } + Exception(const char *msg); + Exception(const char *msg, bool appendSystemError); + + const char *errorMessage() const { return msg.c_str(); } protected: - std::string msg; + std::string msg; }; diff --git a/main.cpp b/main.cpp index 718363b..802f121 100644 --- a/main.cpp +++ b/main.cpp @@ -33,184 +33,184 @@ void usage() { - printf( - "Hans - IP over ICMP version 0.4.1\n\n" - "RUN AS SERVER\n" - " hans -s network [-fvr] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu] [-a ip]\n\n" - "RUN AS CLIENT\n" - " hans -c server [-fv] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu] [-w polls]\n\n" - "ARGUMENTS\n" - " -s network Run as a server with the given network address for the virtual interface.\n" - " -c server Connect to a server.\n" - " -f Run in foreground.\n" - " -v Print debug information.\n" - " -r Respond to ordinary pings. Only in server mode.\n" - " -p password Use a password.\n" - " -u username Set the user under which the program should run.\n" - " -d device Use the given tun device.\n" - " -m mtu Use this mtu to calculate the tunnel mtu.\n" - " The generated echo packets will not be bigger than this value.\n" - " Has to be the same on client and server. Defaults to 1500.\n" - " -w polls Number of echo requests the client sends to the server for polling.\n" - " 0 disables polling. Defaults to 10.\n" - " -i Change the echo id for every echo request.\n" + printf( + "Hans - IP over ICMP version 0.4.1\n\n" + "RUN AS SERVER\n" + " hans -s network [-fvr] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu] [-a ip]\n\n" + "RUN AS CLIENT\n" + " hans -c server [-fv] [-p password] [-u unprivileged_user] [-d tun_device] [-m reference_mtu] [-w polls]\n\n" + "ARGUMENTS\n" + " -s network Run as a server with the given network address for the virtual interface.\n" + " -c server Connect to a server.\n" + " -f Run in foreground.\n" + " -v Print debug information.\n" + " -r Respond to ordinary pings. Only in server mode.\n" + " -p password Use a password.\n" + " -u username Set the user under which the program should run.\n" + " -d device Use the given tun device.\n" + " -m mtu Use this mtu to calculate the tunnel mtu.\n" + " The generated echo packets will not be bigger than this value.\n" + " Has to be the same on client and server. Defaults to 1500.\n" + " -w polls Number of echo requests the client sends to the server for polling.\n" + " 0 disables polling. Defaults to 10.\n" + " -i Change the echo id for every echo request.\n" " -q Change the echo sequence number for every echo request.\n" " -a ip Try to get assigned the given tunnel ip address.\n" - ); + ); } int main(int argc, char *argv[]) { - const char *serverName; - const char *userName = NULL; - const char *password = ""; - const char *device = NULL; - bool isServer = false; - bool isClient = false; - bool foreground = false; - int mtu = 1500; - int maxPolls = 10; - uint32_t network = INADDR_NONE; + const char *serverName; + const char *userName = NULL; + const char *password = ""; + const char *device = NULL; + bool isServer = false; + bool isClient = false; + bool foreground = false; + int mtu = 1500; + int maxPolls = 10; + uint32_t network = INADDR_NONE; uint32_t clientIp = INADDR_NONE; - bool answerPing = false; - uid_t uid = 0; - gid_t gid = 0; - bool changeEchoId = false; - bool changeEchoSeq = false; - bool verbose = false; - - openlog(argv[0], LOG_PERROR, LOG_DAEMON); + bool answerPing = false; + uid_t uid = 0; + gid_t gid = 0; + bool changeEchoId = false; + bool changeEchoSeq = false; + bool verbose = false; + + openlog(argv[0], LOG_PERROR, LOG_DAEMON); - int c; - while ((c = getopt(argc, argv, "fru:d:p:s:c:m:w:qiva:")) != -1) - { - switch(c) { - case 'f': - foreground = true; - break; - case 'u': - userName = optarg; - break; - case 'd': - device = optarg; - break; - case 'p': - password = strdup(optarg); - memset(optarg, 0, strlen(optarg)); - break; - case 'c': - isClient = true; - serverName = optarg; - break; - case 's': - isServer = true; - network = ntohl(inet_addr(optarg)); - if (network == INADDR_NONE) - printf("invalid network\n"); - break; - case 'm': - mtu = atoi(optarg); - break; - case 'w': - maxPolls = atoi(optarg); - break; - case 'r': - answerPing = true; - break; - case 'q': - changeEchoSeq = true; - break; - case 'i': - changeEchoId = true; - break; - case 'v': - verbose = true; - break; - case 'a': - clientIp = ntohl(inet_addr(optarg)); - break; - default: - usage(); - return 1; - } - } + int c; + while ((c = getopt(argc, argv, "fru:d:p:s:c:m:w:qiva:")) != -1) + { + switch(c) { + case 'f': + foreground = true; + break; + case 'u': + userName = optarg; + break; + case 'd': + device = optarg; + break; + case 'p': + password = strdup(optarg); + memset(optarg, 0, strlen(optarg)); + break; + case 'c': + isClient = true; + serverName = optarg; + break; + case 's': + isServer = true; + network = ntohl(inet_addr(optarg)); + if (network == INADDR_NONE) + printf("invalid network\n"); + break; + case 'm': + mtu = atoi(optarg); + break; + case 'w': + maxPolls = atoi(optarg); + break; + case 'r': + answerPing = true; + break; + case 'q': + changeEchoSeq = true; + break; + case 'i': + changeEchoId = true; + break; + case 'v': + verbose = true; + break; + case 'a': + clientIp = ntohl(inet_addr(optarg)); + break; + default: + usage(); + return 1; + } + } - mtu -= Echo::headerSize() + Worker::headerSize(); + mtu -= Echo::headerSize() + Worker::headerSize(); - if (mtu < 68) - { - // RFC 791: Every internet module must be able to forward a datagram of 68 octets without further fragmentation. - printf("mtu too small\n"); - return 1; - } + if (mtu < 68) + { + // RFC 791: Every internet module must be able to forward a datagram of 68 octets without further fragmentation. + printf("mtu too small\n"); + return 1; + } - if ((isClient == isServer) || - (isServer && network == INADDR_NONE) || - (maxPolls < 0 || maxPolls > 255) || - (isServer && (changeEchoSeq || changeEchoId))) - { - usage(); - return 1; - } + if ((isClient == isServer) || + (isServer && network == INADDR_NONE) || + (maxPolls < 0 || maxPolls > 255) || + (isServer && (changeEchoSeq || changeEchoId))) + { + usage(); + return 1; + } - if (userName != NULL) - { - passwd *pw = getpwnam(userName); + if (userName != NULL) + { + passwd *pw = getpwnam(userName); - if (pw != NULL) - { - uid = pw->pw_uid; - gid = pw->pw_gid; - } - else - { - syslog(LOG_ERR, "user not found"); - return 1; - } - } + if (pw != NULL) + { + uid = pw->pw_uid; + gid = pw->pw_gid; + } + else + { + syslog(LOG_ERR, "user not found"); + return 1; + } + } - if (!verbose) - setlogmask(LOG_UPTO(LOG_INFO)); + if (!verbose) + setlogmask(LOG_UPTO(LOG_INFO)); - try - { - Worker *worker; + try + { + Worker *worker; - if (isServer) - { - worker = new Server(mtu, device, password, network, answerPing, uid, gid, 5000); - } - else - { - uint32_t serverIp = inet_addr(serverName); - if (serverIp == INADDR_NONE) - { - struct hostent* he = gethostbyname(serverName); - if (!he) - { - syslog(LOG_ERR, "gethostbyname: %s", hstrerror(h_errno)); - return 1; - } + if (isServer) + { + worker = new Server(mtu, device, password, network, answerPing, uid, gid, 5000); + } + else + { + uint32_t serverIp = inet_addr(serverName); + if (serverIp == INADDR_NONE) + { + struct hostent* he = gethostbyname(serverName); + if (!he) + { + syslog(LOG_ERR, "gethostbyname: %s", hstrerror(h_errno)); + return 1; + } - serverIp = *(uint32_t *)he->h_addr; - } + serverIp = *(uint32_t *)he->h_addr; + } - worker = new Client(mtu, device, ntohl(serverIp), maxPolls, password, uid, gid, changeEchoId, changeEchoSeq, clientIp); - } + worker = new Client(mtu, device, ntohl(serverIp), maxPolls, password, uid, gid, changeEchoId, changeEchoSeq, clientIp); + } - if (!foreground) - { - syslog(LOG_INFO, "detaching from terminal"); - daemon(0, 0); - } + if (!foreground) + { + syslog(LOG_INFO, "detaching from terminal"); + daemon(0, 0); + } - worker->run(); - } - catch (Exception e) - { - syslog(LOG_ERR, "%s", e.errorMessage()); - return 1; - } + worker->run(); + } + catch (Exception e) + { + syslog(LOG_ERR, "%s", e.errorMessage()); + return 1; + } return 0; } diff --git a/osflags b/osflags index 5c5155b..a0dacb6 100644 --- a/osflags +++ b/osflags @@ -5,48 +5,48 @@ MODE=`echo "$2" | tr "a-z" "A-Z"` case $1 in ld) - case $OS in - DARWIN) - if [ "$MODE" == TUNEMU ]; then - echo tunemu.o -lpcap - fi - ;; - esac - ;; + case $OS in + DARWIN) + if [ "$MODE" == TUNEMU ]; then + echo tunemu.o -lpcap + fi + ;; + esac + ;; c) - FLAGS=-D$OS + FLAGS=-D$OS - case $OS in - LINUX) - echo $FLAGS -DHAVE_LINUX_IF_TUN_H - ;; - *) - echo $FLAGS - ;; - esac - ;; + case $OS in + LINUX) + echo $FLAGS -DHAVE_LINUX_IF_TUN_H + ;; + *) + echo $FLAGS + ;; + esac + ;; dev) - case $OS in - LINUX) - echo tun_dev_linux.c - ;; - FREEBSD) - echo tun_dev_freebsd.c - ;; - OPENBSD) - echo tun_dev_openbsd.c - ;; - DARWIN) - if [ "$MODE" == TUNEMU ]; then - echo tun_dev_darwin_emu.c - else - echo tun_dev_generic.c - fi - ;; - *) - echo tun_dev_generic.c - ;; - esac - ;; + case $OS in + LINUX) + echo tun_dev_linux.c + ;; + FREEBSD) + echo tun_dev_freebsd.c + ;; + OPENBSD) + echo tun_dev_openbsd.c + ;; + DARWIN) + if [ "$MODE" == TUNEMU ]; then + echo tun_dev_darwin_emu.c + else + echo tun_dev_generic.c + fi + ;; + *) + echo tun_dev_generic.c + ;; + esac + ;; esac diff --git a/server.cpp b/server.cpp index dce368f..b5bc69f 100644 --- a/server.cpp +++ b/server.cpp @@ -33,15 +33,15 @@ using namespace std; const Worker::TunnelHeader::Magic Server::magic("hans"); Server::Server(int tunnelMtu, const char *deviceName, const char *passphrase, uint32_t network, bool answerEcho, uid_t uid, gid_t gid, int pollTimeout) - : Worker(tunnelMtu, deviceName, answerEcho, uid, gid), auth(passphrase) + : Worker(tunnelMtu, deviceName, answerEcho, uid, gid), auth(passphrase) { - this->network = network & 0xffffff00; - this->pollTimeout = pollTimeout; + this->network = network & 0xffffff00; + this->pollTimeout = pollTimeout; this->latestAssignedIpOffset = FIRST_ASSIGNED_IP_OFFSET - 1; - tun->setIp(this->network + 1, this->network + 2, true); + tun->setIp(this->network + 1, this->network + 2, true); - dropPrivileges(); + dropPrivileges(); } Server::~Server() @@ -51,269 +51,269 @@ Server::~Server() void Server::handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId, uint16_t echoSeq) { - ClientData client; - client.realIp = realIp; - client.maxPolls = 1; + ClientData client; + client.realIp = realIp; + client.maxPolls = 1; - pollReceived(&client, echoId, echoSeq); + pollReceived(&client, echoId, echoSeq); - if (header.type != TunnelHeader::TYPE_CONNECTION_REQUEST || dataLength != sizeof(ClientConnectData)) - { - syslog(LOG_DEBUG, "invalid request %s", Utility::formatIp(realIp).c_str()); - sendReset(&client); - return; - } + if (header.type != TunnelHeader::TYPE_CONNECTION_REQUEST || dataLength != sizeof(ClientConnectData)) + { + syslog(LOG_DEBUG, "invalid request %s", Utility::formatIp(realIp).c_str()); + sendReset(&client); + return; + } - ClientConnectData *connectData = (ClientConnectData *)echoReceivePayloadBuffer(); + ClientConnectData *connectData = (ClientConnectData *)echoReceivePayloadBuffer(); - client.maxPolls = connectData->maxPolls; - client.state = ClientData::STATE_NEW; - client.tunnelIp = reserveTunnelIp(connectData->desiredIp); + client.maxPolls = connectData->maxPolls; + client.state = ClientData::STATE_NEW; + client.tunnelIp = reserveTunnelIp(connectData->desiredIp); - syslog(LOG_DEBUG, "new client: %s (%s)\n", Utility::formatIp(client.realIp).c_str(), Utility::formatIp(client.tunnelIp).c_str()); + syslog(LOG_DEBUG, "new client: %s (%s)\n", Utility::formatIp(client.realIp).c_str(), Utility::formatIp(client.tunnelIp).c_str()); - if (client.tunnelIp != 0) - { - client.challenge = auth.generateChallenge(CHALLENGE_SIZE); - sendChallenge(&client); + if (client.tunnelIp != 0) + { + client.challenge = auth.generateChallenge(CHALLENGE_SIZE); + sendChallenge(&client); - // add client to list - clientList.push_back(client); - clientRealIpMap[realIp] = clientList.size() - 1; - clientTunnelIpMap[client.tunnelIp] = clientList.size() - 1; - } - else - { - syslog(LOG_WARNING, "server full"); - sendEchoToClient(&client, TunnelHeader::TYPE_SERVER_FULL, 0); - } + // add client to list + clientList.push_back(client); + clientRealIpMap[realIp] = clientList.size() - 1; + clientTunnelIpMap[client.tunnelIp] = clientList.size() - 1; + } + else + { + syslog(LOG_WARNING, "server full"); + sendEchoToClient(&client, TunnelHeader::TYPE_SERVER_FULL, 0); + } } 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(echoSendPayloadBuffer(), &client->challenge[0], client->challenge.size()); - sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE, client->challenge.size()); + memcpy(echoSendPayloadBuffer(), &client->challenge[0], client->challenge.size()); + sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE, client->challenge.size()); - client->state = ClientData::STATE_CHALLENGE_SENT; + client->state = ClientData::STATE_CHALLENGE_SENT; } void Server::removeClient(ClientData *client) { - syslog(LOG_DEBUG, "removing client: %s (%s)\n", Utility::formatIp(client->realIp).c_str(), Utility::formatIp(client->tunnelIp).c_str()); + syslog(LOG_DEBUG, "removing client: %s (%s)\n", Utility::formatIp(client->realIp).c_str(), Utility::formatIp(client->tunnelIp).c_str()); - releaseTunnelIp(client->tunnelIp); + releaseTunnelIp(client->tunnelIp); - int nr = clientRealIpMap[client->realIp]; + int nr = clientRealIpMap[client->realIp]; - clientRealIpMap.erase(client->realIp); - clientTunnelIpMap.erase(client->tunnelIp); + clientRealIpMap.erase(client->realIp); + clientTunnelIpMap.erase(client->tunnelIp); - clientList.erase(clientList.begin() + nr); + clientList.erase(clientList.begin() + nr); } 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, echoReceivePayloadBuffer(), length) != 0) - { - syslog(LOG_DEBUG, "wrong challenge response\n"); + if (length != sizeof(Auth::Response) || memcmp(&rightResponse, echoReceivePayloadBuffer(), length) != 0) + { + syslog(LOG_DEBUG, "wrong challenge response\n"); - sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE_ERROR, 0); + sendEchoToClient(client, TunnelHeader::TYPE_CHALLENGE_ERROR, 0); - removeClient(client); - return; - } + removeClient(client); + return; + } - uint32_t *ip = (uint32_t *)echoSendPayloadBuffer(); - *ip = htonl(client->tunnelIp); + uint32_t *ip = (uint32_t *)echoSendPayloadBuffer(); + *ip = htonl(client->tunnelIp); - sendEchoToClient(client, TunnelHeader::TYPE_CONNECTION_ACCEPT, sizeof(uint32_t)); + sendEchoToClient(client, TunnelHeader::TYPE_CONNECTION_ACCEPT, sizeof(uint32_t)); - client->state = ClientData::STATE_ESTABLISHED; + client->state = ClientData::STATE_ESTABLISHED; - syslog(LOG_INFO, "connection established: %s", Utility::formatIp(client->realIp).c_str()); + syslog(LOG_INFO, "connection established: %s", Utility::formatIp(client->realIp).c_str()); } void Server::sendReset(ClientData *client) { - syslog(LOG_DEBUG, "sending reset: %s", Utility::formatIp(client->realIp).c_str()); - sendEchoToClient(client, TunnelHeader::TYPE_RESET_CONNECTION, 0); + syslog(LOG_DEBUG, "sending reset: %s", Utility::formatIp(client->realIp).c_str()); + sendEchoToClient(client, TunnelHeader::TYPE_RESET_CONNECTION, 0); } bool Server::handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { - if (reply) - return false; + if (reply) + return false; - if (header.magic != Client::magic) - return false; + if (header.magic != Client::magic) + return false; - ClientData *client = getClientByRealIp(realIp); - if (client == NULL) - { - handleUnknownClient(header, dataLength, realIp, id, seq); - return true; - } + ClientData *client = getClientByRealIp(realIp); + if (client == NULL) + { + handleUnknownClient(header, dataLength, realIp, id, seq); + return true; + } - pollReceived(client, id, seq); + pollReceived(client, id, seq); - switch (header.type) - { - case TunnelHeader::TYPE_CONNECTION_REQUEST: - if (client->state == ClientData::STATE_CHALLENGE_SENT) - { - sendChallenge(client); - return true; - } + switch (header.type) + { + case TunnelHeader::TYPE_CONNECTION_REQUEST: + if (client->state == ClientData::STATE_CHALLENGE_SENT) + { + sendChallenge(client); + return true; + } - while (client->pollIds.size() > 1) - client->pollIds.pop(); + while (client->pollIds.size() > 1) + client->pollIds.pop(); - syslog(LOG_DEBUG, "reconnecting %s", Utility::formatIp(realIp).c_str()); - sendReset(client); - removeClient(client); - return true; - case TunnelHeader::TYPE_CHALLENGE_RESPONSE: - if (client->state == ClientData::STATE_CHALLENGE_SENT) - { - checkChallenge(client, dataLength); - return true; - } - break; - case TunnelHeader::TYPE_DATA: - if (client->state == ClientData::STATE_ESTABLISHED) - { - if (dataLength == 0) - { - syslog(LOG_WARNING, "received empty data packet"); - return true; - } + syslog(LOG_DEBUG, "reconnecting %s", Utility::formatIp(realIp).c_str()); + sendReset(client); + removeClient(client); + return true; + case TunnelHeader::TYPE_CHALLENGE_RESPONSE: + if (client->state == ClientData::STATE_CHALLENGE_SENT) + { + checkChallenge(client, dataLength); + return true; + } + break; + case TunnelHeader::TYPE_DATA: + if (client->state == ClientData::STATE_ESTABLISHED) + { + if (dataLength == 0) + { + syslog(LOG_WARNING, "received empty data packet"); + return true; + } - sendToTun(dataLength); - return true; - } - break; - case TunnelHeader::TYPE_POLL: - return true; - } + sendToTun(dataLength); + return true; + } + break; + case TunnelHeader::TYPE_POLL: + return true; + } - syslog(LOG_DEBUG, "invalid packet from: %s, type: %d, state: %d", Utility::formatIp(realIp).c_str(), header.type, client->state); + syslog(LOG_DEBUG, "invalid packet from: %s, type: %d, state: %d", Utility::formatIp(realIp).c_str(), header.type, client->state); - return true; + return true; } Server::ClientData *Server::getClientByTunnelIp(uint32_t ip) { - ClientIpMap::iterator clientMapIterator = clientTunnelIpMap.find(ip); - if (clientMapIterator == clientTunnelIpMap.end()) - return NULL; - - return &clientList[clientMapIterator->second]; + ClientIpMap::iterator clientMapIterator = clientTunnelIpMap.find(ip); + if (clientMapIterator == clientTunnelIpMap.end()) + return NULL; + + return &clientList[clientMapIterator->second]; } Server::ClientData *Server::getClientByRealIp(uint32_t ip) { - ClientIpMap::iterator clientMapIterator = clientRealIpMap.find(ip); - if (clientMapIterator == clientRealIpMap.end()) - return NULL; - - return &clientList[clientMapIterator->second]; + ClientIpMap::iterator clientMapIterator = clientRealIpMap.find(ip); + if (clientMapIterator == clientRealIpMap.end()) + return NULL; + + return &clientList[clientMapIterator->second]; } void Server::handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp) { - if (destIp == network + 255) // ignore broadcasts - return; + if (destIp == network + 255) // ignore broadcasts + return; - ClientData *client = getClientByTunnelIp(destIp); + ClientData *client = getClientByTunnelIp(destIp); - if (client == NULL) - { - syslog(LOG_DEBUG, "unknown client: %s\n", Utility::formatIp(destIp).c_str()); - return; - } + if (client == NULL) + { + syslog(LOG_DEBUG, "unknown client: %s\n", Utility::formatIp(destIp).c_str()); + return; + } - sendEchoToClient(client, TunnelHeader::TYPE_DATA, dataLength); + sendEchoToClient(client, TunnelHeader::TYPE_DATA, dataLength); } 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(ClientData::EchoId(echoId, echoSeq)); - if (client->pollIds.size() > maxSavedPolls) - client->pollIds.pop(); - DEBUG_ONLY(printf("poll -> %d\n", client->pollIds.size())); + client->pollIds.push(ClientData::EchoId(echoId, echoSeq)); + if (client->pollIds.size() > maxSavedPolls) + client->pollIds.pop(); + DEBUG_ONLY(printf("poll -> %d\n", client->pollIds.size())); - if (client->pendingPackets.size() > 0) - { - Packet &packet = client->pendingPackets.front(); - memcpy(echoSendPayloadBuffer(), &packet.data[0], packet.data.size()); - client->pendingPackets.pop(); + if (client->pendingPackets.size() > 0) + { + Packet &packet = client->pendingPackets.front(); + memcpy(echoSendPayloadBuffer(), &packet.data[0], packet.data.size()); + client->pendingPackets.pop(); - DEBUG_ONLY(printf("pending packet: %d bytes\n", packet.data.size())); - sendEchoToClient(client, packet.type, packet.data.size()); - } + DEBUG_ONLY(printf("pending packet: %d bytes\n", packet.data.size())); + sendEchoToClient(client, packet.type, packet.data.size()); + } - client->lastActivity = now; + client->lastActivity = now; } void Server::sendEchoToClient(ClientData *client, int type, int dataLength) { - if (client->maxPolls == 0) - { - sendEcho(magic, type, dataLength, client->realIp, true, client->pollIds.front().id, client->pollIds.front().seq); - return; - } + if (client->maxPolls == 0) + { + sendEcho(magic, type, dataLength, client->realIp, true, client->pollIds.front().id, client->pollIds.front().seq); + return; + } - if (client->pollIds.size() != 0) - { - ClientData::EchoId echoId = client->pollIds.front(); - client->pollIds.pop(); + if (client->pollIds.size() != 0) + { + ClientData::EchoId echoId = client->pollIds.front(); + client->pollIds.pop(); - DEBUG_ONLY(printf("sending -> %d\n", client->pollIds.size())); - sendEcho(magic, type, dataLength, client->realIp, true, echoId.id, echoId.seq); - return; - } + DEBUG_ONLY(printf("sending -> %d\n", client->pollIds.size())); + sendEcho(magic, type, dataLength, client->realIp, true, echoId.id, echoId.seq); + return; + } - if (client->pendingPackets.size() == MAX_BUFFERED_PACKETS) - { - client->pendingPackets.pop(); - syslog(LOG_WARNING, "packet dropped to %s", Utility::formatIp(client->tunnelIp).c_str()); - } + if (client->pendingPackets.size() == MAX_BUFFERED_PACKETS) + { + client->pendingPackets.pop(); + syslog(LOG_WARNING, "packet dropped to %s", Utility::formatIp(client->tunnelIp).c_str()); + } - DEBUG_ONLY(printf("packet queued: %d bytes\n", dataLength)); + DEBUG_ONLY(printf("packet queued: %d bytes\n", dataLength)); - client->pendingPackets.push(Packet()); - Packet &packet = client->pendingPackets.back(); - packet.type = type; - packet.data.resize(dataLength); - memcpy(&packet.data[0], echoReceivePayloadBuffer(), dataLength); + client->pendingPackets.push(Packet()); + Packet &packet = client->pendingPackets.back(); + packet.type = type; + packet.data.resize(dataLength); + memcpy(&packet.data[0], echoReceivePayloadBuffer(), dataLength); } void Server::releaseTunnelIp(uint32_t tunnelIp) { - usedIps.erase(tunnelIp); + usedIps.erase(tunnelIp); } void Server::handleTimeout() { - for (int i = 0; i < clientList.size(); i++) - { - ClientData *client = &clientList[i]; + for (int i = 0; i < clientList.size(); i++) + { + ClientData *client = &clientList[i]; - if (client->lastActivity + KEEP_ALIVE_INTERVAL * 2 < now) - { - syslog(LOG_DEBUG, "client timeout: %s\n", Utility::formatIp(client->realIp).c_str()); - removeClient(client); - i--; - } - } + if (client->lastActivity + KEEP_ALIVE_INTERVAL * 2 < now) + { + syslog(LOG_DEBUG, "client timeout: %s\n", Utility::formatIp(client->realIp).c_str()); + removeClient(client); + i--; + } + } - setTimeout(KEEP_ALIVE_INTERVAL); + setTimeout(KEEP_ALIVE_INTERVAL); } uint32_t Server::reserveTunnelIp(uint32_t desiredIp) @@ -339,16 +339,16 @@ uint32_t Server::reserveTunnelIp(uint32_t desiredIp) } } - if (!ipAvailable) - return 0; + if (!ipAvailable) + return 0; - usedIps.insert(network + latestAssignedIpOffset); - return network + latestAssignedIpOffset; + usedIps.insert(network + latestAssignedIpOffset); + return network + latestAssignedIpOffset; } void Server::run() { - setTimeout(KEEP_ALIVE_INTERVAL); + setTimeout(KEEP_ALIVE_INTERVAL); - Worker::run(); + Worker::run(); } diff --git a/server.h b/server.h index 28f6f59..a4e0c2e 100644 --- a/server.h +++ b/server.h @@ -31,96 +31,96 @@ class Server : public Worker { public: - Server(int tunnelMtu, const char *deviceName, const char *passphrase, uint32_t network, bool answerEcho, uid_t uid, gid_t gid, int pollTimeout); - virtual ~Server(); + Server(int tunnelMtu, const char *deviceName, const char *passphrase, uint32_t network, bool answerEcho, uid_t uid, gid_t gid, int pollTimeout); + virtual ~Server(); // change some time: // struct __attribute__ ((__packed__)) ClientConnectData - struct ClientConnectData - { - uint8_t maxPolls; + struct ClientConnectData + { + uint8_t maxPolls; uint32_t desiredIp; - }; + }; - static const Worker::TunnelHeader::Magic magic; + static const Worker::TunnelHeader::Magic magic; protected: - struct Packet - { - int type; - std::vector data; - }; + struct Packet + { + int type; + std::vector data; + }; - struct ClientData - { - enum State - { - STATE_NEW, - STATE_CHALLENGE_SENT, - STATE_ESTABLISHED - }; + struct ClientData + { + enum State + { + STATE_NEW, + STATE_CHALLENGE_SENT, + STATE_ESTABLISHED + }; - struct EchoId - { - EchoId(uint16_t id, uint16_t seq) { this->id = id; this->seq = seq; } + struct EchoId + { + EchoId(uint16_t id, uint16_t seq) { this->id = id; this->seq = seq; } - uint16_t id; - uint16_t seq; - }; + uint16_t id; + uint16_t seq; + }; - uint32_t realIp; - uint32_t tunnelIp; + uint32_t realIp; + uint32_t tunnelIp; - std::queue pendingPackets; + std::queue pendingPackets; - int maxPolls; - std::queue pollIds; - Time lastActivity; + int maxPolls; + std::queue pollIds; + Time lastActivity; - State state; + State state; - Auth::Challenge challenge; - }; + Auth::Challenge challenge; + }; - typedef std::vector ClientList; - typedef std::map ClientIpMap; + typedef std::vector ClientList; + typedef std::map ClientIpMap; - virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq); - virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); - virtual void handleTimeout(); + virtual bool handleEchoData(const TunnelHeader &header, int dataLength, uint32_t realIp, bool reply, uint16_t id, uint16_t seq); + virtual void handleTunData(int dataLength, uint32_t sourceIp, uint32_t destIp); + virtual void handleTimeout(); - virtual void run(); + virtual void run(); - void serveTun(ClientData *client); + void serveTun(ClientData *client); - void handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId, uint16_t echoSeq); - void removeClient(ClientData *client); + void handleUnknownClient(const TunnelHeader &header, int dataLength, uint32_t realIp, uint16_t echoId, uint16_t echoSeq); + void removeClient(ClientData *client); - void sendChallenge(ClientData *client); - void checkChallenge(ClientData *client, int dataLength); - void sendReset(ClientData *client); + void sendChallenge(ClientData *client); + void checkChallenge(ClientData *client, int dataLength); + void sendReset(ClientData *client); - void sendEchoToClient(ClientData *client, int type, int dataLength); + void sendEchoToClient(ClientData *client, int type, int dataLength); - void pollReceived(ClientData *client, uint16_t echoId, uint16_t echoSeq); + void pollReceived(ClientData *client, uint16_t echoId, uint16_t echoSeq); - uint32_t reserveTunnelIp(uint32_t desiredIp); - void releaseTunnelIp(uint32_t tunnelIp); + uint32_t reserveTunnelIp(uint32_t desiredIp); + void releaseTunnelIp(uint32_t tunnelIp); - ClientData *getClientByTunnelIp(uint32_t ip); - ClientData *getClientByRealIp(uint32_t ip); + ClientData *getClientByTunnelIp(uint32_t ip); + ClientData *getClientByRealIp(uint32_t ip); - Auth auth; + Auth auth; - uint32_t network; - std::set usedIps; + uint32_t network; + std::set usedIps; uint32_t latestAssignedIpOffset; - Time pollTimeout; + Time pollTimeout; - ClientList clientList; - ClientIpMap clientRealIpMap; - ClientIpMap clientTunnelIpMap; + ClientList clientList; + ClientIpMap clientRealIpMap; + ClientIpMap clientTunnelIpMap; }; #endif diff --git a/time.cpp b/time.cpp index 96f4f24..919eeae 100644 --- a/time.cpp +++ b/time.cpp @@ -23,63 +23,63 @@ const Time Time::ZERO = Time(0); Time::Time(int ms) { - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; } Time Time::operator-(const Time &other) const { - Time result; - result.tv.tv_sec = tv.tv_sec - other.tv.tv_sec; - result.tv.tv_usec = tv.tv_usec - other.tv.tv_usec; - - if (result.tv.tv_usec < 0) - { - result.tv.tv_usec += 1000000; - result.tv.tv_sec -= 1; - } - - return result; + Time result; + result.tv.tv_sec = tv.tv_sec - other.tv.tv_sec; + result.tv.tv_usec = tv.tv_usec - other.tv.tv_usec; + + if (result.tv.tv_usec < 0) + { + result.tv.tv_usec += 1000000; + result.tv.tv_sec -= 1; + } + + return result; } Time Time::operator+(const Time &other) const { - Time result; - result.tv.tv_sec = tv.tv_sec + other.tv.tv_sec; - result.tv.tv_usec = tv.tv_usec + other.tv.tv_usec; - - if (result.tv.tv_usec >= 1000000) - { - result.tv.tv_usec -= 1000000; - result.tv.tv_sec += 1; - } - - return result; + Time result; + result.tv.tv_sec = tv.tv_sec + other.tv.tv_sec; + result.tv.tv_usec = tv.tv_usec + other.tv.tv_usec; + + if (result.tv.tv_usec >= 1000000) + { + result.tv.tv_usec -= 1000000; + result.tv.tv_sec += 1; + } + + return result; } bool Time::operator==(const Time &other) const { - return tv.tv_sec != other.tv.tv_sec ? false : tv.tv_usec == other.tv.tv_usec; + return tv.tv_sec != other.tv.tv_sec ? false : tv.tv_usec == other.tv.tv_usec; } bool Time::operator!=(const Time &other) const { - return tv.tv_sec != other.tv.tv_sec ? true : tv.tv_usec != other.tv.tv_usec; + return tv.tv_sec != other.tv.tv_sec ? true : tv.tv_usec != other.tv.tv_usec; } bool Time::operator<(const Time &other) const { - return tv.tv_sec != other.tv.tv_sec ? tv.tv_sec < other.tv.tv_sec : tv.tv_usec < other.tv.tv_usec; + return tv.tv_sec != other.tv.tv_sec ? tv.tv_sec < other.tv.tv_sec : tv.tv_usec < other.tv.tv_usec; } bool Time::operator>(const Time &other) const { - return tv.tv_sec != other.tv.tv_sec ? tv.tv_sec > other.tv.tv_sec : tv.tv_usec > other.tv.tv_usec; + return tv.tv_sec != other.tv.tv_sec ? tv.tv_sec > other.tv.tv_sec : tv.tv_usec > other.tv.tv_usec; } Time Time::now() { - Time result; - gettimeofday(&result.tv, 0); - return result; + Time result; + gettimeofday(&result.tv, 0); + return result; } diff --git a/time.h b/time.h index 75e8a1e..41bb415 100644 --- a/time.h +++ b/time.h @@ -25,24 +25,24 @@ class Time { public: - Time() { tv.tv_sec = 0; tv.tv_usec = 0; }; - Time(int ms); + Time() { tv.tv_sec = 0; tv.tv_usec = 0; }; + Time(int ms); - timeval &getTimeval() { return tv; } + timeval &getTimeval() { return tv; } - Time operator+(const Time &other) const; - Time operator-(const Time &other) const; + Time operator+(const Time &other) const; + Time operator-(const Time &other) const; - bool operator!=(const Time &other) const; - bool operator==(const Time &other) const; - bool operator<(const Time &other) const; - bool operator>(const Time &other) const; + bool operator!=(const Time &other) const; + bool operator==(const Time &other) const; + bool operator<(const Time &other) const; + bool operator>(const Time &other) const; - static Time now(); + static Time now(); - static const Time ZERO; + static const Time ZERO; protected: - timeval tv; + timeval tv; }; #endif diff --git a/tun.cpp b/tun.cpp index 2b47101..f546079 100644 --- a/tun.cpp +++ b/tun.cpp @@ -37,77 +37,77 @@ using namespace std; Tun::Tun(const char *device, int mtu) { - this->mtu = mtu; + this->mtu = mtu; - if (device != NULL) - { - strncpy(this->device, device, VTUN_DEV_LEN); - this->device[VTUN_DEV_LEN] = 0; - } - else - this->device[0] = 0; + if (device != NULL) + { + strncpy(this->device, device, VTUN_DEV_LEN); + this->device[VTUN_DEV_LEN] = 0; + } + else + this->device[0] = 0; - fd = tun_open(this->device); - if (fd == -1) - throw Exception("could not create tunnel device"); + fd = tun_open(this->device); + if (fd == -1) + throw Exception("could not create tunnel device"); - char cmdline[512]; - snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s mtu %u", this->device, mtu); - if (system(cmdline) != 0) - syslog(LOG_ERR, "could not set tun device mtu"); + char cmdline[512]; + snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s mtu %u", this->device, mtu); + if (system(cmdline) != 0) + syslog(LOG_ERR, "could not set tun device mtu"); } Tun::~Tun() { - tun_close(fd, device); + tun_close(fd, device); } void Tun::setIp(uint32_t ip, uint32_t destIp, bool includeSubnet) { - char cmdline[512]; - string ips = Utility::formatIp(ip); - string destIps = Utility::formatIp(destIp); + char cmdline[512]; + string ips = Utility::formatIp(ip); + string destIps = Utility::formatIp(destIp); #ifdef LINUX - snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s %s netmask 255.255.255.0", device, ips.c_str()); + snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s %s netmask 255.255.255.0", device, ips.c_str()); #else - snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s %s %s netmask 255.255.255.255", device, ips.c_str(), destIps.c_str()); + snprintf(cmdline, sizeof(cmdline), "/sbin/ifconfig %s %s %s netmask 255.255.255.255", device, ips.c_str(), destIps.c_str()); #endif - if (system(cmdline) != 0) - syslog(LOG_ERR, "could not set tun device ip address"); + if (system(cmdline) != 0) + syslog(LOG_ERR, "could not set tun device ip address"); #ifndef LINUX - if (includeSubnet) - { - snprintf(cmdline, sizeof(cmdline), "/sbin/route add %s/24 %s", destIps.c_str(), destIps.c_str()); - if (system(cmdline) != 0) - syslog(LOG_ERR, "could not add route"); - } + if (includeSubnet) + { + snprintf(cmdline, sizeof(cmdline), "/sbin/route add %s/24 %s", destIps.c_str(), destIps.c_str()); + if (system(cmdline) != 0) + syslog(LOG_ERR, "could not add route"); + } #endif } void Tun::write(const char *buffer, int length) { - if (tun_write(fd, (char *)buffer, length) == -1) - syslog(LOG_ERR, "error writing %d bytes to tun: %s", length, strerror(errno)); + if (tun_write(fd, (char *)buffer, length) == -1) + syslog(LOG_ERR, "error writing %d bytes to tun: %s", length, strerror(errno)); } int Tun::read(char *buffer) { - int length = tun_read(fd, buffer, mtu); - if (length == -1) - syslog(LOG_ERR, "error reading from tun: %s", strerror(errno)); - return length; + int length = tun_read(fd, buffer, mtu); + if (length == -1) + syslog(LOG_ERR, "error reading from tun: %s", strerror(errno)); + return length; } int Tun::read(char *buffer, uint32_t &sourceIp, uint32_t &destIp) { - int length = read(buffer); + int length = read(buffer); - IpHeader *header = (IpHeader *)buffer; - sourceIp = ntohl(header->ip_src.s_addr); - destIp = ntohl(header->ip_dst.s_addr); + IpHeader *header = (IpHeader *)buffer; + sourceIp = ntohl(header->ip_src.s_addr); + destIp = ntohl(header->ip_dst.s_addr); - return length; + return length; } diff --git a/tun.h b/tun.h index a6675d2..c6c382a 100644 --- a/tun.h +++ b/tun.h @@ -28,22 +28,22 @@ class Tun { public: - Tun(const char *device, int mtu); - ~Tun(); + Tun(const char *device, int mtu); + ~Tun(); - int getFd() { return fd; } + int getFd() { return fd; } - int read(char *buffer); - int read(char *buffer, uint32_t &sourceIp, uint32_t &destIp); + int read(char *buffer); + int read(char *buffer, uint32_t &sourceIp, uint32_t &destIp); - void write(const char *buffer, int length); + void write(const char *buffer, int length); - void setIp(uint32_t ip, uint32_t destIp, bool includeSubnet); + void setIp(uint32_t ip, uint32_t destIp, bool includeSubnet); protected: - char device[VTUN_DEV_LEN]; + char device[VTUN_DEV_LEN]; - int mtu; - int fd; + int mtu; + int fd; }; #endif diff --git a/tun_dev.h b/tun_dev.h index 087712b..667750d 100644 --- a/tun_dev.h +++ b/tun_dev.h @@ -20,8 +20,8 @@ extern "C" { - int tun_open(char *dev); - int tun_close(int fd, char *dev); - int tun_write(int fd, char *buf, int len); - int tun_read(int fd, char *buf, int len); + int tun_open(char *dev); + int tun_close(int fd, char *dev); + int tun_write(int fd, char *buf, int len); + int tun_read(int fd, char *buf, int len); } diff --git a/tun_dev_darwin_emu.c b/tun_dev_darwin_emu.c index 3061997..88a2b50 100644 --- a/tun_dev_darwin_emu.c +++ b/tun_dev_darwin_emu.c @@ -22,23 +22,23 @@ int tun_open(char *dev) { - int fd = tunemu_open(dev); - if (fd < 0) - syslog(LOG_ERR, tunemu_error); - return fd; + int fd = tunemu_open(dev); + if (fd < 0) + syslog(LOG_ERR, tunemu_error); + return fd; } int tun_close(int fd, char *dev) { - return tunemu_close(fd); + return tunemu_close(fd); } int tun_write(int fd, char *buf, int len) { - return tunemu_write(fd, buf, len); + return tunemu_write(fd, buf, len); } int tun_read(int fd, char *buf, int len) { - return tunemu_read(fd, buf, len); + return tunemu_read(fd, buf, len); } diff --git a/tun_dev_freebsd.c b/tun_dev_freebsd.c index 55f887f..b626591 100644 --- a/tun_dev_freebsd.c +++ b/tun_dev_freebsd.c @@ -60,9 +60,9 @@ int tun_open(char *dev) if( fd > -1 ){ i=0; /* Disable extended modes */ - ioctl(fd, TUNSLMODE, &i); + ioctl(fd, TUNSLMODE, &i); ioctl(fd, TUNSIFHEAD, &i); - } + } return fd; } diff --git a/tun_dev_linux.c b/tun_dev_linux.c index 538f3b0..daaeb82 100644 --- a/tun_dev_linux.c +++ b/tun_dev_linux.c @@ -62,11 +62,11 @@ static int tun_open_common0(char *dev, int istun) } else if (errno != ENOENT) err = errno; - else if (i) /* don't try all 256 devices */ + else if (i) /* don't try all 256 devices */ break; } if (err) - errno = err; + errno = err; return -1; } @@ -97,9 +97,9 @@ static int tun_open_common(char *dev, int istun) if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) { if (errno == EBADFD) { - /* Try old ioctl */ - if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0) - goto failed; + /* Try old ioctl */ + if (ioctl(fd, OTUNSETIFF, (void *) &ifr) < 0) + goto failed; } else goto failed; } diff --git a/tun_dev_svr4.c b/tun_dev_svr4.c index 4c32f6d..538aed4 100644 --- a/tun_dev_svr4.c +++ b/tun_dev_svr4.c @@ -74,7 +74,7 @@ int tun_open(char *dev) char *ptr; if( *dev ){ - ptr = dev; + ptr = dev; while( *ptr && !isdigit((int)*ptr) ) ptr++; ppa = atoi(ptr); } diff --git a/utility.cpp b/utility.cpp index edd3d03..9c16f6a 100644 --- a/utility.cpp +++ b/utility.cpp @@ -26,18 +26,18 @@ using namespace std; string Utility::formatIp(uint32_t ip) { - char buffer[16]; - sprintf(buffer, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); - return buffer; + char buffer[16]; + sprintf(buffer, "%d.%d.%d.%d", (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); + return buffer; } int Utility::rand() { - static bool init = false; - if (!init) - { - init = true; - srand(time(NULL)); - } - return ::rand(); + static bool init = false; + if (!init) + { + init = true; + srand(time(NULL)); + } + return ::rand(); } diff --git a/utility.h b/utility.h index d397040..fb4fe11 100644 --- a/utility.h +++ b/utility.h @@ -26,8 +26,8 @@ class Utility { public: - static std::string formatIp(uint32_t ip); - static int rand(); + static std::string formatIp(uint32_t ip); + static int rand(); }; #endif diff --git a/worker.cpp b/worker.cpp index d5be42b..a4b37f9 100644 --- a/worker.cpp +++ b/worker.cpp @@ -30,169 +30,169 @@ using namespace std; Worker::TunnelHeader::Magic::Magic(const char *magic) { - memset(data, 0, sizeof(data)); - strncpy(data, magic, sizeof(data)); + memset(data, 0, sizeof(data)); + strncpy(data, magic, sizeof(data)); } bool Worker::TunnelHeader::Magic::operator==(const Magic &other) const { - return memcmp(data, other.data, sizeof(data)) == 0; + return memcmp(data, other.data, sizeof(data)) == 0; } bool Worker::TunnelHeader::Magic::operator!=(const Magic &other) const { - return memcmp(data, other.data, sizeof(data)) != 0; + return memcmp(data, other.data, sizeof(data)) != 0; } Worker::Worker(int tunnelMtu, const char *deviceName, bool answerEcho, uid_t uid, gid_t gid) { - this->tunnelMtu = tunnelMtu; - this->answerEcho = answerEcho; - this->uid = uid; - this->gid = gid; - this->privilegesDropped = false; + this->tunnelMtu = tunnelMtu; + this->answerEcho = answerEcho; + this->uid = uid; + this->gid = gid; + this->privilegesDropped = false; - echo = NULL; - tun = NULL; + echo = NULL; + tun = NULL; - try - { - echo = new Echo(tunnelMtu + sizeof(TunnelHeader)); - tun = new Tun(deviceName, tunnelMtu); - } - catch (...) - { - delete echo; - delete tun; + try + { + echo = new Echo(tunnelMtu + sizeof(TunnelHeader)); + tun = new Tun(deviceName, tunnelMtu); + } + catch (...) + { + delete echo; + delete tun; - throw; - } + throw; + } } Worker::~Worker() { - delete echo; - delete tun; + delete echo; + delete tun; } void Worker::sendEcho(const TunnelHeader::Magic &magic, int type, int length, uint32_t realIp, bool reply, uint16_t id, uint16_t seq) { - if (length > payloadBufferSize()) - throw Exception("packet too big"); + if (length > payloadBufferSize()) + throw Exception("packet too big"); - TunnelHeader *header = (TunnelHeader *)echo->sendPayloadBuffer(); - header->magic = magic; - header->type = type; + TunnelHeader *header = (TunnelHeader *)echo->sendPayloadBuffer(); + header->magic = magic; + header->type = type; - DEBUG_ONLY(printf("sending: type %d, length %d, id %d, seq %d\n", type, length, id, seq)); + 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) { - tun->write(echoReceivePayloadBuffer(), length); + tun->write(echoReceivePayloadBuffer(), length); } void Worker::setTimeout(Time delta) { - nextTimeout = now + delta; + nextTimeout = now + delta; } void Worker::run() { - now = Time::now(); - alive = true; + now = Time::now(); + alive = true; - int maxFd = echo->getFd() > tun->getFd() ? echo->getFd() : tun->getFd(); + int maxFd = echo->getFd() > tun->getFd() ? echo->getFd() : tun->getFd(); - while (alive) - { - fd_set fs; - Time timeout; + while (alive) + { + fd_set fs; + Time timeout; - FD_ZERO(&fs); - FD_SET(tun->getFd(), &fs); - FD_SET(echo->getFd(), &fs); + FD_ZERO(&fs); + FD_SET(tun->getFd(), &fs); + FD_SET(echo->getFd(), &fs); - if (nextTimeout != Time::ZERO) - { - timeout = nextTimeout - now; - if (timeout < Time::ZERO) - timeout = Time::ZERO; - } + if (nextTimeout != Time::ZERO) + { + timeout = nextTimeout - now; + if (timeout < Time::ZERO) + timeout = Time::ZERO; + } - // wait for data or timeout - int result = select(maxFd + 1 , &fs, NULL, NULL, nextTimeout != Time::ZERO ? &timeout.getTimeval() : NULL); - if (result == -1) - throw Exception("select", true); - now = Time::now(); + // wait for data or timeout + int result = select(maxFd + 1 , &fs, NULL, NULL, nextTimeout != Time::ZERO ? &timeout.getTimeval() : NULL); + if (result == -1) + throw Exception("select", true); + now = Time::now(); - // timeout - if (result == 0) - { - nextTimeout = Time::ZERO; - handleTimeout(); - continue; - } + // timeout + if (result == 0) + { + nextTimeout = Time::ZERO; + handleTimeout(); + continue; + } - // icmp data - if (FD_ISSET(echo->getFd(), &fs)) - { - bool reply; - uint16_t id, seq; - uint32_t ip; + // icmp data + if (FD_ISSET(echo->getFd(), &fs)) + { + bool reply; + uint16_t id, seq; + uint32_t ip; - int dataLength = echo->receive(ip, reply, id, seq); - if (dataLength != -1) - { - bool valid = dataLength >= sizeof(TunnelHeader); + int dataLength = echo->receive(ip, reply, id, seq); + if (dataLength != -1) + { + bool valid = dataLength >= sizeof(TunnelHeader); - if (valid) - { - TunnelHeader *header = (TunnelHeader *)echo->receivePayloadBuffer(); + if (valid) + { + TunnelHeader *header = (TunnelHeader *)echo->receivePayloadBuffer(); - DEBUG_ONLY(printf("received: type %d, length %d, id %d, seq %d\n", header->type, dataLength - sizeof(TunnelHeader), id, seq)); + 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); - } + valid = handleEchoData(*header, dataLength - sizeof(TunnelHeader), ip, reply, id, seq); + } - if (!valid && !reply && answerEcho) - { - memcpy(echo->sendPayloadBuffer(), echo->receivePayloadBuffer(), dataLength); - echo->send(dataLength, ip, true, id, seq); - } - } - } + if (!valid && !reply && answerEcho) + { + memcpy(echo->sendPayloadBuffer(), echo->receivePayloadBuffer(), dataLength); + echo->send(dataLength, ip, true, id, seq); + } + } + } - // data from tun - if (FD_ISSET(tun->getFd(), &fs)) - { - uint32_t sourceIp, destIp; + // data from tun + if (FD_ISSET(tun->getFd(), &fs)) + { + uint32_t sourceIp, destIp; - int dataLength = tun->read(echoSendPayloadBuffer(), sourceIp, destIp); + int dataLength = tun->read(echoSendPayloadBuffer(), sourceIp, destIp); - if (dataLength == 0) - throw Exception("tunnel closed"); + if (dataLength == 0) + throw Exception("tunnel closed"); if (dataLength != -1) handleTunData(dataLength, sourceIp, destIp); - } - } + } + } } void Worker::dropPrivileges() { - if (uid <= 0 || privilegesDropped) - return; + if (uid <= 0 || privilegesDropped) + return; - syslog(LOG_INFO, "dropping privileges"); + syslog(LOG_INFO, "dropping privileges"); - if (setgid(gid) == -1) - throw Exception("setgid", true); + if (setgid(gid) == -1) + throw Exception("setgid", true); - if (setuid(uid) == -1) - throw Exception("setuid", true); + if (setuid(uid) == -1) + throw Exception("setuid", true); - privilegesDropped = true; + privilegesDropped = true; } diff --git a/worker.h b/worker.h index 7c87408..fba3040 100644 --- a/worker.h +++ b/worker.h @@ -29,76 +29,76 @@ class Worker { public: - Worker(int tunnelMtu, const char *deviceName, bool answerEcho, uid_t uid, gid_t gid); - virtual ~Worker(); + Worker(int tunnelMtu, const char *deviceName, bool answerEcho, uid_t uid, gid_t gid); + virtual ~Worker(); - virtual void run(); + virtual void run(); - static int headerSize() { return sizeof(TunnelHeader); } + static int headerSize() { return sizeof(TunnelHeader); } protected: - struct TunnelHeader - { - struct Magic - { - Magic() { } - Magic(const char *magic); + struct TunnelHeader + { + struct Magic + { + Magic() { } + Magic(const char *magic); - bool operator==(const Magic &other) const; - bool operator!=(const Magic &other) const; + bool operator==(const Magic &other) const; + bool operator!=(const Magic &other) const; - char data[4]; - }; + char data[4]; + }; - Magic magic; - uint8_t type; + Magic magic; + uint8_t type; - enum Type - { - TYPE_RESET_CONNECTION = 1, - TYPE_CONNECTION_REQUEST = 2, - TYPE_CHALLENGE = 3, - TYPE_CHALLENGE_RESPONSE = 4, - TYPE_CONNECTION_ACCEPT = 5, - TYPE_CHALLENGE_ERROR = 6, - TYPE_DATA = 7, - TYPE_POLL = 8, - TYPE_SERVER_FULL = 9 - }; - }; // size = 5 + enum Type + { + TYPE_RESET_CONNECTION = 1, + TYPE_CONNECTION_REQUEST = 2, + TYPE_CHALLENGE = 3, + TYPE_CHALLENGE_RESPONSE = 4, + TYPE_CONNECTION_ACCEPT = 5, + TYPE_CHALLENGE_ERROR = 6, + TYPE_DATA = 7, + TYPE_POLL = 8, + TYPE_SERVER_FULL = 9 + }; + }; // size = 5 - 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) { } // to echoSendPayloadBuffer - virtual void handleTimeout() { } + 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) { } // to echoSendPayloadBuffer + 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 sendToTun(int length); // from echoReceivePayloadBuffer + 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); // from echoReceivePayloadBuffer - void setTimeout(Time delta); + void setTimeout(Time delta); - char *echoSendPayloadBuffer() { return echo->sendPayloadBuffer() + sizeof(TunnelHeader); } - char *echoReceivePayloadBuffer() { return echo->receivePayloadBuffer() + 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(); - Echo *echo; - Tun *tun; - bool alive; - bool answerEcho; - int tunnelMtu; - int maxTunnelHeaderSize; - uid_t uid; - gid_t gid; + Echo *echo; + Tun *tun; + bool alive; + bool answerEcho; + int tunnelMtu; + int maxTunnelHeaderSize; + uid_t uid; + gid_t gid; - bool privilegesDropped; + bool privilegesDropped; - Time now; + Time now; private: - int readIcmpData(int *realIp, int *id, int *seq); + int readIcmpData(int *realIp, int *id, int *seq); - Time nextTimeout; + Time nextTimeout; }; #endif