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:
Tue Oct 31 21:25:09 2017 +0000
Revision:
48:952dddb74b8b
Parent:
43:bc028d5a6424
Child:
49:1a6336f2b3f9
Split address resolution into AR4 and AR6. Corrected issue clearing a AR6 record.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 37:793b39683406 1 #include "mbed.h"
andrewboyson 37:793b39683406 2 #include "log.h"
andrewboyson 37:793b39683406 3 #include "net.h"
andrewboyson 37:793b39683406 4 #include "action.h"
andrewboyson 37:793b39683406 5 #include "ip6.h"
andrewboyson 37:793b39683406 6 #include "udp.h"
andrewboyson 48:952dddb74b8b 7 #include "ar4.h"
andrewboyson 48:952dddb74b8b 8 #include "ar6.h"
andrewboyson 37:793b39683406 9 #include "arp.h"
andrewboyson 37:793b39683406 10 #include "io.h"
andrewboyson 37:793b39683406 11 #include "eth.h"
andrewboyson 37:793b39683406 12 #include "nr.h"
andrewboyson 37:793b39683406 13 #include "dns.h"
andrewboyson 37:793b39683406 14 #include "mac.h"
andrewboyson 22:914b970356f0 15
andrewboyson 37:793b39683406 16 bool NtpTrace = false;
andrewboyson 0:faa09bd4e6bf 17
andrewboyson 0:faa09bd4e6bf 18 #define HEADER_SIZE 48
andrewboyson 0:faa09bd4e6bf 19
andrewboyson 42:222a4f45f916 20 #define USE_IP4 false
andrewboyson 42:222a4f45f916 21
andrewboyson 0:faa09bd4e6bf 22 #define CLIENT 3
andrewboyson 0:faa09bd4e6bf 23 #define SERVER 4
andrewboyson 0:faa09bd4e6bf 24
andrewboyson 22:914b970356f0 25 uint64_t (*NtpGetClockNowFunction) ();
andrewboyson 22:914b970356f0 26
andrewboyson 22:914b970356f0 27 bool NtpServerEnable = false;
andrewboyson 22:914b970356f0 28 uint64_t (*NtpGetClockRefFunction) ();
andrewboyson 22:914b970356f0 29 int (*NtpGetClockStratumFunction)();
andrewboyson 22:914b970356f0 30 char * (*NtpGetClockIdentFunction) ();
andrewboyson 22:914b970356f0 31
andrewboyson 36:900e24b27bfb 32 uint32_t NtpServerIp4;
andrewboyson 36:900e24b27bfb 33 char NtpServerIp6[16];
andrewboyson 22:914b970356f0 34 bool NtpClientRequest = false;
andrewboyson 35:93c39d260a83 35 char NtpServerName[DNS_MAX_LABEL_LENGTH+1];
andrewboyson 35:93c39d260a83 36 void (*NtpSetClockFunction) (uint64_t ori, uint64_t rec);
andrewboyson 35:93c39d260a83 37
andrewboyson 0:faa09bd4e6bf 38 __packed struct header {
andrewboyson 0:faa09bd4e6bf 39 unsigned Mode : 3;
andrewboyson 0:faa09bd4e6bf 40 unsigned VN : 3;
andrewboyson 0:faa09bd4e6bf 41 unsigned LI : 2;
andrewboyson 0:faa09bd4e6bf 42 uint8_t Stratum;
andrewboyson 0:faa09bd4e6bf 43 int8_t Poll;
andrewboyson 0:faa09bd4e6bf 44 int8_t Precision;
andrewboyson 0:faa09bd4e6bf 45 uint32_t RootDelay;
andrewboyson 0:faa09bd4e6bf 46 uint32_t Dispersion;
andrewboyson 0:faa09bd4e6bf 47 char RefIdentifier[4];
andrewboyson 0:faa09bd4e6bf 48
andrewboyson 0:faa09bd4e6bf 49 uint64_t RefTimeStamp;
andrewboyson 0:faa09bd4e6bf 50 uint64_t OriTimeStamp;
andrewboyson 0:faa09bd4e6bf 51 uint64_t RecTimeStamp;
andrewboyson 0:faa09bd4e6bf 52 uint64_t TraTimeStamp;
andrewboyson 0:faa09bd4e6bf 53 };
andrewboyson 37:793b39683406 54 static void logHeader(struct header* pHeader)
andrewboyson 37:793b39683406 55 {
andrewboyson 43:bc028d5a6424 56 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 57 {
andrewboyson 43:bc028d5a6424 58 Log ("NTP header\r\n");
andrewboyson 43:bc028d5a6424 59 LogF(" Mode %d", pHeader->Mode);
andrewboyson 43:bc028d5a6424 60 LogF(", Version %d", pHeader->VN);
andrewboyson 43:bc028d5a6424 61 LogF(", LI %d", pHeader->LI);
andrewboyson 43:bc028d5a6424 62 LogF(", Stratum %d", pHeader->Stratum);
andrewboyson 43:bc028d5a6424 63 LogF(", Poll %d", pHeader->Poll);
andrewboyson 43:bc028d5a6424 64 LogF(", Precision %d", pHeader->Precision);
andrewboyson 43:bc028d5a6424 65 LogF(", Root delay %d", NetToHost32(pHeader->RootDelay));
andrewboyson 43:bc028d5a6424 66 LogF(", Dispersion %d", NetToHost32(pHeader->Dispersion));
andrewboyson 43:bc028d5a6424 67 Log (", Ident ");
andrewboyson 43:bc028d5a6424 68 for (int i = 0; i < 4; i++) if (pHeader->RefIdentifier[i]) LogPush(pHeader->RefIdentifier[i]);
andrewboyson 43:bc028d5a6424 69 Log ("\r\n");
andrewboyson 43:bc028d5a6424 70 LogF(" REF %llu\r\n", NetToHost64(pHeader->RefTimeStamp));
andrewboyson 43:bc028d5a6424 71 LogF(" ORI %llu\r\n", NetToHost64(pHeader->OriTimeStamp));
andrewboyson 43:bc028d5a6424 72 LogF(" REC %llu\r\n", NetToHost64(pHeader->RecTimeStamp));
andrewboyson 43:bc028d5a6424 73 LogF(" TRA %llu\r\n", NetToHost64(pHeader->TraTimeStamp));
andrewboyson 43:bc028d5a6424 74 }
andrewboyson 43:bc028d5a6424 75 else
andrewboyson 43:bc028d5a6424 76 {
andrewboyson 43:bc028d5a6424 77 Log ("NTP header");
andrewboyson 43:bc028d5a6424 78 LogF(": Mode %d", pHeader->Mode);
andrewboyson 43:bc028d5a6424 79 LogF(", Version %d", pHeader->VN);
andrewboyson 43:bc028d5a6424 80 LogF(", LI %d", pHeader->LI);
andrewboyson 43:bc028d5a6424 81 LogF(", Stratum %d", pHeader->Stratum);
andrewboyson 43:bc028d5a6424 82 LogF(", Poll %d", pHeader->Poll);
andrewboyson 43:bc028d5a6424 83 LogF(", Precision %d", pHeader->Precision);
andrewboyson 43:bc028d5a6424 84 LogF(", Root delay %d", NetToHost32(pHeader->RootDelay));
andrewboyson 43:bc028d5a6424 85 LogF(", Dispersion %d", NetToHost32(pHeader->Dispersion));
andrewboyson 43:bc028d5a6424 86 Log (", Ident ");
andrewboyson 43:bc028d5a6424 87 for (int i = 0; i < 4; i++) if (pHeader->RefIdentifier[i]) LogPush(pHeader->RefIdentifier[i]);
andrewboyson 43:bc028d5a6424 88 Log ("\r\n");
andrewboyson 43:bc028d5a6424 89 }
andrewboyson 37:793b39683406 90 }
andrewboyson 22:914b970356f0 91 static int handleRequest(struct header* pHeader)
andrewboyson 0:faa09bd4e6bf 92 {
andrewboyson 22:914b970356f0 93 if (!NtpServerEnable) return DO_NOTHING;
andrewboyson 17:e475ab861365 94
andrewboyson 17:e475ab861365 95 if (!NtpGetClockRefFunction || !NtpGetClockNowFunction || !NtpGetClockStratumFunction || !NtpGetClockIdentFunction)
andrewboyson 17:e475ab861365 96 {
andrewboyson 17:e475ab861365 97 LogTimeF("NtpHandleRequest - NTP server is enabled but has not been plumbed into a clock\r\n");
andrewboyson 17:e475ab861365 98 return DO_NOTHING;
andrewboyson 17:e475ab861365 99 }
andrewboyson 22:914b970356f0 100
andrewboyson 20:23f2b29b48ea 101 uint64_t refNtp = NtpGetClockRefFunction();
andrewboyson 20:23f2b29b48ea 102 uint64_t nowNtp = NtpGetClockNowFunction();
andrewboyson 20:23f2b29b48ea 103 int stratum = NtpGetClockStratumFunction();
andrewboyson 20:23f2b29b48ea 104 char* ident = NtpGetClockIdentFunction();
andrewboyson 22:914b970356f0 105
andrewboyson 22:914b970356f0 106 pHeader->Mode = SERVER;
andrewboyson 22:914b970356f0 107 pHeader->LI = 0;
andrewboyson 22:914b970356f0 108 pHeader->Stratum = stratum;
andrewboyson 22:914b970356f0 109 pHeader->Poll = 0;
andrewboyson 22:914b970356f0 110 pHeader->Precision = 0;
andrewboyson 22:914b970356f0 111 pHeader->RootDelay = 0;
andrewboyson 22:914b970356f0 112 pHeader->Dispersion = 0;
andrewboyson 22:914b970356f0 113 pHeader->RefIdentifier[0] = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string.
andrewboyson 22:914b970356f0 114 pHeader->RefIdentifier[1] = ident[1];
andrewboyson 22:914b970356f0 115 pHeader->RefIdentifier[2] = ident[2];
andrewboyson 22:914b970356f0 116 pHeader->RefIdentifier[3] = ident[3];
andrewboyson 22:914b970356f0 117
andrewboyson 22:914b970356f0 118 pHeader->RefTimeStamp = NetToHost64(refNtp);
andrewboyson 22:914b970356f0 119 pHeader->OriTimeStamp = pHeader->TraTimeStamp;
andrewboyson 22:914b970356f0 120 pHeader->RecTimeStamp = NetToHost64(nowNtp);
andrewboyson 22:914b970356f0 121 pHeader->TraTimeStamp = NetToHost64(nowNtp);
andrewboyson 22:914b970356f0 122 return UNICAST;
andrewboyson 22:914b970356f0 123 }
andrewboyson 37:793b39683406 124 static void (*pTraceBack)(void);
andrewboyson 22:914b970356f0 125 static int handleReply(struct header* pHeader)
andrewboyson 22:914b970356f0 126 {
andrewboyson 22:914b970356f0 127 if (!NtpGetClockNowFunction || !NtpSetClockFunction)
andrewboyson 22:914b970356f0 128 {
andrewboyson 22:914b970356f0 129 LogTimeF("Ntp reply has been received but NTP has not been plumbed into a clock\r\n");
andrewboyson 22:914b970356f0 130 return DO_NOTHING;
andrewboyson 22:914b970356f0 131 }
andrewboyson 22:914b970356f0 132 if (pHeader->Mode != SERVER)
andrewboyson 22:914b970356f0 133 {
andrewboyson 22:914b970356f0 134 LogTimeF("Ntp reply has been received but mode is not SERVER it is %d\r\n", pHeader->Mode);
andrewboyson 22:914b970356f0 135 return DO_NOTHING;
andrewboyson 22:914b970356f0 136 }
andrewboyson 37:793b39683406 137 if (NtpTrace)
andrewboyson 22:914b970356f0 138 {
andrewboyson 43:bc028d5a6424 139 if (NetTraceNewLine) Log("\r\n");
andrewboyson 22:914b970356f0 140 LogTimeF("NTP received reply\r\n");
andrewboyson 43:bc028d5a6424 141 if (NetTraceStack) pTraceBack();
andrewboyson 37:793b39683406 142 logHeader(pHeader);
andrewboyson 22:914b970356f0 143 }
andrewboyson 37:793b39683406 144
andrewboyson 22:914b970356f0 145 uint64_t ori = NetToHost64(pHeader->OriTimeStamp);
andrewboyson 22:914b970356f0 146 uint64_t rec = NetToHost64(pHeader->RecTimeStamp);
andrewboyson 22:914b970356f0 147
andrewboyson 22:914b970356f0 148 NtpSetClockFunction(ori, rec);
andrewboyson 22:914b970356f0 149 return DO_NOTHING;
andrewboyson 22:914b970356f0 150 }
andrewboyson 37:793b39683406 151 int NtpHandlePacketReceived(void (*traceback)(void), int* pSize, void * pPacket)
andrewboyson 22:914b970356f0 152 {
andrewboyson 37:793b39683406 153 pTraceBack = traceback;
andrewboyson 37:793b39683406 154
andrewboyson 22:914b970356f0 155 if (*pSize != HEADER_SIZE)
andrewboyson 22:914b970356f0 156 {
andrewboyson 22:914b970356f0 157 LogTimeF("\r\nNTP packet wrong size %d\r\n", *pSize);
andrewboyson 22:914b970356f0 158 return DO_NOTHING;
andrewboyson 22:914b970356f0 159 }
andrewboyson 22:914b970356f0 160 struct header* pHeader = (struct header*)pPacket;
andrewboyson 17:e475ab861365 161
andrewboyson 0:faa09bd4e6bf 162 switch (pHeader->Mode)
andrewboyson 0:faa09bd4e6bf 163 {
andrewboyson 22:914b970356f0 164 case CLIENT: return handleRequest(pHeader);
andrewboyson 22:914b970356f0 165 case SERVER: return handleReply(pHeader);
andrewboyson 0:faa09bd4e6bf 166 default:
andrewboyson 22:914b970356f0 167 LogTimeF("\r\nNTP packet unknown mode %d\r\n", pHeader->Mode);
andrewboyson 22:914b970356f0 168 return DO_NOTHING;
andrewboyson 0:faa09bd4e6bf 169 }
andrewboyson 22:914b970356f0 170 }
andrewboyson 22:914b970356f0 171 static int sendRequest(void* pPacket, int* pSize)
andrewboyson 22:914b970356f0 172 {
andrewboyson 22:914b970356f0 173 struct header* pHeader = (struct header*)pPacket;
andrewboyson 22:914b970356f0 174
andrewboyson 22:914b970356f0 175 pHeader->Mode = CLIENT;
andrewboyson 22:914b970356f0 176 pHeader->VN = 3;
andrewboyson 22:914b970356f0 177 pHeader->LI = 0;
andrewboyson 22:914b970356f0 178 pHeader->Stratum = 0;
andrewboyson 22:914b970356f0 179 pHeader->Poll = 0;
andrewboyson 22:914b970356f0 180 pHeader->Precision = 0;
andrewboyson 22:914b970356f0 181 pHeader->RootDelay = 0;
andrewboyson 22:914b970356f0 182 pHeader->Dispersion = 0;
andrewboyson 22:914b970356f0 183 pHeader->RefIdentifier[0] = 0;
andrewboyson 22:914b970356f0 184 pHeader->RefIdentifier[1] = 0;
andrewboyson 22:914b970356f0 185 pHeader->RefIdentifier[2] = 0;
andrewboyson 22:914b970356f0 186 pHeader->RefIdentifier[3] = 0;
andrewboyson 22:914b970356f0 187
andrewboyson 22:914b970356f0 188 pHeader->RefTimeStamp = 0;
andrewboyson 22:914b970356f0 189 pHeader->OriTimeStamp = 0;
andrewboyson 22:914b970356f0 190 pHeader->RecTimeStamp = 0;
andrewboyson 22:914b970356f0 191 pHeader->TraTimeStamp = NetToHost64(NtpGetClockNowFunction());
andrewboyson 22:914b970356f0 192 *pSize = HEADER_SIZE;
andrewboyson 22:914b970356f0 193
andrewboyson 22:914b970356f0 194 return UNICAST_NTP;
andrewboyson 0:faa09bd4e6bf 195 }
andrewboyson 36:900e24b27bfb 196 static bool resolve4(char* server, uint32_t* pIp)
andrewboyson 36:900e24b27bfb 197 {
andrewboyson 36:900e24b27bfb 198 //Check if have IP, if not, then request it and stop
andrewboyson 36:900e24b27bfb 199 NrNameToIp4(server, pIp);
andrewboyson 36:900e24b27bfb 200 if (!*pIp)
andrewboyson 36:900e24b27bfb 201 {
andrewboyson 36:900e24b27bfb 202 NrMakeRequestForIp4FromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 36:900e24b27bfb 203 return false;
andrewboyson 36:900e24b27bfb 204 }
andrewboyson 35:93c39d260a83 205
andrewboyson 36:900e24b27bfb 206 //Check if have MAC and, if not, request it and stop
andrewboyson 36:900e24b27bfb 207 char mac[6];
andrewboyson 48:952dddb74b8b 208 Ar4IpToMac(*pIp, mac);
andrewboyson 36:900e24b27bfb 209 if (MacIsEmpty(mac))
andrewboyson 36:900e24b27bfb 210 {
andrewboyson 48:952dddb74b8b 211 Ar4MakeRequestForMacFromIp(*pIp); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 36:900e24b27bfb 212 return false;
andrewboyson 36:900e24b27bfb 213 }
andrewboyson 36:900e24b27bfb 214
andrewboyson 36:900e24b27bfb 215 return true;
andrewboyson 36:900e24b27bfb 216 }
andrewboyson 36:900e24b27bfb 217 static bool resolve6(char* server, char* ip)
andrewboyson 36:900e24b27bfb 218 {
andrewboyson 36:900e24b27bfb 219 //Check if have IP, if not, then request it and stop
andrewboyson 36:900e24b27bfb 220 NrNameToIp6(server, ip);
andrewboyson 36:900e24b27bfb 221 if (Ip6IsEmpty(ip))
andrewboyson 36:900e24b27bfb 222 {
andrewboyson 36:900e24b27bfb 223 NrMakeRequestForIp6FromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 36:900e24b27bfb 224 return false;
andrewboyson 36:900e24b27bfb 225 }
andrewboyson 36:900e24b27bfb 226
andrewboyson 36:900e24b27bfb 227 //Check if have MAC and, if not, request it and stop
andrewboyson 36:900e24b27bfb 228 char mac[6];
andrewboyson 48:952dddb74b8b 229 Ar6IpToMac(ip, mac);
andrewboyson 36:900e24b27bfb 230 if (MacIsEmpty(mac))
andrewboyson 36:900e24b27bfb 231 {
andrewboyson 48:952dddb74b8b 232 Ar6MakeRequestForMacFromIp(ip); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 36:900e24b27bfb 233 return false;
andrewboyson 36:900e24b27bfb 234 }
andrewboyson 36:900e24b27bfb 235
andrewboyson 36:900e24b27bfb 236 return true;
andrewboyson 36:900e24b27bfb 237 }
andrewboyson 22:914b970356f0 238 int NtpPollForPacketToSend(int type, void* pPacket, int* pSize)
andrewboyson 22:914b970356f0 239 {
andrewboyson 22:914b970356f0 240 if (!NtpClientRequest) return DO_NOTHING; //Wait until a request for time is made
andrewboyson 22:914b970356f0 241
andrewboyson 35:93c39d260a83 242 if (!NtpServerName[0])
andrewboyson 35:93c39d260a83 243 {
andrewboyson 35:93c39d260a83 244 LogTimeF("NtpPollForRequestToSend - A request to send a client message has been made but no server name has been specified\r\n");
andrewboyson 35:93c39d260a83 245 NtpClientRequest = false;
andrewboyson 35:93c39d260a83 246 return DO_NOTHING;
andrewboyson 35:93c39d260a83 247 }
andrewboyson 35:93c39d260a83 248
andrewboyson 35:93c39d260a83 249 if (!NtpGetClockNowFunction || !NtpSetClockFunction)
andrewboyson 22:914b970356f0 250 {
andrewboyson 22:914b970356f0 251 LogTimeF("NtpPollForRequestToSend - A request to send a client message has been made but NTP has not been plumbed into a clock\r\n");
andrewboyson 22:914b970356f0 252 NtpClientRequest = false;
andrewboyson 22:914b970356f0 253 return DO_NOTHING;
andrewboyson 22:914b970356f0 254 }
andrewboyson 42:222a4f45f916 255
andrewboyson 42:222a4f45f916 256 if (type == IPV4)
andrewboyson 42:222a4f45f916 257 {
andrewboyson 42:222a4f45f916 258 if (!resolve4(NtpServerName, &NtpServerIp4)) return DO_NOTHING;
andrewboyson 42:222a4f45f916 259 }
andrewboyson 42:222a4f45f916 260 else if (type == IPV6)
andrewboyson 42:222a4f45f916 261 {
andrewboyson 42:222a4f45f916 262 if (!resolve6(NtpServerName, NtpServerIp6)) return DO_NOTHING;
andrewboyson 42:222a4f45f916 263 }
andrewboyson 42:222a4f45f916 264 else
andrewboyson 42:222a4f45f916 265 {
andrewboyson 42:222a4f45f916 266 return DO_NOTHING;
andrewboyson 42:222a4f45f916 267 }
andrewboyson 35:93c39d260a83 268
andrewboyson 35:93c39d260a83 269 //Have IP and MAC so send request
andrewboyson 42:222a4f45f916 270 NtpClientRequest = false;
andrewboyson 42:222a4f45f916 271 int dest = sendRequest(pPacket, pSize);
andrewboyson 42:222a4f45f916 272 if (NtpTrace)
andrewboyson 37:793b39683406 273 {
andrewboyson 43:bc028d5a6424 274 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 275 LogTimeF("Sending NTP request\r\n");
andrewboyson 42:222a4f45f916 276 logHeader((struct header*)pPacket);
andrewboyson 37:793b39683406 277 }
andrewboyson 43:bc028d5a6424 278 return ActionMakeFromDestAndTrace(dest, NtpTrace && NetTraceStack);
andrewboyson 22:914b970356f0 279 }
andrewboyson 22:914b970356f0 280