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:
34:e3a7bff69bfc
Child:
36:900e24b27bfb
Added name resolution and address resolution

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