Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Fri Jan 19 19:47:37 2018 +0000
Revision:
66:18a10c0b6d93
Parent:
65:37acccf2752f
Child:
83:08c983006a6e
Updated following clock.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 61:aad055f1b0d1 1 #include <stdint.h>
andrewboyson 61:aad055f1b0d1 2 #include <stdbool.h>
andrewboyson 61:aad055f1b0d1 3
andrewboyson 57:e0fb648acf48 4 #include "log.h"
andrewboyson 57:e0fb648acf48 5 #include "net.h"
andrewboyson 57:e0fb648acf48 6 #include "action.h"
andrewboyson 57:e0fb648acf48 7 #include "ip6addr.h"
andrewboyson 57:e0fb648acf48 8 #include "udp.h"
andrewboyson 57:e0fb648acf48 9 #include "ar4.h"
andrewboyson 57:e0fb648acf48 10 #include "ar6.h"
andrewboyson 57:e0fb648acf48 11 #include "arp.h"
andrewboyson 57:e0fb648acf48 12 #include "eth.h"
andrewboyson 57:e0fb648acf48 13 #include "nr4.h"
andrewboyson 57:e0fb648acf48 14 #include "nr6.h"
andrewboyson 57:e0fb648acf48 15 #include "dns.h"
andrewboyson 57:e0fb648acf48 16 #include "mac.h"
andrewboyson 57:e0fb648acf48 17 #include "tftp.h"
andrewboyson 66:18a10c0b6d93 18 #include "clock.h"
andrewboyson 57:e0fb648acf48 19
andrewboyson 57:e0fb648acf48 20 bool TftpTrace = false;
andrewboyson 57:e0fb648acf48 21
andrewboyson 57:e0fb648acf48 22 #define WRITE_TIMEOUT_SECS 5
andrewboyson 57:e0fb648acf48 23
andrewboyson 57:e0fb648acf48 24 #define TFTP_RRQ 1
andrewboyson 57:e0fb648acf48 25 #define TFTP_WRQ 2
andrewboyson 57:e0fb648acf48 26 #define TFTP_DATA 3
andrewboyson 57:e0fb648acf48 27 #define TFTP_ACK 4
andrewboyson 57:e0fb648acf48 28 #define TFTP_ERROR 5
andrewboyson 57:e0fb648acf48 29
andrewboyson 57:e0fb648acf48 30 static void logOp(char* p)
andrewboyson 57:e0fb648acf48 31 {
andrewboyson 57:e0fb648acf48 32 if (*p)
andrewboyson 57:e0fb648acf48 33 {
andrewboyson 57:e0fb648acf48 34 LogF("Unknown op code %02x%02x", *p, *++p);
andrewboyson 57:e0fb648acf48 35 return;
andrewboyson 57:e0fb648acf48 36 }
andrewboyson 57:e0fb648acf48 37 p++;
andrewboyson 57:e0fb648acf48 38 switch (*p)
andrewboyson 57:e0fb648acf48 39 {
andrewboyson 57:e0fb648acf48 40 case TFTP_RRQ: Log ("RRQ") ; break;
andrewboyson 57:e0fb648acf48 41 case TFTP_WRQ: Log ("WRQ") ; break;
andrewboyson 57:e0fb648acf48 42 case TFTP_DATA: Log ("DATA") ; break;
andrewboyson 57:e0fb648acf48 43 case TFTP_ACK: Log ("ACK") ; break;
andrewboyson 57:e0fb648acf48 44 case TFTP_ERROR: Log ("ERROR") ; break;
andrewboyson 57:e0fb648acf48 45 default: LogF("Unknown op code 00%02x", *p); break;
andrewboyson 57:e0fb648acf48 46 }
andrewboyson 57:e0fb648acf48 47 }
andrewboyson 57:e0fb648acf48 48
andrewboyson 57:e0fb648acf48 49 static void logError(char* p)
andrewboyson 57:e0fb648acf48 50 {
andrewboyson 57:e0fb648acf48 51 if (*p)
andrewboyson 57:e0fb648acf48 52 {
andrewboyson 57:e0fb648acf48 53 LogF("Unknown error code %02x%02x", *p, *++p);
andrewboyson 57:e0fb648acf48 54 return;
andrewboyson 57:e0fb648acf48 55 }
andrewboyson 57:e0fb648acf48 56 p++;
andrewboyson 57:e0fb648acf48 57 switch (*p)
andrewboyson 57:e0fb648acf48 58 {
andrewboyson 57:e0fb648acf48 59 case 0: Log ("Not defined, see error message." ); break;
andrewboyson 57:e0fb648acf48 60 case 1: Log ("File not found." ); break;
andrewboyson 57:e0fb648acf48 61 case 2: Log ("Access violation." ); break;
andrewboyson 57:e0fb648acf48 62 case 3: Log ("Disk full or allocation exceeded."); break;
andrewboyson 57:e0fb648acf48 63 case 4: Log ("Illegal TFTP operation." ); break;
andrewboyson 57:e0fb648acf48 64 case 5: Log ("Unknown transfer ID." ); break;
andrewboyson 57:e0fb648acf48 65 case 6: Log ("File already exists." ); break;
andrewboyson 57:e0fb648acf48 66 case 7: Log ("No such user." ); break;
andrewboyson 57:e0fb648acf48 67 default: LogF("Unknown error code 00%02x", *p ); break;
andrewboyson 57:e0fb648acf48 68 }
andrewboyson 57:e0fb648acf48 69 }
andrewboyson 57:e0fb648acf48 70 uint32_t TftpServerIp4;
andrewboyson 57:e0fb648acf48 71 char TftpServerIp6[16];
andrewboyson 57:e0fb648acf48 72 int TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 73 char TftpServerName[DNS_MAX_LABEL_LENGTH+1];
andrewboyson 57:e0fb648acf48 74 char TftpFileName [DNS_MAX_LABEL_LENGTH+1];
andrewboyson 57:e0fb648acf48 75
andrewboyson 57:e0fb648acf48 76 int (*TftpGetNextByteFunction)();
andrewboyson 57:e0fb648acf48 77
andrewboyson 57:e0fb648acf48 78 static int size;
andrewboyson 57:e0fb648acf48 79
andrewboyson 59:e0e556c8bd46 80 static void logHeader(char* p)
andrewboyson 57:e0fb648acf48 81 {
andrewboyson 57:e0fb648acf48 82 if (NetTraceVerbose)
andrewboyson 57:e0fb648acf48 83 {
andrewboyson 57:e0fb648acf48 84 Log ("TFTP header\r\n");
andrewboyson 57:e0fb648acf48 85 Log (" Op code "); logOp(p); Log("\r\n");
andrewboyson 57:e0fb648acf48 86 Log (" Size "); LogF("%d", size); Log("\r\n");
andrewboyson 57:e0fb648acf48 87 }
andrewboyson 57:e0fb648acf48 88 else
andrewboyson 57:e0fb648acf48 89 {
andrewboyson 57:e0fb648acf48 90 Log ("TFTP header");
andrewboyson 57:e0fb648acf48 91 Log (": Op "); logOp(p);
andrewboyson 57:e0fb648acf48 92 LogF(", %d bytes", size);
andrewboyson 57:e0fb648acf48 93 Log ("\r\n");
andrewboyson 57:e0fb648acf48 94 }
andrewboyson 57:e0fb648acf48 95 }
andrewboyson 59:e0e556c8bd46 96 static int sendBlock(uint16_t block, char* pHeader)
andrewboyson 57:e0fb648acf48 97 {
andrewboyson 57:e0fb648acf48 98 /*2 bytes 2 bytes n bytes
andrewboyson 57:e0fb648acf48 99 ----------------------------------
andrewboyson 57:e0fb648acf48 100 | Opcode | Block # | Data |
andrewboyson 57:e0fb648acf48 101 ---------------------------------- */
andrewboyson 59:e0e556c8bd46 102 char* p = pHeader;
andrewboyson 57:e0fb648acf48 103 *p++ = 0;
andrewboyson 57:e0fb648acf48 104 *p++ = TFTP_DATA;
andrewboyson 57:e0fb648acf48 105 *p++ = block >> 8;
andrewboyson 57:e0fb648acf48 106 *p++ = block & 0xFF;
andrewboyson 57:e0fb648acf48 107
andrewboyson 57:e0fb648acf48 108 int len = 0;
andrewboyson 57:e0fb648acf48 109 while (len < 512)
andrewboyson 57:e0fb648acf48 110 {
andrewboyson 57:e0fb648acf48 111 int c = TftpGetNextByteFunction();
andrewboyson 57:e0fb648acf48 112 if (c == -1) break;
andrewboyson 57:e0fb648acf48 113 *p++ = c;
andrewboyson 57:e0fb648acf48 114 len++;
andrewboyson 57:e0fb648acf48 115 }
andrewboyson 57:e0fb648acf48 116 if (len < 512) TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 117 size = p - pHeader;
andrewboyson 57:e0fb648acf48 118 return UNICAST_TFTP;
andrewboyson 57:e0fb648acf48 119 }
andrewboyson 59:e0e556c8bd46 120 static void handleError(char* p)
andrewboyson 57:e0fb648acf48 121 {
andrewboyson 57:e0fb648acf48 122 /*2 bytes 2 bytes string 1 byte
andrewboyson 57:e0fb648acf48 123 -----------------------------------------
andrewboyson 57:e0fb648acf48 124 | ERROR | ErrorCode | ErrMsg | 0 |
andrewboyson 57:e0fb648acf48 125 ----------------------------------------- */
andrewboyson 59:e0e556c8bd46 126 p += 2; //Skip the op code which we already know
andrewboyson 57:e0fb648acf48 127 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 128 LogTime("TFTP error - ");
andrewboyson 57:e0fb648acf48 129 logError(p); p += 2;
andrewboyson 57:e0fb648acf48 130 Log(p);
andrewboyson 57:e0fb648acf48 131 Log("\r\n");
andrewboyson 57:e0fb648acf48 132 TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 133 }
andrewboyson 59:e0e556c8bd46 134 static int handleAck(char* pHeaderRx, char* pHeaderTx)
andrewboyson 57:e0fb648acf48 135 {
andrewboyson 59:e0e556c8bd46 136 /* 2 bytes 2 bytes
andrewboyson 59:e0e556c8bd46 137 -----------------------
andrewboyson 59:e0e556c8bd46 138 | ACK | Block # |
andrewboyson 59:e0e556c8bd46 139 ----------------------- */
andrewboyson 59:e0e556c8bd46 140 char* p = pHeaderRx;
andrewboyson 59:e0e556c8bd46 141 p += 2; //Skip the op code which we already know
andrewboyson 57:e0fb648acf48 142 uint16_t block = *p++;
andrewboyson 57:e0fb648acf48 143 block <<= 8;
andrewboyson 57:e0fb648acf48 144 block += *p++;
andrewboyson 57:e0fb648acf48 145
andrewboyson 59:e0e556c8bd46 146 return sendBlock(block + 1, pHeaderTx);
andrewboyson 57:e0fb648acf48 147 }
andrewboyson 59:e0e556c8bd46 148 static int sendRequest(char* pHeader)
andrewboyson 57:e0fb648acf48 149 {
andrewboyson 57:e0fb648acf48 150 /*2 bytes string 1 byte string 1 byte
andrewboyson 57:e0fb648acf48 151 -----------------------------------------------
andrewboyson 57:e0fb648acf48 152 | WRQ | Filename | 0 | Mode | 0 |
andrewboyson 57:e0fb648acf48 153 ----------------------------------------------- */
andrewboyson 59:e0e556c8bd46 154 char* p = pHeader;
andrewboyson 57:e0fb648acf48 155 *p++ = 0;
andrewboyson 57:e0fb648acf48 156 *p++ = TFTP_WRQ;
andrewboyson 57:e0fb648acf48 157 char* pName = TftpFileName;
andrewboyson 57:e0fb648acf48 158 while (*pName) *p++ = *pName++;
andrewboyson 57:e0fb648acf48 159 *p++ = 0;
andrewboyson 57:e0fb648acf48 160 const char* pMode = "octet";
andrewboyson 57:e0fb648acf48 161 while (*pMode) *p++ = *pMode++;
andrewboyson 57:e0fb648acf48 162 *p++ = 0;
andrewboyson 57:e0fb648acf48 163 size = p - pHeader;
andrewboyson 57:e0fb648acf48 164 return UNICAST_TFTP;
andrewboyson 57:e0fb648acf48 165 }
andrewboyson 57:e0fb648acf48 166 static void (*pTraceBack)(void);
andrewboyson 59:e0e556c8bd46 167 int TftpHandlePacketReceived(void (*traceback)(void), int sizeRx, void * pPacketRx, int* pSizeTx, void* pPacketTx)
andrewboyson 57:e0fb648acf48 168 {
andrewboyson 57:e0fb648acf48 169 pTraceBack = traceback;
andrewboyson 59:e0e556c8bd46 170 char* pHeaderRx = (char*)pPacketRx;
andrewboyson 59:e0e556c8bd46 171 char* pHeaderTx = (char*)pPacketTx;
andrewboyson 59:e0e556c8bd46 172 size = sizeRx;
andrewboyson 57:e0fb648acf48 173
andrewboyson 59:e0e556c8bd46 174 char* p = pHeaderRx;
andrewboyson 57:e0fb648acf48 175
andrewboyson 57:e0fb648acf48 176 if (*p)
andrewboyson 57:e0fb648acf48 177 {
andrewboyson 57:e0fb648acf48 178 LogTimeF("Expected high byte of op code to be zero not %u\r\n", *p);
andrewboyson 57:e0fb648acf48 179 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 180 }
andrewboyson 57:e0fb648acf48 181 if (TftpTrace)
andrewboyson 57:e0fb648acf48 182 {
andrewboyson 57:e0fb648acf48 183 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 184 LogTimeF("TFTP received packet\r\n");
andrewboyson 57:e0fb648acf48 185 if (NetTraceStack) pTraceBack();
andrewboyson 59:e0e556c8bd46 186 logHeader(pHeaderRx);
andrewboyson 57:e0fb648acf48 187 }
andrewboyson 57:e0fb648acf48 188 p++;
andrewboyson 57:e0fb648acf48 189 int dest = DO_NOTHING;
andrewboyson 57:e0fb648acf48 190 switch (*p)
andrewboyson 57:e0fb648acf48 191 {
andrewboyson 57:e0fb648acf48 192 case TFTP_ACK:
andrewboyson 57:e0fb648acf48 193 if (TftpWriteStatus == TFTP_WRITE_STATUS_NONE) return DO_NOTHING;
andrewboyson 59:e0e556c8bd46 194 dest = handleAck(pHeaderRx, pHeaderTx);
andrewboyson 57:e0fb648acf48 195 break;
andrewboyson 57:e0fb648acf48 196 case TFTP_ERROR:
andrewboyson 59:e0e556c8bd46 197 handleError(pHeaderRx);
andrewboyson 57:e0fb648acf48 198 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 199 default:
andrewboyson 57:e0fb648acf48 200 LogTimeF("\r\nTFTP packet unknown mode %d\r\n", *p);
andrewboyson 57:e0fb648acf48 201 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 202 }
andrewboyson 57:e0fb648acf48 203
andrewboyson 59:e0e556c8bd46 204 if (TftpTrace) logHeader(pHeaderTx);
andrewboyson 57:e0fb648acf48 205
andrewboyson 59:e0e556c8bd46 206 *pSizeTx = size;
andrewboyson 57:e0fb648acf48 207 return ActionMakeFromDestAndTrace(dest, TftpTrace && NetTraceStack);
andrewboyson 57:e0fb648acf48 208 }
andrewboyson 57:e0fb648acf48 209 static bool resolve4(char* server, uint32_t* pIp)
andrewboyson 57:e0fb648acf48 210 {
andrewboyson 57:e0fb648acf48 211 //Check if have IP, if not, then request it and stop
andrewboyson 57:e0fb648acf48 212 Nr4NameToIp(server, pIp);
andrewboyson 57:e0fb648acf48 213 if (!*pIp)
andrewboyson 57:e0fb648acf48 214 {
andrewboyson 57:e0fb648acf48 215 Nr4MakeRequestForIpFromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 57:e0fb648acf48 216 return false;
andrewboyson 57:e0fb648acf48 217 }
andrewboyson 57:e0fb648acf48 218
andrewboyson 57:e0fb648acf48 219 //Check if have MAC and, if not, request it and stop
andrewboyson 57:e0fb648acf48 220 char mac[6];
andrewboyson 57:e0fb648acf48 221 Ar4IpToMac(*pIp, mac);
andrewboyson 57:e0fb648acf48 222 if (MacIsEmpty(mac))
andrewboyson 57:e0fb648acf48 223 {
andrewboyson 57:e0fb648acf48 224 Ar4MakeRequestForMacFromIp(*pIp); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 57:e0fb648acf48 225 return false;
andrewboyson 57:e0fb648acf48 226 }
andrewboyson 57:e0fb648acf48 227
andrewboyson 57:e0fb648acf48 228 return true;
andrewboyson 57:e0fb648acf48 229 }
andrewboyson 57:e0fb648acf48 230 static bool resolve6(char* server, char* ip)
andrewboyson 57:e0fb648acf48 231 {
andrewboyson 57:e0fb648acf48 232 //Check if have IP, if not, then request it and stop
andrewboyson 57:e0fb648acf48 233 Nr6NameToIp(server, ip);
andrewboyson 57:e0fb648acf48 234 if (Ip6AddressIsEmpty(ip))
andrewboyson 57:e0fb648acf48 235 {
andrewboyson 57:e0fb648acf48 236 Nr6MakeRequestForIpFromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 57:e0fb648acf48 237 return false;
andrewboyson 57:e0fb648acf48 238 }
andrewboyson 57:e0fb648acf48 239
andrewboyson 57:e0fb648acf48 240 //Check if have MAC and, if not, request it and stop
andrewboyson 57:e0fb648acf48 241 char mac[6];
andrewboyson 57:e0fb648acf48 242 Ar6IpToMac(ip, mac);
andrewboyson 57:e0fb648acf48 243 if (MacIsEmpty(mac))
andrewboyson 57:e0fb648acf48 244 {
andrewboyson 57:e0fb648acf48 245 Ar6MakeRequestForMacFromIp(ip); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 57:e0fb648acf48 246 return false;
andrewboyson 57:e0fb648acf48 247 }
andrewboyson 57:e0fb648acf48 248
andrewboyson 57:e0fb648acf48 249 return true;
andrewboyson 57:e0fb648acf48 250 }
andrewboyson 57:e0fb648acf48 251 int TftpPollForPacketToSend(int type, void* pPacket, int* pSize)
andrewboyson 57:e0fb648acf48 252 {
andrewboyson 57:e0fb648acf48 253 if (TftpWriteStatus != TFTP_WRITE_STATUS_REQUEST) return DO_NOTHING; //Wait until a request to send a file
andrewboyson 57:e0fb648acf48 254
andrewboyson 59:e0e556c8bd46 255 char* pHeader = (char*)pPacket;
andrewboyson 57:e0fb648acf48 256 size = *pSize;
andrewboyson 57:e0fb648acf48 257
andrewboyson 57:e0fb648acf48 258 if (!TftpServerName[0])
andrewboyson 57:e0fb648acf48 259 {
andrewboyson 57:e0fb648acf48 260 LogTimeF("TftpPollForRequestToSend - A request to send a client message has been made but no server name has been specified\r\n");
andrewboyson 57:e0fb648acf48 261 TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 262 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 263 }
andrewboyson 57:e0fb648acf48 264
andrewboyson 57:e0fb648acf48 265 if (!TftpGetNextByteFunction)
andrewboyson 57:e0fb648acf48 266 {
andrewboyson 57:e0fb648acf48 267 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 57:e0fb648acf48 268 TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 269 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 270 }
andrewboyson 57:e0fb648acf48 271
andrewboyson 57:e0fb648acf48 272 if (type == IPV4)
andrewboyson 57:e0fb648acf48 273 {
andrewboyson 57:e0fb648acf48 274 if (!resolve4(TftpServerName, &TftpServerIp4)) return DO_NOTHING;
andrewboyson 57:e0fb648acf48 275 }
andrewboyson 57:e0fb648acf48 276 else if (type == IPV6)
andrewboyson 57:e0fb648acf48 277 {
andrewboyson 57:e0fb648acf48 278 if (!resolve6(TftpServerName, TftpServerIp6)) return DO_NOTHING;
andrewboyson 57:e0fb648acf48 279 }
andrewboyson 57:e0fb648acf48 280 else
andrewboyson 57:e0fb648acf48 281 {
andrewboyson 57:e0fb648acf48 282 return DO_NOTHING;
andrewboyson 57:e0fb648acf48 283 }
andrewboyson 57:e0fb648acf48 284
andrewboyson 57:e0fb648acf48 285 //Have IP and MAC so send request
andrewboyson 57:e0fb648acf48 286 TftpWriteStatus = TFTP_WRITE_STATUS_IN_PROGRESS;
andrewboyson 59:e0e556c8bd46 287 int dest = sendRequest(pHeader);
andrewboyson 57:e0fb648acf48 288 if (TftpTrace)
andrewboyson 57:e0fb648acf48 289 {
andrewboyson 57:e0fb648acf48 290 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 291 LogTimeF("TFTP Sending request\r\n");
andrewboyson 59:e0e556c8bd46 292 logHeader(pHeader);
andrewboyson 57:e0fb648acf48 293 }
andrewboyson 57:e0fb648acf48 294 *pSize = size;
andrewboyson 57:e0fb648acf48 295 return ActionMakeFromDestAndTrace(dest, TftpTrace && NetTraceStack);
andrewboyson 57:e0fb648acf48 296 }
andrewboyson 57:e0fb648acf48 297 int elapsed = 0;
andrewboyson 57:e0fb648acf48 298 void TftpMain()
andrewboyson 57:e0fb648acf48 299 {
andrewboyson 57:e0fb648acf48 300 if (TftpWriteStatus == TFTP_WRITE_STATUS_IN_PROGRESS)
andrewboyson 57:e0fb648acf48 301 {
andrewboyson 66:18a10c0b6d93 302 if (ClockTicked) elapsed++;
andrewboyson 57:e0fb648acf48 303 if (elapsed > WRITE_TIMEOUT_SECS)
andrewboyson 57:e0fb648acf48 304 {
andrewboyson 57:e0fb648acf48 305 TftpWriteStatus = TFTP_WRITE_STATUS_NONE;
andrewboyson 57:e0fb648acf48 306 LogTime("TFTP - write operation timed out so reset\r\n");
andrewboyson 57:e0fb648acf48 307 }
andrewboyson 57:e0fb648acf48 308 }
andrewboyson 57:e0fb648acf48 309 else
andrewboyson 57:e0fb648acf48 310 {
andrewboyson 57:e0fb648acf48 311 elapsed = 0;
andrewboyson 57:e0fb648acf48 312 }
andrewboyson 57:e0fb648acf48 313 }