From 182c351807c9ee93b4449c779f8af7efbfd429dd Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Thu, 4 Jan 2007 16:49:13 +0000 Subject: [PATCH] MVP Hx directory locator service added --- Makefile | 2 +- dsock.c | 80 ++++++++++++++++++++++++++-------- dsock.h | 24 +++++++---- mvprelay.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++ mvprelay.h | 72 +++++++++++++++++++++++++++++++ mvpserver.c | 12 ++++++ mvpserver.h | 2 + tftpclient.c | 27 ++++++++---- udpreplier.c | 4 +- 9 files changed, 303 insertions(+), 38 deletions(-) create mode 100755 mvprelay.c create mode 100755 mvprelay.h diff --git a/Makefile b/Makefile index 724d89d..d7d52c3 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' ### The object files (add further files here): OBJS = $(PLUGIN).o dsock.o mvpserver.o udpreplier.o bootpd.o tftpd.o mvpclient.o tcp.o \ - ringbuffer.o \ + ringbuffer.o mvprelay.o \ recplayer.o config.o log.o thread.o mvpreceiver.o tftpclient.o ### Implicit rules: diff --git a/dsock.c b/dsock.c index 885d927..4e7b8d9 100644 --- a/dsock.c +++ b/dsock.c @@ -32,7 +32,7 @@ DatagramSocket::~DatagramSocket() shutdown(); } -bool DatagramSocket::init(short port) +bool DatagramSocket::init(USHORT port) { myPort = port; if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) @@ -47,7 +47,7 @@ bool DatagramSocket::init(short port) memset(&(myAddr.sin_zero), 0, 8); // zero the rest of the struct if (bind(socketnum, (struct sockaddr *)&myAddr, addrlen) == -1) { - log->log("UDP", Log::CRIT, "Bind error"); + log->log("UDP", Log::CRIT, "Bind error %u", myPort); close(socketnum); return false; } @@ -116,7 +116,7 @@ unsigned char DatagramSocket::waitforMessage(unsigned char how) memset(&buf[mlength], 0, MAXBUFLEN - mlength); strcpy(fromIPA, inet_ntoa(theirAddr.sin_addr)); fromPort = ntohs(theirAddr.sin_port); -// log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength); + //log->log("UDP", Log::DEBUG, "%s:%i received length %i", fromIPA, fromPort, mlength); return 2; } @@ -126,19 +126,12 @@ unsigned char DatagramSocket::waitforMessage(unsigned char how) */ } -int DatagramSocket::getDataLength(void) const -{ - return mlength; -} - -char *DatagramSocket::getData(void) { return buf; } -char *DatagramSocket::getFromIPA(void) { return fromIPA; } -short DatagramSocket::getFromPort(void) const { return fromPort; } - -void DatagramSocket::send(char *ipa, short port, char *message, int length) +void DatagramSocket::send(char *ipa, USHORT port, char *message, int length) { int sentLength = 0; + //log->log("UDP", Log::DEBUG, "Send port %u", port); + theirAddr.sin_family = AF_INET; // host byte order theirAddr.sin_port = htons(port); // short, network byte order struct in_addr tad; // temp struct tad needed to pass to theirAddr.sin_addr @@ -149,19 +142,72 @@ void DatagramSocket::send(char *ipa, short port, char *message, int length) sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen); if (sentLength == length) { -// log->log("UDP", Log::DEBUG, "%s:%i sent length %i", ipa, port, length); + //log->log("UDP", Log::DEBUG, "%s:%u sent length %i", ipa, port, length); return; } - log->log("UDP", Log::DEBUG, "%s:%i send failed %i", ipa, port, length); + log->log("UDP", Log::DEBUG, "%s:%u send failed %i", ipa, port, length); sentLength = sendto(socketnum, message, length, 0, (struct sockaddr *)&theirAddr, addrlen); if (sentLength == length) { - log->log("UDP", Log::DEBUG, "%s:%i sent length %i 2nd try", ipa, port, length); + log->log("UDP", Log::DEBUG, "%s:%u sent length %i 2nd try", ipa, port, length); return; } - log->log("UDP", Log::DEBUG, "%s:%i send failed %i 2nd try", ipa, port, length); + log->log("UDP", Log::DEBUG, "%s:%u send failed %i 2nd try", ipa, port, length); +} + +ULONG DatagramSocket::getMyIP(ULONG targetIP) +{ + // More friendly interface to below, takes and returns IP in network order + + struct in_addr stargetIP; + stargetIP.s_addr = targetIP; + struct in_addr ret = myIPforIP(stargetIP); + return ret.s_addr; } +struct in_addr DatagramSocket::myIPforIP(struct in_addr targetIP) +{ + // This function takes a target IP on the network and returns the local IP + // that would be used to communicate with it. + // This function is static. + + struct in_addr fail; + fail.s_addr = 0; + + int zSocket; + if ((zSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) + { + Log::getInstance()->log("UDP", Log::CRIT, "Socket error"); + return fail; + } + + struct sockaddr_in zTarget; + zTarget.sin_family = AF_INET; + zTarget.sin_port = htons(3024); // arbitrary + zTarget.sin_addr.s_addr = targetIP.s_addr; + memset(&(zTarget.sin_zero), 0, 8); + + if (connect(zSocket, (struct sockaddr *)&zTarget, sizeof(struct sockaddr)) == -1) + { + Log::getInstance()->log("UDP", Log::CRIT, "Connect error"); + close(zSocket); + return fail; + } + + struct sockaddr_in zSource; + socklen_t zSourceLen = sizeof(struct sockaddr_in); + memset(&zSource, 0, zSourceLen); + + if (getsockname(zSocket, (struct sockaddr*)&zSource, &zSourceLen) == -1) + { + Log::getInstance()->log("UDP", Log::CRIT, "Getsockname error"); + close(zSocket); + return fail; + } + + close(zSocket); + return zSource.sin_addr; +} diff --git a/dsock.h b/dsock.h index 388e006..9ce3b9d 100644 --- a/dsock.h +++ b/dsock.h @@ -32,6 +32,7 @@ #include #include +#include "defines.h" #include "log.h" #define MAXBUFLEN 2000 @@ -43,26 +44,31 @@ class DatagramSocket public: DatagramSocket(); ~DatagramSocket(); - bool init(short); // port + bool init(USHORT); // port void shutdown(); unsigned char waitforMessage(unsigned char); // int =0-block =1-new wait =2-continue wait - int getDataLength(void) const; - char *getData(void); // returns a pointer to the data - char *getFromIPA(void); // returns a pointer to from IP address - short getFromPort(void) const; - void send(char *, short, char *, int); // send wants: IP Address ddn style, port, - // data, length of data + void send(char *, USHORT, char *, int); // send wants: IP Address ddn style, port, + // data, length of data + + char* getData(void) { return buf; } // returns a pointer to the data + char* getFromIPA(void) { return fromIPA; } // returns a pointer to from IP address + USHORT getFromPort(void) const { return fromPort; } // returns the sender port number + int getDataLength(void) const { return mlength; } // returns data length + + ULONG getMyIP(ULONG targetIP); + static struct in_addr myIPforIP(struct in_addr targetIP); + private: Log* log; int initted; int socketnum; // Socket descriptor - short myPort; // My port number + USHORT myPort; // My port number struct sockaddr_in myAddr; // My address struct sockaddr_in theirAddr; // User address socklen_t addrlen; // length of sockaddr struct char buf[MAXBUFLEN]; // main data buffer char fromIPA[20]; // from string (ip address) - short fromPort; // which port user sent on + USHORT fromPort; // which port user sent on int mlength; // length of message struct timeval tv; fd_set readfds; diff --git a/mvprelay.c b/mvprelay.c new file mode 100755 index 0000000..0e49f28 --- /dev/null +++ b/mvprelay.c @@ -0,0 +1,118 @@ +/* + Copyright 2007 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "mvprelay.h" + +MVPRelay::MVPRelay() +{ +} + +MVPRelay::~MVPRelay() +{ + shutdown(); +} + +int MVPRelay::shutdown() +{ + if (threadIsActive()) threadCancel(); + + return 1; +} + +int MVPRelay::run() +{ + if (threadIsActive()) return 1; + + if (!ds.init(16881)) + { + Log::getInstance()->log("MVPRelay", Log::CRIT, "Could not open UDP 16881"); + shutdown(); + return 0; + } + + if (!threadStart()) + { + shutdown(); + return 0; + } + + Log::getInstance()->log("MVPRelay", Log::DEBUG, "MVPRelay replier started"); + return 1; +} + +void MVPRelay::threadMethod() +{ + int retval; + while(1) + { + retval = ds.waitforMessage(0); + if (retval == 1) continue; + + Log::getInstance()->log("MVPRelay", Log::DEBUG, "MVPRelay request from %s", ds.getFromIPA()); + +// TCP::dump((UCHAR*)ds.getData(), ds.getDataLength()); + + UCHAR* in = (UCHAR*)ds.getData(); + + // Check incoming packet magic number + + ULONG inMagic = ntohl(*(ULONG*)&in[4]); + if (inMagic != 0xbabefafe) + { + Log::getInstance()->log("MVPRelay", Log::DEBUG, "inMagic not correct"); + continue; + } + + // Get peer info + USHORT peerPort = ntohs(*(USHORT*)&in[20]); + + // Get my IP for this connection + ULONG myIP = ds.getMyIP(*(ULONG*)&in[16]); + Log::getInstance()->log("MVPRelay", Log::DEBUG, "Sending my IP as %x", ntohl(myIP)); + + // Required return parameters: + // -Seq number + // -Magic number + // -Client IP & port + // -First server IP + + // Construct reply packet + + UCHAR out[52]; + memset(out, 0, 52); + + // Copy sequence number + memcpy(out, in, 4); + + // Return magic number is 0xfafebabe + *(ULONG*)&out[4] = htonl(0xfafebabe); + + // Copy client IP and port to reply + memcpy(&out[16], &in[16], 6); + + // Insert server address + *(ULONG*)&out[24] = myIP; + + // Send it + ds.send(ds.getFromIPA(), peerPort, (char*)out, 52); + +// TCP::dump(out, 52); + } +} diff --git a/mvprelay.h b/mvprelay.h new file mode 100755 index 0000000..fd51bfc --- /dev/null +++ b/mvprelay.h @@ -0,0 +1,72 @@ +/* + Copyright 2007 Chris Tallon + + This file is part of VOMP. + + VOMP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + VOMP is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with VOMP; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MVPRELAY_H +#define MVPRELAY_H + +#include +#include + +#include "log.h" +#include "dsock.h" +#include "thread.h" + +#include "tcp.h" // temp + +class MVPRelay : public Thread +{ + public: + MVPRelay(); + virtual ~MVPRelay(); + + int run(); + int shutdown(); + + private: + void threadMethod(); + + DatagramSocket ds; +}; + +#endif + +/* + +Protocol information (from the original mvprelay.c) + +0 4 bytes: sequence +4 4 bytes: magic number = 0xBABEFAFE +8 6 bytes: client MAC address +14 2 bytes: reserved = 0 +16 4 bytes: client IP address +20 2 bytes: client port number +22 2 bytes: reserved = 0 +24 4 bytes: GUI IP address +28 2 bytes: GUI port number +30 2 bytes: reserved = 0 +32 4 bytes: Con IP address ??? +36 2 bytes: Con port number ??? +38 6 bytes: reserved = 0 ??? +44 4 bytes: Server IP address ??? +48 2 bytes: Server port number ??? +50 2 bytes: reserved = 0 ??? + +Total: 52 bytes +*/ diff --git a/mvpserver.c b/mvpserver.c index 29cecd8..15c0f2c 100644 --- a/mvpserver.c +++ b/mvpserver.c @@ -37,6 +37,7 @@ int MVPServer::stop() udpr.shutdown(); bootpd.shutdown(); tftpd.shutdown(); + mvprelay.shutdown(); log.log("Main", Log::INFO, "Stopped main server thread"); log.shutdown(); @@ -185,6 +186,17 @@ int MVPServer::run(char* tconfigDirExtra) log.log("Main", Log::INFO, "Not starting TFTPd"); } + // Start mvprelay thread + if (!mvprelay.run()) + { + log.log("Main", Log::CRIT, "Could not start MVPRelay"); + stop(); + return 0; + } + else + { + log.log("Main", Log::INFO, "MVPRelay started"); + } // start thread here if (!threadStart()) diff --git a/mvpserver.h b/mvpserver.h index 48598d7..5236f35 100644 --- a/mvpserver.h +++ b/mvpserver.h @@ -27,6 +27,7 @@ #include "defines.h" #include "udpreplier.h" +#include "mvprelay.h" #include "bootpd.h" #include "tftpd.h" #include "mvpclient.h" @@ -50,6 +51,7 @@ class MVPServer : public Thread UDPReplier udpr; Bootpd bootpd; Tftpd tftpd; + MVPRelay mvprelay; int listeningSocket; char* configDirExtra; }; diff --git a/tftpclient.c b/tftpclient.c index 8613339..9a6cb52 100644 --- a/tftpclient.c +++ b/tftpclient.c @@ -30,7 +30,6 @@ TftpClient::TftpClient() TftpClient::~TftpClient() { - log->log("TftpClient", Log::DEBUG, "Someone calls tftpclient::~tftpclient"); shutdown(); } @@ -45,7 +44,7 @@ int TftpClient::shutdown() file = NULL; } - log->log("TftpClient", Log::DEBUG, "shutdown"); + log->log("TftpClient", Log::DEBUG, "Shutdown"); return 1; } @@ -113,7 +112,7 @@ void TftpClient::threadMethod() // see if we need to retransmit a data packet if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 1))) { -// log->log("TftpClient", Log::DEBUG, "Retransmitting buffer"); + log->log("TftpClient", Log::DEBUG, "Retransmitting buffer"); transmitBuffer(); } @@ -121,8 +120,17 @@ void TftpClient::threadMethod() } else { - if (strcmp(ds.getFromIPA(), peerIP)) continue; // not from my client's IP - if (ds.getFromPort() != peerPort) continue; // not from my client's port + if (strcmp(ds.getFromIPA(), peerIP)) + { + log->log("TftpClient", Log::ERR, "Not my client IP"); + continue; // not from my client's IP + } + + if (ds.getFromPort() != peerPort) + { + log->log("TftpClient", Log::ERR, "Not my client port %i %u", ds.getFromPort(), peerPort); + continue; // not from my client's port + } if (!processMessage((UCHAR*)ds.getData(), ds.getDataLength())) { @@ -241,12 +249,14 @@ int TftpClient::processAck(UCHAR* data, int length) { // state == 2, end of transfer. kill connection log->log("TftpClient", Log::INFO, "File transfer finished"); + fclose(file); + file = NULL; return 0; } } else { -// log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock); + log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock); transmitBuffer(); } @@ -288,8 +298,6 @@ int TftpClient::sendBlock() { // end of file state = 2; - fclose(file); - file = NULL; } else { @@ -303,7 +311,8 @@ int TftpClient::sendBlock() void TftpClient::transmitBuffer() { + ds.send(peerIP, peerPort, (char*)buffer, bufferLength); // dump(buffer, bufferLength); -// log->log("TftpClient", Log::DEBUG, "Sent block number %i", blockNumber - 1); +// log->log("TftpClient", Log::DEBUG, "Sent block number %i to port %u", blockNumber - 1, peerPort); } diff --git a/udpreplier.c b/udpreplier.c index c4b7436..79ff4b3 100644 --- a/udpreplier.c +++ b/udpreplier.c @@ -58,7 +58,7 @@ int UDPReplier::run(char* tserverName) return 0; } - Log::getInstance()->log("UDP", Log::DEBUG, "UDP replier started"); + Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP replier started"); return 1; } @@ -72,7 +72,7 @@ void UDPReplier::threadMethod() if (!strcmp(ds.getData(), "VOMP")) { - Log::getInstance()->log("UDP", Log::DEBUG, "UDP request from %s", ds.getFromIPA()); + Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP request from %s", ds.getFromIPA()); ds.send(ds.getFromIPA(), 3024, serverName, strlen(serverName)); } } -- 2.39.5