A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Apr 02 19:08:25 2020 +0000
Revision:
167:3ba4e3c49631
Parent:
160:6a1d1d368f80
Child:
170:96c637dc3f52
Modified resolution cache ajaxs to include the index

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 115:5c003909bcf3 1 #include <stdint.h>
andrewboyson 115:5c003909bcf3 2 #include <stdbool.h>
andrewboyson 115:5c003909bcf3 3
andrewboyson 115:5c003909bcf3 4 #include "log.h"
andrewboyson 115:5c003909bcf3 5 #include "net.h"
andrewboyson 115:5c003909bcf3 6 #include "action.h"
andrewboyson 115:5c003909bcf3 7 #include "udp.h"
andrewboyson 115:5c003909bcf3 8 #include "dns.h"
andrewboyson 115:5c003909bcf3 9 #include "tftp.h"
andrewboyson 115:5c003909bcf3 10 #include "mstimer.h"
andrewboyson 116:60521b29e4c9 11 #include "resolve.h"
andrewboyson 128:79052cb4a41c 12 #include "dnslabel.h"
andrewboyson 115:5c003909bcf3 13
andrewboyson 115:5c003909bcf3 14 bool TftpTrace = false;
andrewboyson 115:5c003909bcf3 15
andrewboyson 116:60521b29e4c9 16 #define WRITE_TIMEOUT_MS 6000 //Make this longer than the resolve time which is up to 3 seconds
andrewboyson 115:5c003909bcf3 17
andrewboyson 115:5c003909bcf3 18 #define TFTP_RRQ 1
andrewboyson 115:5c003909bcf3 19 #define TFTP_WRQ 2
andrewboyson 115:5c003909bcf3 20 #define TFTP_DATA 3
andrewboyson 115:5c003909bcf3 21 #define TFTP_ACK 4
andrewboyson 115:5c003909bcf3 22 #define TFTP_ERROR 5
andrewboyson 115:5c003909bcf3 23
andrewboyson 115:5c003909bcf3 24 static void logOp(char* p)
andrewboyson 115:5c003909bcf3 25 {
andrewboyson 115:5c003909bcf3 26 if (*p)
andrewboyson 115:5c003909bcf3 27 {
andrewboyson 160:6a1d1d368f80 28 LogF("Unknown op code %02x", *p); LogF("%02x", *++p);
andrewboyson 115:5c003909bcf3 29 return;
andrewboyson 115:5c003909bcf3 30 }
andrewboyson 115:5c003909bcf3 31 p++;
andrewboyson 115:5c003909bcf3 32 switch (*p)
andrewboyson 115:5c003909bcf3 33 {
andrewboyson 115:5c003909bcf3 34 case TFTP_RRQ: Log ("RRQ") ; break;
andrewboyson 115:5c003909bcf3 35 case TFTP_WRQ: Log ("WRQ") ; break;
andrewboyson 115:5c003909bcf3 36 case TFTP_DATA: Log ("DATA") ; break;
andrewboyson 115:5c003909bcf3 37 case TFTP_ACK: Log ("ACK") ; break;
andrewboyson 115:5c003909bcf3 38 case TFTP_ERROR: Log ("ERROR") ; break;
andrewboyson 115:5c003909bcf3 39 default: LogF("Unknown op code 00%02x", *p); break;
andrewboyson 115:5c003909bcf3 40 }
andrewboyson 115:5c003909bcf3 41 }
andrewboyson 115:5c003909bcf3 42
andrewboyson 115:5c003909bcf3 43 static void logError(char* p)
andrewboyson 115:5c003909bcf3 44 {
andrewboyson 115:5c003909bcf3 45 if (*p)
andrewboyson 115:5c003909bcf3 46 {
andrewboyson 160:6a1d1d368f80 47 LogF("Unknown error code %02x", *p);
andrewboyson 160:6a1d1d368f80 48 LogF("%02x", *++p);
andrewboyson 115:5c003909bcf3 49 return;
andrewboyson 115:5c003909bcf3 50 }
andrewboyson 115:5c003909bcf3 51 p++;
andrewboyson 115:5c003909bcf3 52 switch (*p)
andrewboyson 115:5c003909bcf3 53 {
andrewboyson 115:5c003909bcf3 54 case 0: Log ("Not defined, see error message." ); break;
andrewboyson 115:5c003909bcf3 55 case 1: Log ("File not found." ); break;
andrewboyson 115:5c003909bcf3 56 case 2: Log ("Access violation." ); break;
andrewboyson 115:5c003909bcf3 57 case 3: Log ("Disk full or allocation exceeded."); break;
andrewboyson 115:5c003909bcf3 58 case 4: Log ("Illegal TFTP operation." ); break;
andrewboyson 115:5c003909bcf3 59 case 5: Log ("Unknown transfer ID." ); break;
andrewboyson 115:5c003909bcf3 60 case 6: Log ("File already exists." ); break;
andrewboyson 115:5c003909bcf3 61 case 7: Log ("No such user." ); break;
andrewboyson 115:5c003909bcf3 62 default: LogF("Unknown error code 00%02x", *p ); break;
andrewboyson 115:5c003909bcf3 63 }
andrewboyson 115:5c003909bcf3 64 }
andrewboyson 115:5c003909bcf3 65 bool TftpSendRequestsViaIp4 = false;
andrewboyson 115:5c003909bcf3 66 uint32_t TftpServerIp4;
andrewboyson 115:5c003909bcf3 67 char TftpServerIp6[16];
andrewboyson 115:5c003909bcf3 68 int TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 115:5c003909bcf3 69 char TftpServerName[DNS_MAX_LABEL_LENGTH+1];
andrewboyson 115:5c003909bcf3 70 char TftpFileName [DNS_MAX_LABEL_LENGTH+1];
andrewboyson 115:5c003909bcf3 71
andrewboyson 115:5c003909bcf3 72 int (*TftpGetNextByteFunction)();
andrewboyson 115:5c003909bcf3 73
andrewboyson 115:5c003909bcf3 74 static void logHeader(int size, char* p)
andrewboyson 115:5c003909bcf3 75 {
andrewboyson 115:5c003909bcf3 76 if (NetTraceVerbose)
andrewboyson 115:5c003909bcf3 77 {
andrewboyson 115:5c003909bcf3 78 Log ("TFTP header\r\n");
andrewboyson 115:5c003909bcf3 79 Log (" Op code "); logOp(p); Log("\r\n");
andrewboyson 115:5c003909bcf3 80 Log (" Size "); LogF("%d", size); Log("\r\n");
andrewboyson 115:5c003909bcf3 81 }
andrewboyson 115:5c003909bcf3 82 else
andrewboyson 115:5c003909bcf3 83 {
andrewboyson 115:5c003909bcf3 84 Log ("TFTP header");
andrewboyson 115:5c003909bcf3 85 Log (": Op "); logOp(p);
andrewboyson 115:5c003909bcf3 86 LogF(", %d bytes", size);
andrewboyson 115:5c003909bcf3 87 Log ("\r\n");
andrewboyson 115:5c003909bcf3 88 }
andrewboyson 115:5c003909bcf3 89 }
andrewboyson 115:5c003909bcf3 90 static int sendBlock(uint16_t block, int* pSize, char* pHeader)
andrewboyson 115:5c003909bcf3 91 {
andrewboyson 115:5c003909bcf3 92 /*2 bytes 2 bytes n bytes
andrewboyson 115:5c003909bcf3 93 ----------------------------------
andrewboyson 115:5c003909bcf3 94 | Opcode | Block # | Data |
andrewboyson 115:5c003909bcf3 95 ---------------------------------- */
andrewboyson 115:5c003909bcf3 96 char* p = pHeader;
andrewboyson 115:5c003909bcf3 97 *p++ = 0;
andrewboyson 115:5c003909bcf3 98 *p++ = TFTP_DATA;
andrewboyson 115:5c003909bcf3 99 *p++ = block >> 8;
andrewboyson 115:5c003909bcf3 100 *p++ = block & 0xFF;
andrewboyson 115:5c003909bcf3 101
andrewboyson 115:5c003909bcf3 102 int len = 0;
andrewboyson 115:5c003909bcf3 103 while (len < 512)
andrewboyson 115:5c003909bcf3 104 {
andrewboyson 115:5c003909bcf3 105 int c = TftpGetNextByteFunction();
andrewboyson 115:5c003909bcf3 106 if (c == -1) break;
andrewboyson 115:5c003909bcf3 107 *p++ = c;
andrewboyson 115:5c003909bcf3 108 len++;
andrewboyson 115:5c003909bcf3 109 }
andrewboyson 115:5c003909bcf3 110 if (len < 512) TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 115:5c003909bcf3 111 *pSize = p - pHeader;
andrewboyson 115:5c003909bcf3 112 return UNICAST_TFTP;
andrewboyson 115:5c003909bcf3 113 }
andrewboyson 115:5c003909bcf3 114 static void handleError(char* p)
andrewboyson 115:5c003909bcf3 115 {
andrewboyson 115:5c003909bcf3 116 /*2 bytes 2 bytes string 1 byte
andrewboyson 115:5c003909bcf3 117 -----------------------------------------
andrewboyson 115:5c003909bcf3 118 | ERROR | ErrorCode | ErrMsg | 0 |
andrewboyson 115:5c003909bcf3 119 ----------------------------------------- */
andrewboyson 115:5c003909bcf3 120 p += 2; //Skip the op code which we already know
andrewboyson 115:5c003909bcf3 121 if (NetTraceNewLine) Log("\r\n");
andrewboyson 115:5c003909bcf3 122 LogTime("TFTP error - ");
andrewboyson 115:5c003909bcf3 123 logError(p); p += 2;
andrewboyson 115:5c003909bcf3 124 Log(p);
andrewboyson 115:5c003909bcf3 125 Log("\r\n");
andrewboyson 115:5c003909bcf3 126 TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 115:5c003909bcf3 127 }
andrewboyson 115:5c003909bcf3 128 static int handleAck(char* pHeaderRx, int* pSizeTx, char* pHeaderTx)
andrewboyson 115:5c003909bcf3 129 {
andrewboyson 115:5c003909bcf3 130 /* 2 bytes 2 bytes
andrewboyson 115:5c003909bcf3 131 -----------------------
andrewboyson 115:5c003909bcf3 132 | ACK | Block # |
andrewboyson 115:5c003909bcf3 133 ----------------------- */
andrewboyson 115:5c003909bcf3 134 char* p = pHeaderRx;
andrewboyson 115:5c003909bcf3 135 p += 2; //Skip the op code which we already know
andrewboyson 115:5c003909bcf3 136 uint16_t block = *p++;
andrewboyson 115:5c003909bcf3 137 block <<= 8;
andrewboyson 115:5c003909bcf3 138 block += *p++;
andrewboyson 115:5c003909bcf3 139
andrewboyson 115:5c003909bcf3 140 return sendBlock(block + 1, pSizeTx, pHeaderTx);
andrewboyson 115:5c003909bcf3 141 }
andrewboyson 115:5c003909bcf3 142 static int sendRequest(int* pSize, char* pHeader)
andrewboyson 115:5c003909bcf3 143 {
andrewboyson 115:5c003909bcf3 144 /*2 bytes string 1 byte string 1 byte
andrewboyson 115:5c003909bcf3 145 -----------------------------------------------
andrewboyson 115:5c003909bcf3 146 | WRQ | Filename | 0 | Mode | 0 |
andrewboyson 115:5c003909bcf3 147 ----------------------------------------------- */
andrewboyson 115:5c003909bcf3 148 char* p = pHeader;
andrewboyson 115:5c003909bcf3 149 *p++ = 0;
andrewboyson 115:5c003909bcf3 150 *p++ = TFTP_WRQ;
andrewboyson 115:5c003909bcf3 151 char* pName = TftpFileName;
andrewboyson 115:5c003909bcf3 152 while (*pName) *p++ = *pName++;
andrewboyson 115:5c003909bcf3 153 *p++ = 0;
andrewboyson 115:5c003909bcf3 154 const char* pMode = "octet";
andrewboyson 115:5c003909bcf3 155 while (*pMode) *p++ = *pMode++;
andrewboyson 115:5c003909bcf3 156 *p++ = 0;
andrewboyson 115:5c003909bcf3 157 *pSize = p - pHeader;
andrewboyson 115:5c003909bcf3 158 return UNICAST_TFTP;
andrewboyson 115:5c003909bcf3 159 }
andrewboyson 115:5c003909bcf3 160 int TftpHandlePacketReceived(void (*traceback)(void), int sizeRx, void * pPacketRx, int* pSizeTx, void* pPacketTx)
andrewboyson 115:5c003909bcf3 161 {
andrewboyson 115:5c003909bcf3 162 char* pHeaderRx = (char*)pPacketRx;
andrewboyson 115:5c003909bcf3 163 char* pHeaderTx = (char*)pPacketTx;
andrewboyson 115:5c003909bcf3 164
andrewboyson 115:5c003909bcf3 165 char* p = pHeaderRx;
andrewboyson 115:5c003909bcf3 166
andrewboyson 115:5c003909bcf3 167 if (*p)
andrewboyson 115:5c003909bcf3 168 {
andrewboyson 115:5c003909bcf3 169 LogTimeF("Expected high byte of op code to be zero not %u\r\n", *p);
andrewboyson 115:5c003909bcf3 170 return DO_NOTHING;
andrewboyson 115:5c003909bcf3 171 }
andrewboyson 115:5c003909bcf3 172 if (TftpTrace)
andrewboyson 115:5c003909bcf3 173 {
andrewboyson 115:5c003909bcf3 174 if (NetTraceNewLine) Log("\r\n");
andrewboyson 115:5c003909bcf3 175 LogTimeF("TFTP received packet\r\n");
andrewboyson 115:5c003909bcf3 176 if (NetTraceStack) traceback();
andrewboyson 115:5c003909bcf3 177 logHeader(sizeRx, pHeaderRx);
andrewboyson 115:5c003909bcf3 178 }
andrewboyson 115:5c003909bcf3 179 p++;
andrewboyson 115:5c003909bcf3 180 int dest = DO_NOTHING;
andrewboyson 115:5c003909bcf3 181 switch (*p)
andrewboyson 115:5c003909bcf3 182 {
andrewboyson 115:5c003909bcf3 183 case TFTP_ACK:
andrewboyson 115:5c003909bcf3 184 if (TftpWriteStatus == TFTP_WRITE_STATUS_NONE) return DO_NOTHING;
andrewboyson 115:5c003909bcf3 185 dest = handleAck(pHeaderRx, pSizeTx, pHeaderTx);
andrewboyson 115:5c003909bcf3 186 break;
andrewboyson 115:5c003909bcf3 187 case TFTP_ERROR:
andrewboyson 115:5c003909bcf3 188 handleError(pHeaderRx);
andrewboyson 115:5c003909bcf3 189 return DO_NOTHING;
andrewboyson 115:5c003909bcf3 190 default:
andrewboyson 115:5c003909bcf3 191 LogTimeF("\r\nTFTP packet unknown mode %d\r\n", *p);
andrewboyson 115:5c003909bcf3 192 return DO_NOTHING;
andrewboyson 115:5c003909bcf3 193 }
andrewboyson 115:5c003909bcf3 194
andrewboyson 115:5c003909bcf3 195 if (TftpTrace) logHeader(*pSizeTx, pHeaderTx);
andrewboyson 115:5c003909bcf3 196
andrewboyson 115:5c003909bcf3 197 return ActionMakeFromDestAndTrace(dest, TftpTrace && NetTraceStack);
andrewboyson 115:5c003909bcf3 198 }
andrewboyson 115:5c003909bcf3 199 static bool isTimedOut()
andrewboyson 115:5c003909bcf3 200 {
andrewboyson 115:5c003909bcf3 201 static uint32_t writeStartMs = 0;
andrewboyson 115:5c003909bcf3 202
andrewboyson 115:5c003909bcf3 203 if (TftpWriteStatus == TFTP_WRITE_STATUS_NONE) writeStartMs = MsTimerCount;
andrewboyson 115:5c003909bcf3 204
andrewboyson 133:a37eb35a03f1 205 if (MsTimerRelative(writeStartMs, WRITE_TIMEOUT_MS))
andrewboyson 115:5c003909bcf3 206 {
andrewboyson 115:5c003909bcf3 207 LogTime("TFTP - write operation timed out so reset\r\n");
andrewboyson 115:5c003909bcf3 208 writeStartMs = MsTimerCount;
andrewboyson 115:5c003909bcf3 209 return true;
andrewboyson 115:5c003909bcf3 210 }
andrewboyson 115:5c003909bcf3 211 return false;
andrewboyson 115:5c003909bcf3 212 }
andrewboyson 115:5c003909bcf3 213 static bool isOkToGo()
andrewboyson 115:5c003909bcf3 214 {
andrewboyson 115:5c003909bcf3 215 if (!TftpServerName[0])
andrewboyson 115:5c003909bcf3 216 {
andrewboyson 115:5c003909bcf3 217 LogTimeF("TftpPollForRequestToSend - A request to send a client message has been made but no server name has been specified\r\n");
andrewboyson 115:5c003909bcf3 218 return false;
andrewboyson 115:5c003909bcf3 219 }
andrewboyson 115:5c003909bcf3 220
andrewboyson 115:5c003909bcf3 221 if (!TftpGetNextByteFunction)
andrewboyson 115:5c003909bcf3 222 {
andrewboyson 115:5c003909bcf3 223 LogTimeF("TftpPollForRequestToSend - A request to send a client message has been made but TFTP has not been plumbed into a file stream\r\n");
andrewboyson 115:5c003909bcf3 224 return false;
andrewboyson 115:5c003909bcf3 225 }
andrewboyson 115:5c003909bcf3 226 return true;
andrewboyson 115:5c003909bcf3 227 }
andrewboyson 115:5c003909bcf3 228 int TftpPollForPacketToSend(int type, void* pPacket, int* pSize)
andrewboyson 115:5c003909bcf3 229 {
andrewboyson 116:60521b29e4c9 230 if (isTimedOut() ) { TftpWriteStatus = TFTP_WRITE_STATUS_NONE; return DO_NOTHING; }
andrewboyson 116:60521b29e4c9 231 if (TftpWriteStatus != TFTP_WRITE_STATUS_REQUEST ) { return DO_NOTHING; }
andrewboyson 116:60521b29e4c9 232 if (!isOkToGo() ) { TftpWriteStatus = TFTP_WRITE_STATUS_NONE; return DO_NOTHING; }
andrewboyson 116:60521b29e4c9 233 if (!Resolve(TftpServerName, type, &TftpServerIp4, TftpServerIp6)) { return DO_NOTHING; }
andrewboyson 115:5c003909bcf3 234
andrewboyson 115:5c003909bcf3 235 //Have IP and MAC so send request
andrewboyson 115:5c003909bcf3 236 TftpWriteStatus = TFTP_WRITE_STATUS_IN_PROGRESS;
andrewboyson 115:5c003909bcf3 237 int dest = sendRequest(pSize, (char*)pPacket);
andrewboyson 115:5c003909bcf3 238 if (TftpTrace)
andrewboyson 115:5c003909bcf3 239 {
andrewboyson 115:5c003909bcf3 240 if (NetTraceNewLine) Log("\r\n");
andrewboyson 115:5c003909bcf3 241 LogTimeF("TFTP Sending request\r\n");
andrewboyson 115:5c003909bcf3 242 logHeader(*pSize, (char*)pPacket);
andrewboyson 115:5c003909bcf3 243 }
andrewboyson 115:5c003909bcf3 244 return ActionMakeFromDestAndTrace(dest, TftpTrace && NetTraceStack);
andrewboyson 115:5c003909bcf3 245 }