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:
Mon Sep 25 07:09:32 2017 +0000
Revision:
36:900e24b27bfb
Parent:
35:93c39d260a83
Child:
37:793b39683406
Corrected DNS NameCompare to correctly compare a shortcut name

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 30:e34173b7585c 1 #include "mbed.h"
andrewboyson 30:e34173b7585c 2 #include "log.h"
andrewboyson 30:e34173b7585c 3 #include "net.h"
andrewboyson 30:e34173b7585c 4 #include "icmp6.h"
andrewboyson 30:e34173b7585c 5 #include "udptcp6.h"
andrewboyson 30:e34173b7585c 6 #include "ar.h"
andrewboyson 35:93c39d260a83 7 #include "nr.h"
andrewboyson 30:e34173b7585c 8 #include "slaac.h"
andrewboyson 30:e34173b7585c 9 #include "eth.h"
andrewboyson 30:e34173b7585c 10 #include "ip.h"
andrewboyson 30:e34173b7585c 11 #include "ip6.h"
andrewboyson 30:e34173b7585c 12 #include "ra.h"
andrewboyson 30:e34173b7585c 13 #include "io.h"
andrewboyson 35:93c39d260a83 14 #include "ntp.h"
andrewboyson 36:900e24b27bfb 15 #include "mac.h"
andrewboyson 11:c051adb70c5a 16
andrewboyson 11:c051adb70c5a 17 #define DEBUG false
andrewboyson 34:e3a7bff69bfc 18 #define SHOW_FILTERED true
andrewboyson 11:c051adb70c5a 19
andrewboyson 36:900e24b27bfb 20 void Ip6Clear(char* ip)
andrewboyson 36:900e24b27bfb 21 {
andrewboyson 36:900e24b27bfb 22 *ip = 0;
andrewboyson 36:900e24b27bfb 23 }
andrewboyson 36:900e24b27bfb 24 bool Ip6IsEmpty(char* ip)
andrewboyson 36:900e24b27bfb 25 {
andrewboyson 36:900e24b27bfb 26 return !*ip; //Just check for the first byte being non zero
andrewboyson 36:900e24b27bfb 27 }
andrewboyson 14:e75a59c1123d 28 static void addHexNibble(bool* pAdded, int number, int index, char** pp)
andrewboyson 14:e75a59c1123d 29 {
andrewboyson 14:e75a59c1123d 30 int nibble = number;
andrewboyson 14:e75a59c1123d 31 if (index) nibble >>= 4;
andrewboyson 14:e75a59c1123d 32 nibble &= 0xF;
andrewboyson 14:e75a59c1123d 33
andrewboyson 14:e75a59c1123d 34 if (nibble || *pAdded)
andrewboyson 14:e75a59c1123d 35 {
andrewboyson 14:e75a59c1123d 36 **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
andrewboyson 14:e75a59c1123d 37 *pp += 1;
andrewboyson 14:e75a59c1123d 38 *pAdded = true;
andrewboyson 14:e75a59c1123d 39 }
andrewboyson 14:e75a59c1123d 40 }
andrewboyson 14:e75a59c1123d 41 int Ip6AddressToString(char* pIp, int size, char* pText)
andrewboyson 14:e75a59c1123d 42 {
andrewboyson 14:e75a59c1123d 43 char* pIpE = pIp + 16;
andrewboyson 14:e75a59c1123d 44 char* p = pText;
andrewboyson 14:e75a59c1123d 45 while (true)
andrewboyson 14:e75a59c1123d 46 {
andrewboyson 14:e75a59c1123d 47 bool added = false;
andrewboyson 14:e75a59c1123d 48 if (*pIp || *(pIp + 1))
andrewboyson 14:e75a59c1123d 49 {
andrewboyson 14:e75a59c1123d 50 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 1, &p);
andrewboyson 14:e75a59c1123d 51 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 0, &p);
andrewboyson 14:e75a59c1123d 52 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 1, &p);
andrewboyson 14:e75a59c1123d 53 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 0, &p);
andrewboyson 14:e75a59c1123d 54 }
andrewboyson 14:e75a59c1123d 55
andrewboyson 14:e75a59c1123d 56 pIp += 2;
andrewboyson 14:e75a59c1123d 57 if (pIp >= pIpE) break;
andrewboyson 14:e75a59c1123d 58
andrewboyson 14:e75a59c1123d 59 if (p > pText + size - 2) break; *p++ = ':';
andrewboyson 14:e75a59c1123d 60 }
andrewboyson 14:e75a59c1123d 61 *p = 0;
andrewboyson 14:e75a59c1123d 62 return p - pText;
andrewboyson 14:e75a59c1123d 63 }
andrewboyson 35:93c39d260a83 64 bool Ip6IsSame(char* ipA, char* ipB)
andrewboyson 35:93c39d260a83 65 {
andrewboyson 35:93c39d260a83 66 return memcmp(ipA, ipB, 16) == 0;
andrewboyson 35:93c39d260a83 67 }
andrewboyson 36:900e24b27bfb 68 void Ip6Copy(char* ipTo, char* ipFrom)
andrewboyson 35:93c39d260a83 69 {
andrewboyson 35:93c39d260a83 70 memcpy(ipTo, ipFrom, 16);
andrewboyson 35:93c39d260a83 71 }
andrewboyson 14:e75a59c1123d 72
andrewboyson 11:c051adb70c5a 73 char Ip6AllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
andrewboyson 11:c051adb70c5a 74 char Ip6AllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
andrewboyson 11:c051adb70c5a 75 char Ip6Mdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
andrewboyson 11:c051adb70c5a 76 char Ip6Llmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03};
andrewboyson 11:c051adb70c5a 77
andrewboyson 11:c051adb70c5a 78 void Ip6DestIpFromAction(int action, char* pDstIp)
andrewboyson 11:c051adb70c5a 79 {
andrewboyson 11:c051adb70c5a 80 switch (action)
andrewboyson 11:c051adb70c5a 81 {
andrewboyson 36:900e24b27bfb 82 case UNICAST: break;
andrewboyson 36:900e24b27bfb 83 case UNICAST_DNS: Ip6Copy(pDstIp, RaDnsServer ); break;
andrewboyson 36:900e24b27bfb 84 case UNICAST_NTP: Ip6Copy(pDstIp, NtpServerIp6 ); break;
andrewboyson 36:900e24b27bfb 85 case MULTICAST_NODE: Ip6Copy(pDstIp, Ip6AllNodes ); break;
andrewboyson 36:900e24b27bfb 86 case MULTICAST_ROUTER: Ip6Copy(pDstIp, Ip6AllRouters); break;
andrewboyson 36:900e24b27bfb 87 case MULTICAST_MDNS: Ip6Copy(pDstIp, Ip6Mdns ); break;
andrewboyson 36:900e24b27bfb 88 case MULTICAST_LLMNR: Ip6Copy(pDstIp, Ip6Llmnr ); break;
andrewboyson 11:c051adb70c5a 89 default:
andrewboyson 11:c051adb70c5a 90 LogTimeF("Ip6 DestIpFromAction unknown action %d\r\n", action);
andrewboyson 11:c051adb70c5a 91 break;
andrewboyson 11:c051adb70c5a 92 }
andrewboyson 11:c051adb70c5a 93 }
andrewboyson 10:f0854784e960 94
andrewboyson 10:f0854784e960 95 #define HEADER_LENGTH 40
andrewboyson 10:f0854784e960 96 __packed struct header
andrewboyson 10:f0854784e960 97 {
andrewboyson 10:f0854784e960 98 uint32_t versionTrafficFlow;
andrewboyson 10:f0854784e960 99 uint16_t dataLength;
andrewboyson 10:f0854784e960 100 uint8_t protocol;
andrewboyson 10:f0854784e960 101 uint8_t hoplimit;
andrewboyson 10:f0854784e960 102 char src[16];
andrewboyson 10:f0854784e960 103 char dst[16];
andrewboyson 10:f0854784e960 104 };
andrewboyson 11:c051adb70c5a 105
andrewboyson 11:c051adb70c5a 106 static uint8_t version;
andrewboyson 11:c051adb70c5a 107 static int dataLength;
andrewboyson 11:c051adb70c5a 108 static uint8_t protocol;
andrewboyson 11:c051adb70c5a 109 static uint8_t hoplimit;
andrewboyson 35:93c39d260a83 110 static char srcIp[16];
andrewboyson 35:93c39d260a83 111 static char dstIp[16];
andrewboyson 11:c051adb70c5a 112 static void* pData;
andrewboyson 11:c051adb70c5a 113
andrewboyson 35:93c39d260a83 114 void Ip6LogHeaderSrc()
andrewboyson 35:93c39d260a83 115 {
andrewboyson 35:93c39d260a83 116 char text[64];
andrewboyson 35:93c39d260a83 117 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 35:93c39d260a83 118 Log(text);
andrewboyson 35:93c39d260a83 119 }
andrewboyson 35:93c39d260a83 120 void Ip6LogHeaderDst()
andrewboyson 35:93c39d260a83 121 {
andrewboyson 35:93c39d260a83 122 char text[64];
andrewboyson 35:93c39d260a83 123 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 35:93c39d260a83 124 Log(text);
andrewboyson 35:93c39d260a83 125 }
andrewboyson 35:93c39d260a83 126
andrewboyson 11:c051adb70c5a 127 static void readHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 128 {
andrewboyson 11:c051adb70c5a 129 version = (pHeader->versionTrafficFlow >> 4) & 0xF;
andrewboyson 11:c051adb70c5a 130 dataLength = NetToHost16(pHeader->dataLength);
andrewboyson 11:c051adb70c5a 131 protocol = pHeader->protocol;
andrewboyson 11:c051adb70c5a 132 hoplimit = pHeader->hoplimit;
andrewboyson 36:900e24b27bfb 133 Ip6Copy(srcIp, pHeader->src);
andrewboyson 36:900e24b27bfb 134 Ip6Copy(dstIp, pHeader->dst);
andrewboyson 11:c051adb70c5a 135 pData = (char*)pHeader + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 136 }
andrewboyson 11:c051adb70c5a 137 static void writeHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 138 {
andrewboyson 36:900e24b27bfb 139 pHeader->versionTrafficFlow = version << 4;
andrewboyson 36:900e24b27bfb 140 pHeader->protocol = protocol;
andrewboyson 36:900e24b27bfb 141 pHeader->hoplimit = 255;
andrewboyson 36:900e24b27bfb 142 Ip6Copy(pHeader->dst, dstIp);
andrewboyson 36:900e24b27bfb 143 Ip6Copy(pHeader->src, srcIp);
andrewboyson 36:900e24b27bfb 144 pHeader->dataLength = NetToHost16(dataLength);
andrewboyson 11:c051adb70c5a 145 }
andrewboyson 11:c051adb70c5a 146
andrewboyson 11:c051adb70c5a 147 static void logHeader(char* title)
andrewboyson 11:c051adb70c5a 148 {
andrewboyson 11:c051adb70c5a 149 char text[100];
andrewboyson 11:c051adb70c5a 150 LogTimeF("%s\r\n", title);
andrewboyson 11:c051adb70c5a 151 LogF(" Version %d\r\n", version);
andrewboyson 11:c051adb70c5a 152 LogF(" Payload length %d\r\n", dataLength);
andrewboyson 11:c051adb70c5a 153 LogF(" Hop limit %d\r\n", hoplimit);
andrewboyson 14:e75a59c1123d 154 IpProtocolToString(protocol, sizeof(text), text);
andrewboyson 11:c051adb70c5a 155 LogF(" Protocol %s\r\n", text);
andrewboyson 35:93c39d260a83 156 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 157 LogF(" Source IP %s\r\n", text);
andrewboyson 35:93c39d260a83 158 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 159 LogF(" Destination IP %s\r\n", text);
andrewboyson 11:c051adb70c5a 160 }
andrewboyson 11:c051adb70c5a 161
andrewboyson 10:f0854784e960 162 static bool getIsSolicited(char* p)
andrewboyson 10:f0854784e960 163 {
andrewboyson 10:f0854784e960 164 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 165 if (*p++ != 0x02) return false;
andrewboyson 10:f0854784e960 166
andrewboyson 10:f0854784e960 167 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 168 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 169
andrewboyson 10:f0854784e960 170 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 171 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 172
andrewboyson 10:f0854784e960 173 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 174 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 175
andrewboyson 10:f0854784e960 176 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 177 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 178
andrewboyson 10:f0854784e960 179 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 180 if (*p++ != 0x01) return false;
andrewboyson 10:f0854784e960 181
andrewboyson 10:f0854784e960 182 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 183
andrewboyson 10:f0854784e960 184 return true;
andrewboyson 10:f0854784e960 185 }
andrewboyson 10:f0854784e960 186 static bool getIsSameGroup(char* pA, char* pB)
andrewboyson 10:f0854784e960 187 {
andrewboyson 10:f0854784e960 188 pA += 13;
andrewboyson 10:f0854784e960 189 pB += 13;
andrewboyson 10:f0854784e960 190 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 191 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 192 return *pA == *pB;
andrewboyson 10:f0854784e960 193 }
andrewboyson 10:f0854784e960 194 int Ip6HandleReceivedPacket(char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 195 {
andrewboyson 10:f0854784e960 196 struct header * pHeader = (header*)pPacket;
andrewboyson 11:c051adb70c5a 197 readHeader(pHeader);
andrewboyson 10:f0854784e960 198
andrewboyson 35:93c39d260a83 199 bool isMe = SlaacIsMe(dstIp);
andrewboyson 35:93c39d260a83 200 bool isMulticast = dstIp[0] == 0xFF;
andrewboyson 35:93c39d260a83 201 bool isSolicited = getIsSolicited(dstIp);
andrewboyson 35:93c39d260a83 202 bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp);
andrewboyson 10:f0854784e960 203
andrewboyson 34:e3a7bff69bfc 204 bool doIt = isMe || (isMulticast && !isSolicited) || (isGroup && isSolicited);
andrewboyson 10:f0854784e960 205
andrewboyson 14:e75a59c1123d 206 if (!doIt)
andrewboyson 14:e75a59c1123d 207 {
andrewboyson 34:e3a7bff69bfc 208 if (DEBUG || SHOW_FILTERED)
andrewboyson 15:6ca6778168b1 209 {
andrewboyson 15:6ca6778168b1 210 char text[100];
andrewboyson 35:93c39d260a83 211 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 212 LogTimeF("IP6 filtered out ip %s ", text);
andrewboyson 35:93c39d260a83 213 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 214 LogF("from %s \r\n", text);
andrewboyson 15:6ca6778168b1 215 }
andrewboyson 14:e75a59c1123d 216 return DO_NOTHING;
andrewboyson 14:e75a59c1123d 217 }
andrewboyson 10:f0854784e960 218
andrewboyson 35:93c39d260a83 219 ArAddIp6Record(pSrcMac, srcIp);
andrewboyson 35:93c39d260a83 220 NrMakeRequestForNameFromIp6(srcIp);
andrewboyson 11:c051adb70c5a 221
andrewboyson 11:c051adb70c5a 222 if (DEBUG) logHeader("IP6 packet received");
andrewboyson 11:c051adb70c5a 223
andrewboyson 10:f0854784e960 224 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 225 switch (protocol)
andrewboyson 10:f0854784e960 226 {
andrewboyson 35:93c39d260a83 227 case HOPOPT: action = DO_NOTHING; break;
andrewboyson 35:93c39d260a83 228 case ICMP6: action = Icmp6HandleReceivedPacket(srcIp, dstIp, &dataLength, pData); break;
andrewboyson 35:93c39d260a83 229 case UDP: action = Udp6HandleReceivedPacket(srcIp, dstIp, &dataLength, pData); break;
andrewboyson 35:93c39d260a83 230 case TCP: action = Tcp6HandleReceivedPacket(srcIp, dstIp, &dataLength, pData); break;
andrewboyson 10:f0854784e960 231 default:
andrewboyson 11:c051adb70c5a 232 logHeader("IP6 packet unhandled");
andrewboyson 10:f0854784e960 233 return DO_NOTHING;
andrewboyson 10:f0854784e960 234 }
andrewboyson 11:c051adb70c5a 235 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 236
andrewboyson 36:900e24b27bfb 237 MacCopy(pDstMac, pSrcMac);
andrewboyson 11:c051adb70c5a 238
andrewboyson 11:c051adb70c5a 239 if (DEBUG) logHeader("IP6 packet replied to");
andrewboyson 10:f0854784e960 240
andrewboyson 11:c051adb70c5a 241 writeHeader(pHeader);
andrewboyson 11:c051adb70c5a 242
andrewboyson 10:f0854784e960 243 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 244
andrewboyson 10:f0854784e960 245 return action;
andrewboyson 10:f0854784e960 246 }
andrewboyson 10:f0854784e960 247 int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 248 {
andrewboyson 11:c051adb70c5a 249 pData = (char*)pPacket + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 250 dataLength = 0;
andrewboyson 11:c051adb70c5a 251 version = 6;
andrewboyson 11:c051adb70c5a 252 hoplimit = 255;
andrewboyson 10:f0854784e960 253
andrewboyson 10:f0854784e960 254 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 255 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 256 {
andrewboyson 35:93c39d260a83 257 action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 258 protocol = ICMP6;
andrewboyson 10:f0854784e960 259 }
andrewboyson 10:f0854784e960 260
andrewboyson 10:f0854784e960 261 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 262 {
andrewboyson 35:93c39d260a83 263 action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 264 protocol = UDP;
andrewboyson 10:f0854784e960 265 }
andrewboyson 11:c051adb70c5a 266 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 267 switch (action)
andrewboyson 11:c051adb70c5a 268 {
andrewboyson 11:c051adb70c5a 269 case UNICAST:
andrewboyson 11:c051adb70c5a 270 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 271 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 272 case UNICAST_NTP:
andrewboyson 35:93c39d260a83 273 ArIpToMac6(dstIp, pDstMac); //Make the remote MAC from NP
andrewboyson 11:c051adb70c5a 274 break;
andrewboyson 22:914b970356f0 275 case MULTICAST_NODE:
andrewboyson 22:914b970356f0 276 case MULTICAST_ROUTER:
andrewboyson 22:914b970356f0 277 case MULTICAST_MDNS:
andrewboyson 22:914b970356f0 278 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 279 case SOLICITED_NODE:
andrewboyson 22:914b970356f0 280 break;
andrewboyson 22:914b970356f0 281 default:
andrewboyson 22:914b970356f0 282 LogTimeF("Ip6PollForPacketToSend - undefined action %d\r\n", action);
andrewboyson 22:914b970356f0 283 break;
andrewboyson 22:914b970356f0 284
andrewboyson 11:c051adb70c5a 285 }
andrewboyson 11:c051adb70c5a 286
andrewboyson 11:c051adb70c5a 287 if (DEBUG) logHeader("IP6 polled packet sent");
andrewboyson 10:f0854784e960 288
andrewboyson 11:c051adb70c5a 289 writeHeader((header*)pPacket);
andrewboyson 11:c051adb70c5a 290
andrewboyson 10:f0854784e960 291 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 292
andrewboyson 10:f0854784e960 293 return action;
andrewboyson 10:f0854784e960 294 }