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:
Thu Oct 19 20:56:58 2017 +0000
Revision:
43:bc028d5a6424
Parent:
42:222a4f45f916
Child:
48:952dddb74b8b
Added verbose option to trace

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