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:
Fri Jan 11 16:06:08 2019 +0000
Revision:
106:e0f0e8ccb575
Parent:
104:871e65deaa5e
Copied VN and poll from request to reply in NTP message handle

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