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:
Wed Oct 04 07:51:02 2017 +0000
Revision:
37:793b39683406
Parent:
36:900e24b27bfb
Child:
42:222a4f45f916
Added trace back and trace forward to log 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 37:793b39683406 4 #include "action.h"
andrewboyson 30:e34173b7585c 5 #include "icmp6.h"
andrewboyson 30:e34173b7585c 6 #include "udptcp6.h"
andrewboyson 30:e34173b7585c 7 #include "ar.h"
andrewboyson 35:93c39d260a83 8 #include "nr.h"
andrewboyson 30:e34173b7585c 9 #include "slaac.h"
andrewboyson 30:e34173b7585c 10 #include "eth.h"
andrewboyson 30:e34173b7585c 11 #include "ip.h"
andrewboyson 30:e34173b7585c 12 #include "ip6.h"
andrewboyson 30:e34173b7585c 13 #include "ra.h"
andrewboyson 30:e34173b7585c 14 #include "io.h"
andrewboyson 35:93c39d260a83 15 #include "ntp.h"
andrewboyson 36:900e24b27bfb 16 #include "mac.h"
andrewboyson 11:c051adb70c5a 17
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 37:793b39683406 78 void Ip6DestIpFromDest(int dest, char* pDstIp)
andrewboyson 11:c051adb70c5a 79 {
andrewboyson 37:793b39683406 80 switch (dest)
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 37:793b39683406 90 LogTimeF("Ip6DestIpFromDest unknown destination %d\r\n", dest);
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 11:c051adb70c5a 114 static void readHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 115 {
andrewboyson 11:c051adb70c5a 116 version = (pHeader->versionTrafficFlow >> 4) & 0xF;
andrewboyson 11:c051adb70c5a 117 dataLength = NetToHost16(pHeader->dataLength);
andrewboyson 11:c051adb70c5a 118 protocol = pHeader->protocol;
andrewboyson 11:c051adb70c5a 119 hoplimit = pHeader->hoplimit;
andrewboyson 36:900e24b27bfb 120 Ip6Copy(srcIp, pHeader->src);
andrewboyson 36:900e24b27bfb 121 Ip6Copy(dstIp, pHeader->dst);
andrewboyson 11:c051adb70c5a 122 pData = (char*)pHeader + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 123 }
andrewboyson 11:c051adb70c5a 124 static void writeHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 125 {
andrewboyson 36:900e24b27bfb 126 pHeader->versionTrafficFlow = version << 4;
andrewboyson 36:900e24b27bfb 127 pHeader->protocol = protocol;
andrewboyson 36:900e24b27bfb 128 pHeader->hoplimit = 255;
andrewboyson 36:900e24b27bfb 129 Ip6Copy(pHeader->dst, dstIp);
andrewboyson 36:900e24b27bfb 130 Ip6Copy(pHeader->src, srcIp);
andrewboyson 36:900e24b27bfb 131 pHeader->dataLength = NetToHost16(dataLength);
andrewboyson 11:c051adb70c5a 132 }
andrewboyson 11:c051adb70c5a 133
andrewboyson 37:793b39683406 134 static void logHeader()
andrewboyson 11:c051adb70c5a 135 {
andrewboyson 11:c051adb70c5a 136 char text[100];
andrewboyson 37:793b39683406 137 Log("IP6 header\r\n");
andrewboyson 11:c051adb70c5a 138 LogF(" Version %d\r\n", version);
andrewboyson 11:c051adb70c5a 139 LogF(" Payload length %d\r\n", dataLength);
andrewboyson 11:c051adb70c5a 140 LogF(" Hop limit %d\r\n", hoplimit);
andrewboyson 14:e75a59c1123d 141 IpProtocolToString(protocol, sizeof(text), text);
andrewboyson 11:c051adb70c5a 142 LogF(" Protocol %s\r\n", text);
andrewboyson 35:93c39d260a83 143 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 144 LogF(" Source IP %s\r\n", text);
andrewboyson 35:93c39d260a83 145 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 11:c051adb70c5a 146 LogF(" Destination IP %s\r\n", text);
andrewboyson 11:c051adb70c5a 147 }
andrewboyson 11:c051adb70c5a 148
andrewboyson 10:f0854784e960 149 static bool getIsSolicited(char* p)
andrewboyson 10:f0854784e960 150 {
andrewboyson 10:f0854784e960 151 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 152 if (*p++ != 0x02) return false;
andrewboyson 10:f0854784e960 153
andrewboyson 10:f0854784e960 154 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 155 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 156
andrewboyson 10:f0854784e960 157 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 158 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 159
andrewboyson 10:f0854784e960 160 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 161 if (*p++ != 0x00) 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++ != 0x01) return false;
andrewboyson 10:f0854784e960 168
andrewboyson 10:f0854784e960 169 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 170
andrewboyson 10:f0854784e960 171 return true;
andrewboyson 10:f0854784e960 172 }
andrewboyson 10:f0854784e960 173 static bool getIsSameGroup(char* pA, char* pB)
andrewboyson 10:f0854784e960 174 {
andrewboyson 10:f0854784e960 175 pA += 13;
andrewboyson 10:f0854784e960 176 pB += 13;
andrewboyson 10:f0854784e960 177 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 178 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 179 return *pA == *pB;
andrewboyson 10:f0854784e960 180 }
andrewboyson 37:793b39683406 181 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 182 static void trace()
andrewboyson 10:f0854784e960 183 {
andrewboyson 37:793b39683406 184 pTraceBack();
andrewboyson 37:793b39683406 185 logHeader();
andrewboyson 37:793b39683406 186 }
andrewboyson 37:793b39683406 187 int Ip6HandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
andrewboyson 37:793b39683406 188 {
andrewboyson 37:793b39683406 189 pTraceBack = traceback;
andrewboyson 37:793b39683406 190
andrewboyson 10:f0854784e960 191 struct header * pHeader = (header*)pPacket;
andrewboyson 11:c051adb70c5a 192 readHeader(pHeader);
andrewboyson 10:f0854784e960 193
andrewboyson 35:93c39d260a83 194 bool isMe = SlaacIsMe(dstIp);
andrewboyson 35:93c39d260a83 195 bool isMulticast = dstIp[0] == 0xFF;
andrewboyson 35:93c39d260a83 196 bool isSolicited = getIsSolicited(dstIp);
andrewboyson 35:93c39d260a83 197 bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp);
andrewboyson 10:f0854784e960 198
andrewboyson 34:e3a7bff69bfc 199 bool doIt = isMe || (isMulticast && !isSolicited) || (isGroup && isSolicited);
andrewboyson 10:f0854784e960 200
andrewboyson 14:e75a59c1123d 201 if (!doIt)
andrewboyson 14:e75a59c1123d 202 {
andrewboyson 37:793b39683406 203 if (SHOW_FILTERED)
andrewboyson 15:6ca6778168b1 204 {
andrewboyson 15:6ca6778168b1 205 char text[100];
andrewboyson 35:93c39d260a83 206 Ip6AddressToString(dstIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 207 LogTimeF("IP6 filtered out ip %s ", text);
andrewboyson 35:93c39d260a83 208 Ip6AddressToString(srcIp, sizeof(text), text);
andrewboyson 15:6ca6778168b1 209 LogF("from %s \r\n", text);
andrewboyson 15:6ca6778168b1 210 }
andrewboyson 14:e75a59c1123d 211 return DO_NOTHING;
andrewboyson 14:e75a59c1123d 212 }
andrewboyson 10:f0854784e960 213
andrewboyson 35:93c39d260a83 214 ArAddIp6Record(pSrcMac, srcIp);
andrewboyson 35:93c39d260a83 215 NrMakeRequestForNameFromIp6(srcIp);
andrewboyson 11:c051adb70c5a 216
andrewboyson 10:f0854784e960 217 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 218 switch (protocol)
andrewboyson 10:f0854784e960 219 {
andrewboyson 35:93c39d260a83 220 case HOPOPT: action = DO_NOTHING; break;
andrewboyson 37:793b39683406 221 case ICMP6: action = Icmp6HandleReceivedPacket(trace, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 37:793b39683406 222 case UDP: action = Udp6HandleReceivedPacket(trace, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 37:793b39683406 223 case TCP: action = Tcp6HandleReceivedPacket(trace, srcIp, dstIp, &dataLength, pData); break;
andrewboyson 10:f0854784e960 224 default:
andrewboyson 37:793b39683406 225 LogTimeF("IP6 protocol %d unhandled\r\n", protocol);
andrewboyson 10:f0854784e960 226 return DO_NOTHING;
andrewboyson 10:f0854784e960 227 }
andrewboyson 11:c051adb70c5a 228 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 229
andrewboyson 36:900e24b27bfb 230 MacCopy(pDstMac, pSrcMac);
andrewboyson 10:f0854784e960 231
andrewboyson 11:c051adb70c5a 232 writeHeader(pHeader);
andrewboyson 11:c051adb70c5a 233
andrewboyson 10:f0854784e960 234 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 235
andrewboyson 37:793b39683406 236 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 237
andrewboyson 10:f0854784e960 238 return action;
andrewboyson 10:f0854784e960 239 }
andrewboyson 10:f0854784e960 240 int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 241 {
andrewboyson 11:c051adb70c5a 242 pData = (char*)pPacket + HEADER_LENGTH;
andrewboyson 11:c051adb70c5a 243 dataLength = 0;
andrewboyson 11:c051adb70c5a 244 version = 6;
andrewboyson 11:c051adb70c5a 245 hoplimit = 255;
andrewboyson 10:f0854784e960 246
andrewboyson 10:f0854784e960 247 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 248 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 249 {
andrewboyson 35:93c39d260a83 250 action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 251 protocol = ICMP6;
andrewboyson 10:f0854784e960 252 }
andrewboyson 10:f0854784e960 253
andrewboyson 10:f0854784e960 254 if (action == DO_NOTHING)
andrewboyson 10:f0854784e960 255 {
andrewboyson 35:93c39d260a83 256 action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 257 protocol = UDP;
andrewboyson 10:f0854784e960 258 }
andrewboyson 11:c051adb70c5a 259 if (!action) return DO_NOTHING;
andrewboyson 37:793b39683406 260
andrewboyson 37:793b39683406 261 int dest = ActionGetDestPart(action);
andrewboyson 37:793b39683406 262 switch (dest)
andrewboyson 11:c051adb70c5a 263 {
andrewboyson 11:c051adb70c5a 264 case UNICAST:
andrewboyson 11:c051adb70c5a 265 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 266 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 267 case UNICAST_NTP:
andrewboyson 35:93c39d260a83 268 ArIpToMac6(dstIp, pDstMac); //Make the remote MAC from NP
andrewboyson 11:c051adb70c5a 269 break;
andrewboyson 22:914b970356f0 270 case MULTICAST_NODE:
andrewboyson 22:914b970356f0 271 case MULTICAST_ROUTER:
andrewboyson 22:914b970356f0 272 case MULTICAST_MDNS:
andrewboyson 22:914b970356f0 273 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 274 case SOLICITED_NODE:
andrewboyson 22:914b970356f0 275 break;
andrewboyson 22:914b970356f0 276 default:
andrewboyson 37:793b39683406 277 LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 22:914b970356f0 278 break;
andrewboyson 11:c051adb70c5a 279 }
andrewboyson 10:f0854784e960 280
andrewboyson 11:c051adb70c5a 281 writeHeader((header*)pPacket);
andrewboyson 11:c051adb70c5a 282
andrewboyson 10:f0854784e960 283 *pSize = HEADER_LENGTH + dataLength;
andrewboyson 10:f0854784e960 284
andrewboyson 37:793b39683406 285 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 286
andrewboyson 10:f0854784e960 287 return action;
andrewboyson 10:f0854784e960 288 }