From 78ae487dcf3f07187844c8435c76ff8b517e6088 Mon Sep 17 00:00:00 2001 From: Chris Tallon Date: Sat, 18 Feb 2006 18:47:06 +0000 Subject: [PATCH] Finished Bootp/TFTP server --- bootpd.c | 12 +- mvpserver.c | 53 +++++++- tftpclient.c | 192 ++++++----------------------- tftpclient.h | 3 +- tftpd.c | 15 ++- tftpd.h | 4 +- thread.c | 3 +- vomp-00-00-00-00-00-00.conf.sample | 5 + vomp.conf.sample | 12 +- 9 files changed, 130 insertions(+), 169 deletions(-) diff --git a/bootpd.c b/bootpd.c index 1786d5e..0a98fe0 100644 --- a/bootpd.c +++ b/bootpd.c @@ -222,7 +222,17 @@ void Bootpd::processRequest(UCHAR* data, int length) } // Set filename - strncpy((char*)&data[108], "/mvp/vomp-dongle", 127); + char* tftpFileName = config.getValueString("Boot", "TFTP file name"); + if (tftpFileName) + { + strncpy((char*)&data[108], tftpFileName, 127); + delete[] tftpFileName; + } + else + { + data[108] = '-'; + data[109] = '\0'; + } // set to reply data[0] = 2; diff --git a/mvpserver.c b/mvpserver.c index c1063fa..438405c 100644 --- a/mvpserver.c +++ b/mvpserver.c @@ -110,8 +110,22 @@ int MVPServer::run() return 0; } - // Start Bootpd - if (config.getValueString("General", "Bootp server")) + // Read config and start bootp and tftp as appropriate + + char* configString; + int bootpEnabled = 0; + int tftpEnabled = 0; + + configString = config.getValueString("General", "Bootp server enabled"); + if (configString && (!strcasecmp(configString, "yes"))) bootpEnabled = 1; + if (configString) delete[] configString; + + configString = config.getValueString("General", "TFTP server enabled"); + if (configString && (!strcasecmp(configString, "yes"))) tftpEnabled = 1; + if (configString) delete[] configString; + + + if (bootpEnabled) { if (!bootpd.run()) { @@ -125,10 +139,38 @@ int MVPServer::run() log.log("Main", Log::INFO, "Not starting Bootpd"); } - // Start Tftpd - if (config.getValueString("General", "TFTP server")) + if (tftpEnabled) { - if (!tftpd.run()) + char tftpPath[PATH_MAX]; +// snprintf(configFileName, PATH_MAX, "%s/vomp.conf", configDir); + + configString = config.getValueString("General", "TFTP directory"); + if (configString) + { + snprintf(tftpPath, PATH_MAX, "%s", configString); + + // this will never happen.. surely. + if ((strlen(tftpPath) + 2) >= PATH_MAX) + { + delete[] configString; + log.log("Main", Log::CRIT, "Could not understand TFTP directory from config"); + stop(); + return 0; + } + + // if there isn't a / at the end of the dir, add one + if (tftpPath[strlen(tftpPath) - 1] != '/') strcat(tftpPath, "/"); + + delete[] configString; + } + else + { + snprintf(tftpPath, PATH_MAX, "%s/", configDir); + } + + log.log("Main", Log::INFO, "TFTP path '%s'", tftpPath); + + if (!tftpd.run(tftpPath)) { log.log("Main", Log::CRIT, "Could not start TFTPd"); stop(); @@ -140,6 +182,7 @@ int MVPServer::run() log.log("Main", Log::INFO, "Not starting TFTPd"); } + // start thread here if (!threadStart()) { diff --git a/tftpclient.c b/tftpclient.c index 75d72df..8613339 100644 --- a/tftpclient.c +++ b/tftpclient.c @@ -20,9 +20,6 @@ #include "tftpclient.h" -void dump(unsigned char* data, USHORT size); -unsigned char dcc(UCHAR c); - TftpClient::TftpClient() { log = Log::getInstance(); @@ -33,6 +30,7 @@ TftpClient::TftpClient() TftpClient::~TftpClient() { + log->log("TftpClient", Log::DEBUG, "Someone calls tftpclient::~tftpclient"); shutdown(); } @@ -52,11 +50,13 @@ int TftpClient::shutdown() return 1; } -int TftpClient::run(char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length) +int TftpClient::run(char* tbaseDir, char* tpeerIP, USHORT tpeerPort, UCHAR* data, int length) { if (threadIsActive()) return 1; log->log("TftpClient", Log::DEBUG, "Client handler started"); + baseDir = tbaseDir; + strncpy(peerIP, tpeerIP, 16); peerPort = tpeerPort; @@ -87,7 +87,11 @@ void TftpClient::threadMethod() // process the first message received by the parent listener // the first incoming message is placed in buffer by above run method - if (!processMessage(buffer, bufferLength)) return; + if (!processMessage(buffer, bufferLength)) + { + log->log("TftpClient", Log::INFO, "threadMethod terminating connection"); + return; + } int retval; @@ -107,9 +111,9 @@ void TftpClient::threadMethod() { // 1s timer expired // see if we need to retransmit a data packet - if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 3))) + if (((state == 1) || (state == 2)) && (lastCom < (time(NULL) - 1))) { - log->log("TftpClient", Log::DEBUG, "Retransmitting buffer"); +// log->log("TftpClient", Log::DEBUG, "Retransmitting buffer"); transmitBuffer(); } @@ -134,8 +138,8 @@ void TftpClient::threadMethod() void TftpClient::threadPostStopCleanup() { - log->log("TftpClient", Log::DEBUG, "Deleting tftpclient"); - delete this; // careful +// log->log("TftpClient", Log::DEBUG, "Deleting tftpclient"); +// delete this; // careful } int TftpClient::processMessage(UCHAR* data, int length) @@ -162,7 +166,8 @@ int TftpClient::processMessage(UCHAR* data, int length) } case 3: // Data { - break; + log->log("TftpClient", Log::ERR, "Client sent a data packet!"); + return 0; // quit } case 4: // Ack { @@ -176,6 +181,7 @@ int TftpClient::processMessage(UCHAR* data, int length) default: { + log->log("TftpClient", Log::ERR, "Client TFTP protocol error"); return 0; } } @@ -225,7 +231,7 @@ int TftpClient::processAck(UCHAR* data, int length) // successful incoming packet lastCom = time(NULL); - log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock); +// log->log("TftpClient", Log::DEBUG, "Ack received for block %i - success", ackBlock); if (state == 1) // it wasn't the final block { @@ -240,15 +246,34 @@ int TftpClient::processAck(UCHAR* data, int length) } else { - log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected\n", ackBlock); +// log->log("TftpClient", Log::DEBUG, "Ack received for block %i - rejected, retransmitting block\n", ackBlock); + transmitBuffer(); } return 1; } -int TftpClient::openFile(char* filename) +int TftpClient::openFile(char* requestedFile) { - file = fopen("/opt/dvb/vomp-dongle-0.1.1", "r"); + char fileName[PATH_MAX]; + strcpy(fileName, requestedFile); + + for(UINT i = 0; i < strlen(fileName); i++) + { + if (fileName[i] == '/') + { + log->log("TftpClient", Log::ERR, "TFTP filename from client contained a path"); + return 0; + } + } + + char fileName2[PATH_MAX]; + snprintf(fileName2, PATH_MAX, "%s%s", baseDir, fileName); + + log->log("TftpClient", Log::INFO, "File: '%s'", fileName2); + + + file = fopen(fileName2, "r"); if (!file) return 0; return 1; } @@ -280,142 +305,5 @@ 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", blockNumber - 1); } - -void dump(unsigned char* data, USHORT size) -{ - printf("Size = %u\n", size); - - USHORT c = 0; - while(c < size) - { - if ((size - c) > 15) - { - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], data[c+15], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14]), dcc(data[c+15])); - c += 16; - } - else - { - switch (size - c) - { - case 15: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], data[c+14], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13]), dcc(data[c+14])); - c += 15; - break; - case 14: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], data[c+13], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12]), dcc(data[c+13])); - c += 14; - break; - case 13: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], data[c+11], data[c+12], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11]), dcc(data[c+12])); - c += 13; - break; - case 12: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], data[c+11], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10]), dcc(data[c+11])); - c += 12; - break; - case 11: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], data[c+10], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9]), dcc(data[c+10])); - c += 11; - break; - case 10: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], data[c+9], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8]), dcc(data[c+9])); - c += 10; - break; - case 9: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - data[c+8], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7]), - dcc(data[c+8])); - c += 9; - break; - case 8: - printf(" %02X %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], data[c+7], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6]), dcc(data[c+7])); - c += 8; - break; - case 7: - printf(" %02X %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], data[c+6], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5]), dcc(data[c+6])); - c += 7; - break; - case 6: - printf(" %02X %02X %02X %02X %02X %02X %c%c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], data[c+5], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4]), dcc(data[c+5])); - c += 6; - break; - case 5: - printf(" %02X %02X %02X %02X %02X %c%c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], data[c+4], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3]), dcc(data[c+4])); - c += 5; - break; - case 4: - printf(" %02X %02X %02X %02X %c%c%c%c\n", - data[c], data[c+1], data[c+2], data[c+3], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2]), dcc(data[c+3])); - c += 4; - break; - case 3: - printf(" %02X %02X %02X %c%c%c\n", - data[c], data[c+1], data[c+2], - dcc(data[c]), dcc(data[c+1]), dcc(data[c+2])); - c += 3; - break; - case 2: - printf(" %02X %02X %c%c\n", - data[c], data[c+1], - dcc(data[c]), dcc(data[c+1])); - c += 2; - break; - case 1: - printf(" %02X %c\n", - data[c], - dcc(data[c])); - c += 1; - break; - } - } - } -} - -unsigned char dcc(UCHAR c) -{ - if (isspace(c)) return ' '; - if (isprint(c)) return c; - return '.'; -} - diff --git a/tftpclient.h b/tftpclient.h index 2a1bdc6..5a80c2c 100644 --- a/tftpclient.h +++ b/tftpclient.h @@ -37,12 +37,13 @@ class TftpClient : public Thread TftpClient(); virtual ~TftpClient(); - int run(char* ip, USHORT port, UCHAR* data, int length); + int run(char* baseDir, char* ip, USHORT port, UCHAR* data, int length); int shutdown(); private: Log* log; DatagramSocket ds; + char* baseDir; char peerIP[17]; USHORT peerPort; UCHAR buffer[600]; diff --git a/tftpd.c b/tftpd.c index 564b2c5..38415e0 100644 --- a/tftpd.c +++ b/tftpd.c @@ -23,6 +23,7 @@ Tftpd::Tftpd() { log = Log::getInstance(); + baseDir = NULL; } Tftpd::~Tftpd() @@ -35,13 +36,16 @@ int Tftpd::shutdown() if (threadIsActive()) threadCancel(); ds.shutdown(); + if (baseDir) delete[] baseDir; + baseDir = NULL; + return 1; } -int Tftpd::run() +int Tftpd::run(char* tbaseDir) { if (threadIsActive()) return 1; - log->log("Tftpd", Log::DEBUG, "Starting Tftpd"); + log->log("Tftpd", Log::DEBUG, "Starting TFTPd"); if (!ds.init(16869)) { @@ -50,6 +54,9 @@ int Tftpd::run() return 0; } + baseDir = new char[strlen(tbaseDir) + 1]; + strcpy(baseDir, tbaseDir); + if (!threadStart()) { log->log("Tftpd", Log::DEBUG, "Thread start error"); @@ -57,7 +64,7 @@ int Tftpd::run() return 0; } - log->log("Tftpd", Log::DEBUG, "Bootp replier started"); + log->log("Tftpd", Log::DEBUG, "TFTP server started with base path '%s'", baseDir); return 1; } @@ -82,7 +89,7 @@ void Tftpd::threadMethod() else { TftpClient* t = new TftpClient(); - t->run(ds.getFromIPA(), ds.getFromPort(), (UCHAR*)ds.getData(), ds.getDataLength()); + t->run(baseDir, ds.getFromIPA(), ds.getFromPort(), (UCHAR*)ds.getData(), ds.getDataLength()); } } } diff --git a/tftpd.h b/tftpd.h index f866feb..50f2ede 100644 --- a/tftpd.h +++ b/tftpd.h @@ -38,7 +38,7 @@ class Tftpd : public Thread Tftpd(); virtual ~Tftpd(); - int run(); + int run(char* baseDir); int shutdown(); private: @@ -46,6 +46,8 @@ class Tftpd : public Thread DatagramSocket ds; Log* log; + + char* baseDir; }; #endif diff --git a/thread.c b/thread.c index 0eadacb..851c024 100755 --- a/thread.c +++ b/thread.c @@ -59,7 +59,6 @@ void Thread::threadStop() // Signal thread here in case it's waiting threadSignal(); pthread_join(pthread, NULL); - this->threadPostStopCleanup(); } void Thread::threadCancel() @@ -67,7 +66,7 @@ void Thread::threadCancel() threadActive = 0; pthread_cancel(pthread); pthread_join(pthread, NULL); - this->threadPostStopCleanup(); + this->threadPostStopCleanup(); // thread was cancelled, did not run post-stop above } void Thread::threadCheckExit() diff --git a/vomp-00-00-00-00-00-00.conf.sample b/vomp-00-00-00-00-00-00.conf.sample index 35d2fea..061c197 100644 --- a/vomp-00-00-00-00-00-00.conf.sample +++ b/vomp-00-00-00-00-00-00.conf.sample @@ -10,6 +10,11 @@ # Override IP = 1 +## A file name to send to the MVP. The MVP will then request +## this file from the TFTP server. Don't use a path here! + +# TFTP file name = vomp-dongle + [General] ## The client auto-detects whether to use PAL or NTSC. If you diff --git a/vomp.conf.sample b/vomp.conf.sample index c52e473..722c1af 100644 --- a/vomp.conf.sample +++ b/vomp.conf.sample @@ -8,17 +8,23 @@ ## can enter a name here that will appear on the ## server select list on the MVP -# Server name = MyServer +# Server name = My-Server ## Enable this to start the built in Bootp server ## Required to boot the MVP if you have not got a ## DHCP server that can tell the MVP its boot file ## name and server -# Bootp server = 1 +# Bootp server enabled = yes ## Enable this to start the built in TFTP server ## Required to boot the MVP if you have not got a ## TFTP server running elsewhere -# TFTP server = 1 +# TFTP server enabled = yes + +## Base directory for TFTP server +## If you leave this blank the plugin config +## path will be used - i.e. where this file is + +# TFTP directory = /tftpboot -- 2.39.5