### 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:
shutdown();
}
-bool DatagramSocket::init(short port)
+bool DatagramSocket::init(USHORT port)
{
myPort = port;
if ((socketnum = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
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;
}
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;
}
*/
}
-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
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;
+}
#include <string.h>
#include <errno.h>
+#include "defines.h"
#include "log.h"
#define MAXBUFLEN 2000
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;
--- /dev/null
+/*
+ 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);
+ }
+}
--- /dev/null
+/*
+ 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 <stdio.h>
+#include <signal.h>
+
+#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
+*/
udpr.shutdown();
bootpd.shutdown();
tftpd.shutdown();
+ mvprelay.shutdown();
log.log("Main", Log::INFO, "Stopped main server thread");
log.shutdown();
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())
#include "defines.h"
#include "udpreplier.h"
+#include "mvprelay.h"
#include "bootpd.h"
#include "tftpd.h"
#include "mvpclient.h"
UDPReplier udpr;
Bootpd bootpd;
Tftpd tftpd;
+ MVPRelay mvprelay;
int listeningSocket;
char* configDirExtra;
};
TftpClient::~TftpClient()
{
- log->log("TftpClient", Log::DEBUG, "Someone calls tftpclient::~tftpclient");
shutdown();
}
file = NULL;
}
- log->log("TftpClient", Log::DEBUG, "shutdown");
+ log->log("TftpClient", Log::DEBUG, "Shutdown");
return 1;
}
// 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();
}
}
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()))
{
{
// 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();
}
{
// end of file
state = 2;
- fclose(file);
- file = NULL;
}
else
{
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);
}
return 0;
}
- Log::getInstance()->log("UDP", Log::DEBUG, "UDP replier started");
+ Log::getInstance()->log("UDPReplier", Log::DEBUG, "UDP replier started");
return 1;
}
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));
}
}