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:
Thu Aug 10 17:45:37 2017 +0000
Revision:
30:e34173b7585c
Parent:
29:39277bf2003d
Child:
34:e3a7bff69bfc
Added dns address request - only name requests was there before.

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