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 Sep 22 13:55:56 2017 +0000
Revision:
35:93c39d260a83
Parent:
22:914b970356f0
Child:
36:900e24b27bfb
Added name resolution and address resolution

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 1:5f70c361db20 1 #include "mbed.h"
andrewboyson 4:31fa7d50722c 2 #include "log.h"
andrewboyson 1:5f70c361db20 3 #include "net.h"
andrewboyson 7:b794780e33b4 4 #include "udp.h"
andrewboyson 22:914b970356f0 5 #include "ar.h"
andrewboyson 22:914b970356f0 6 #include "arp.h"
andrewboyson 22:914b970356f0 7 #include "io.h"
andrewboyson 22:914b970356f0 8 #include "eth.h"
andrewboyson 35:93c39d260a83 9 #include "nr.h"
andrewboyson 35:93c39d260a83 10 #include "dns.h"
andrewboyson 35:93c39d260a83 11 #include "mac.h"
andrewboyson 22:914b970356f0 12
andrewboyson 22:914b970356f0 13 #define DEBUG false
andrewboyson 0:faa09bd4e6bf 14
andrewboyson 0:faa09bd4e6bf 15 #define HEADER_SIZE 48
andrewboyson 0:faa09bd4e6bf 16
andrewboyson 0:faa09bd4e6bf 17 #define CLIENT 3
andrewboyson 0:faa09bd4e6bf 18 #define SERVER 4
andrewboyson 0:faa09bd4e6bf 19
andrewboyson 22:914b970356f0 20 uint64_t (*NtpGetClockNowFunction) ();
andrewboyson 22:914b970356f0 21
andrewboyson 22:914b970356f0 22 bool NtpServerEnable = false;
andrewboyson 22:914b970356f0 23 uint64_t (*NtpGetClockRefFunction) ();
andrewboyson 22:914b970356f0 24 int (*NtpGetClockStratumFunction)();
andrewboyson 22:914b970356f0 25 char * (*NtpGetClockIdentFunction) ();
andrewboyson 22:914b970356f0 26
andrewboyson 22:914b970356f0 27 bool NtpClientRequest = false;
andrewboyson 35:93c39d260a83 28 char NtpServerName[DNS_MAX_LABEL_LENGTH+1];
andrewboyson 35:93c39d260a83 29 void (*NtpSetClockFunction) (uint64_t ori, uint64_t rec);
andrewboyson 35:93c39d260a83 30
andrewboyson 22:914b970356f0 31 uint32_t NtpServerIp4 = 0;
andrewboyson 35:93c39d260a83 32 char NtpServerIp6[16];
andrewboyson 17:e475ab861365 33
andrewboyson 0:faa09bd4e6bf 34 __packed struct header {
andrewboyson 0:faa09bd4e6bf 35 unsigned Mode : 3;
andrewboyson 0:faa09bd4e6bf 36 unsigned VN : 3;
andrewboyson 0:faa09bd4e6bf 37 unsigned LI : 2;
andrewboyson 0:faa09bd4e6bf 38 uint8_t Stratum;
andrewboyson 0:faa09bd4e6bf 39 int8_t Poll;
andrewboyson 0:faa09bd4e6bf 40 int8_t Precision;
andrewboyson 0:faa09bd4e6bf 41 uint32_t RootDelay;
andrewboyson 0:faa09bd4e6bf 42 uint32_t Dispersion;
andrewboyson 0:faa09bd4e6bf 43 char RefIdentifier[4];
andrewboyson 0:faa09bd4e6bf 44
andrewboyson 0:faa09bd4e6bf 45 uint64_t RefTimeStamp;
andrewboyson 0:faa09bd4e6bf 46 uint64_t OriTimeStamp;
andrewboyson 0:faa09bd4e6bf 47 uint64_t RecTimeStamp;
andrewboyson 0:faa09bd4e6bf 48 uint64_t TraTimeStamp;
andrewboyson 0:faa09bd4e6bf 49 };
andrewboyson 22:914b970356f0 50
andrewboyson 22:914b970356f0 51 static int handleRequest(struct header* pHeader)
andrewboyson 0:faa09bd4e6bf 52 {
andrewboyson 22:914b970356f0 53 if (!NtpServerEnable) return DO_NOTHING;
andrewboyson 17:e475ab861365 54
andrewboyson 17:e475ab861365 55 if (!NtpGetClockRefFunction || !NtpGetClockNowFunction || !NtpGetClockStratumFunction || !NtpGetClockIdentFunction)
andrewboyson 17:e475ab861365 56 {
andrewboyson 17:e475ab861365 57 LogTimeF("NtpHandleRequest - NTP server is enabled but has not been plumbed into a clock\r\n");
andrewboyson 17:e475ab861365 58 return DO_NOTHING;
andrewboyson 17:e475ab861365 59 }
andrewboyson 22:914b970356f0 60
andrewboyson 20:23f2b29b48ea 61 uint64_t refNtp = NtpGetClockRefFunction();
andrewboyson 20:23f2b29b48ea 62 uint64_t nowNtp = NtpGetClockNowFunction();
andrewboyson 20:23f2b29b48ea 63 int stratum = NtpGetClockStratumFunction();
andrewboyson 20:23f2b29b48ea 64 char* ident = NtpGetClockIdentFunction();
andrewboyson 22:914b970356f0 65
andrewboyson 22:914b970356f0 66 pHeader->Mode = SERVER;
andrewboyson 22:914b970356f0 67 pHeader->LI = 0;
andrewboyson 22:914b970356f0 68 pHeader->Stratum = stratum;
andrewboyson 22:914b970356f0 69 pHeader->Poll = 0;
andrewboyson 22:914b970356f0 70 pHeader->Precision = 0;
andrewboyson 22:914b970356f0 71 pHeader->RootDelay = 0;
andrewboyson 22:914b970356f0 72 pHeader->Dispersion = 0;
andrewboyson 22:914b970356f0 73 pHeader->RefIdentifier[0] = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string.
andrewboyson 22:914b970356f0 74 pHeader->RefIdentifier[1] = ident[1];
andrewboyson 22:914b970356f0 75 pHeader->RefIdentifier[2] = ident[2];
andrewboyson 22:914b970356f0 76 pHeader->RefIdentifier[3] = ident[3];
andrewboyson 22:914b970356f0 77
andrewboyson 22:914b970356f0 78 pHeader->RefTimeStamp = NetToHost64(refNtp);
andrewboyson 22:914b970356f0 79 pHeader->OriTimeStamp = pHeader->TraTimeStamp;
andrewboyson 22:914b970356f0 80 pHeader->RecTimeStamp = NetToHost64(nowNtp);
andrewboyson 22:914b970356f0 81 pHeader->TraTimeStamp = NetToHost64(nowNtp);
andrewboyson 22:914b970356f0 82 return UNICAST;
andrewboyson 22:914b970356f0 83 }
andrewboyson 22:914b970356f0 84 static int handleReply(struct header* pHeader)
andrewboyson 22:914b970356f0 85 {
andrewboyson 22:914b970356f0 86 if (!NtpGetClockNowFunction || !NtpSetClockFunction)
andrewboyson 22:914b970356f0 87 {
andrewboyson 22:914b970356f0 88 LogTimeF("Ntp reply has been received but NTP has not been plumbed into a clock\r\n");
andrewboyson 22:914b970356f0 89 return DO_NOTHING;
andrewboyson 22:914b970356f0 90 }
andrewboyson 22:914b970356f0 91 if (pHeader->Mode != SERVER)
andrewboyson 22:914b970356f0 92 {
andrewboyson 22:914b970356f0 93 LogTimeF("Ntp reply has been received but mode is not SERVER it is %d\r\n", pHeader->Mode);
andrewboyson 22:914b970356f0 94 return DO_NOTHING;
andrewboyson 22:914b970356f0 95 }
andrewboyson 22:914b970356f0 96 if (DEBUG)
andrewboyson 22:914b970356f0 97 {
andrewboyson 22:914b970356f0 98 LogTimeF("NTP received reply\r\n");
andrewboyson 22:914b970356f0 99 LogTimeF("REF %llu\r\n", NetToHost64(pHeader->RefTimeStamp));
andrewboyson 22:914b970356f0 100 LogTimeF("ORI %llu\r\n", NetToHost64(pHeader->OriTimeStamp));
andrewboyson 22:914b970356f0 101 LogTimeF("REC %llu\r\n", NetToHost64(pHeader->RecTimeStamp));
andrewboyson 22:914b970356f0 102 LogTimeF("TRA %llu\r\n", NetToHost64(pHeader->TraTimeStamp));
andrewboyson 22:914b970356f0 103 }
andrewboyson 22:914b970356f0 104 uint64_t ori = NetToHost64(pHeader->OriTimeStamp);
andrewboyson 22:914b970356f0 105 uint64_t rec = NetToHost64(pHeader->RecTimeStamp);
andrewboyson 22:914b970356f0 106
andrewboyson 22:914b970356f0 107 NtpSetClockFunction(ori, rec);
andrewboyson 22:914b970356f0 108 return DO_NOTHING;
andrewboyson 22:914b970356f0 109 }
andrewboyson 22:914b970356f0 110 int NtpHandlePacketReceived(int* pSize, void * pPacket)
andrewboyson 22:914b970356f0 111 {
andrewboyson 22:914b970356f0 112 if (*pSize != HEADER_SIZE)
andrewboyson 22:914b970356f0 113 {
andrewboyson 22:914b970356f0 114 LogTimeF("\r\nNTP packet wrong size %d\r\n", *pSize);
andrewboyson 22:914b970356f0 115 return DO_NOTHING;
andrewboyson 22:914b970356f0 116 }
andrewboyson 22:914b970356f0 117 struct header* pHeader = (struct header*)pPacket;
andrewboyson 17:e475ab861365 118
andrewboyson 0:faa09bd4e6bf 119 switch (pHeader->Mode)
andrewboyson 0:faa09bd4e6bf 120 {
andrewboyson 22:914b970356f0 121 case CLIENT: return handleRequest(pHeader);
andrewboyson 22:914b970356f0 122 case SERVER: return handleReply(pHeader);
andrewboyson 0:faa09bd4e6bf 123 default:
andrewboyson 22:914b970356f0 124 LogTimeF("\r\nNTP packet unknown mode %d\r\n", pHeader->Mode);
andrewboyson 22:914b970356f0 125 return DO_NOTHING;
andrewboyson 0:faa09bd4e6bf 126 }
andrewboyson 22:914b970356f0 127 }
andrewboyson 22:914b970356f0 128 static int sendRequest(void* pPacket, int* pSize)
andrewboyson 22:914b970356f0 129 {
andrewboyson 22:914b970356f0 130 struct header* pHeader = (struct header*)pPacket;
andrewboyson 22:914b970356f0 131
andrewboyson 22:914b970356f0 132 pHeader->Mode = CLIENT;
andrewboyson 22:914b970356f0 133 pHeader->VN = 3;
andrewboyson 22:914b970356f0 134 pHeader->LI = 0;
andrewboyson 22:914b970356f0 135 pHeader->Stratum = 0;
andrewboyson 22:914b970356f0 136 pHeader->Poll = 0;
andrewboyson 22:914b970356f0 137 pHeader->Precision = 0;
andrewboyson 22:914b970356f0 138 pHeader->RootDelay = 0;
andrewboyson 22:914b970356f0 139 pHeader->Dispersion = 0;
andrewboyson 22:914b970356f0 140 pHeader->RefIdentifier[0] = 0;
andrewboyson 22:914b970356f0 141 pHeader->RefIdentifier[1] = 0;
andrewboyson 22:914b970356f0 142 pHeader->RefIdentifier[2] = 0;
andrewboyson 22:914b970356f0 143 pHeader->RefIdentifier[3] = 0;
andrewboyson 22:914b970356f0 144
andrewboyson 22:914b970356f0 145 pHeader->RefTimeStamp = 0;
andrewboyson 22:914b970356f0 146 pHeader->OriTimeStamp = 0;
andrewboyson 22:914b970356f0 147 pHeader->RecTimeStamp = 0;
andrewboyson 22:914b970356f0 148 pHeader->TraTimeStamp = NetToHost64(NtpGetClockNowFunction());
andrewboyson 22:914b970356f0 149 *pSize = HEADER_SIZE;
andrewboyson 22:914b970356f0 150
andrewboyson 22:914b970356f0 151 return UNICAST_NTP;
andrewboyson 0:faa09bd4e6bf 152 }
andrewboyson 35:93c39d260a83 153
andrewboyson 22:914b970356f0 154 int NtpPollForPacketToSend(int type, void* pPacket, int* pSize)
andrewboyson 22:914b970356f0 155 {
andrewboyson 22:914b970356f0 156 if (!NtpClientRequest) return DO_NOTHING; //Wait until a request for time is made
andrewboyson 22:914b970356f0 157 if (type != IPV4) return DO_NOTHING; //Only have an IP4 address at this moment
andrewboyson 22:914b970356f0 158
andrewboyson 35:93c39d260a83 159 if (!NtpServerName[0])
andrewboyson 35:93c39d260a83 160 {
andrewboyson 35:93c39d260a83 161 LogTimeF("NtpPollForRequestToSend - A request to send a client message has been made but no server name has been specified\r\n");
andrewboyson 35:93c39d260a83 162 NtpClientRequest = false;
andrewboyson 35:93c39d260a83 163 return DO_NOTHING;
andrewboyson 35:93c39d260a83 164 }
andrewboyson 35:93c39d260a83 165
andrewboyson 35:93c39d260a83 166 if (!NtpGetClockNowFunction || !NtpSetClockFunction)
andrewboyson 22:914b970356f0 167 {
andrewboyson 22:914b970356f0 168 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 169 NtpClientRequest = false;
andrewboyson 22:914b970356f0 170 return DO_NOTHING;
andrewboyson 22:914b970356f0 171 }
andrewboyson 22:914b970356f0 172
andrewboyson 35:93c39d260a83 173 //Check if have IP, if not, then request it and stop
andrewboyson 35:93c39d260a83 174 NrNameToIp4(NtpServerName, &NtpServerIp4);
andrewboyson 35:93c39d260a83 175 if (!NtpServerIp4)
andrewboyson 22:914b970356f0 176 {
andrewboyson 35:93c39d260a83 177 NrMakeRequestForIp4FromName(NtpServerName); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 22:914b970356f0 178 return DO_NOTHING;
andrewboyson 22:914b970356f0 179 }
andrewboyson 35:93c39d260a83 180
andrewboyson 35:93c39d260a83 181 //Check if have MAC and, if not, request it and stop
andrewboyson 35:93c39d260a83 182 char mac[6];
andrewboyson 35:93c39d260a83 183 ArIpToMac4(NtpServerIp4, mac);
andrewboyson 35:93c39d260a83 184 if (MacIsEmpty(mac))
andrewboyson 35:93c39d260a83 185 {
andrewboyson 35:93c39d260a83 186 ArMakeRequestForMacFromIp4(NtpServerIp4); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 35:93c39d260a83 187 return DO_NOTHING;
andrewboyson 35:93c39d260a83 188 }
andrewboyson 35:93c39d260a83 189
andrewboyson 35:93c39d260a83 190 //Have IP and MAC so send request
andrewboyson 35:93c39d260a83 191 if (DEBUG) LogTimeF("Sending NTP request\r\n");
andrewboyson 35:93c39d260a83 192 NtpClientRequest = false;
andrewboyson 35:93c39d260a83 193 return sendRequest(pPacket, pSize);
andrewboyson 22:914b970356f0 194 }
andrewboyson 22:914b970356f0 195