Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Jan 14 13:41:02 2021 +0000
Revision:
184:ad80a63e3002
Parent:
170:96c637dc3f52
Modified TFTP to not start if the network wasn't ready in IPv4; Made changes to DHCP including making the first timeout 4 seconds rather than 1.

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