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 Oct 04 07:51:02 2017 +0000
Revision:
37:793b39683406
Parent:
36:900e24b27bfb
Child:
42:222a4f45f916
Added trace back and trace forward to log messages

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