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:
Mon Mar 11 16:42:45 2019 +0000
Revision:
128:79052cb4a41c
Parent:
116:60521b29e4c9
Child:
132:db2174b36a6d
Tidied up the DNS label module and removed some declarations that had not left room for the terminating null.

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