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:
Wed Jan 31 08:00:27 2018 +0000
Revision:
68:e8c002e5ee4b
Parent:
61:aad055f1b0d1
Child:
69:6b3c648e1452
Moved NtpClientTrace into net library

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