Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Nov 17 15:49:03 2018 +0000
Revision:
83:08c983006a6e
Parent:
66:18a10c0b6d93
Child:
93:580fc113d9e9
Added "send requests via IPv4" toggles for DNS, NTP and TFTP.

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