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 01 15:06:59 2017 +0000
Revision:
34:e3a7bff69bfc
Parent:
30:e34173b7585c
Child:
35:93c39d260a83
Added quiet drop of ICMP unreacheable messages

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