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 Dec 14 20:55:40 2017 +0000
Revision:
59:e0e556c8bd46
Parent:
57:e0fb648acf48
Added buffer length to help avoid over runs

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 52:fbc5a46b5e16 1 #include "mbed.h"
andrewboyson 52:fbc5a46b5e16 2 #include "log.h"
andrewboyson 49:1a6336f2b3f9 3 #include "net.h"
andrewboyson 49:1a6336f2b3f9 4 #include "action.h"
andrewboyson 49:1a6336f2b3f9 5 #include "icmp6.h"
andrewboyson 49:1a6336f2b3f9 6 #include "udptcp6.h"
andrewboyson 49:1a6336f2b3f9 7 #include "ar6.h"
andrewboyson 50:492f2d2954e4 8 #include "nr6.h"
andrewboyson 49:1a6336f2b3f9 9 #include "slaac.h"
andrewboyson 49:1a6336f2b3f9 10 #include "eth.h"
andrewboyson 49:1a6336f2b3f9 11 #include "ip.h"
andrewboyson 49:1a6336f2b3f9 12 #include "ip6addr.h"
andrewboyson 49:1a6336f2b3f9 13 #include "ndp.h"
andrewboyson 49:1a6336f2b3f9 14 #include "io.h"
andrewboyson 49:1a6336f2b3f9 15 #include "ntp.h"
andrewboyson 49:1a6336f2b3f9 16 #include "mac.h"
andrewboyson 49:1a6336f2b3f9 17 #include "http.h"
andrewboyson 11:c051adb70c5a 18
andrewboyson 48:952dddb74b8b 19 bool Ip6Trace = true;
andrewboyson 11:c051adb70c5a 20
andrewboyson 10:f0854784e960 21 __packed struct header
andrewboyson 10:f0854784e960 22 {
andrewboyson 10:f0854784e960 23 uint32_t versionTrafficFlow;
andrewboyson 10:f0854784e960 24 uint16_t dataLength;
andrewboyson 10:f0854784e960 25 uint8_t protocol;
andrewboyson 10:f0854784e960 26 uint8_t hoplimit;
andrewboyson 10:f0854784e960 27 char src[16];
andrewboyson 10:f0854784e960 28 char dst[16];
andrewboyson 10:f0854784e960 29 };
andrewboyson 11:c051adb70c5a 30
andrewboyson 11:c051adb70c5a 31 static uint8_t version;
andrewboyson 11:c051adb70c5a 32 static int dataLength;
andrewboyson 11:c051adb70c5a 33 static uint8_t protocol;
andrewboyson 11:c051adb70c5a 34 static uint8_t hoplimit;
andrewboyson 35:93c39d260a83 35 static char srcIp[16];
andrewboyson 35:93c39d260a83 36 static char dstIp[16];
andrewboyson 11:c051adb70c5a 37 static void* pData;
andrewboyson 11:c051adb70c5a 38
andrewboyson 11:c051adb70c5a 39 static void readHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 40 {
andrewboyson 11:c051adb70c5a 41 version = (pHeader->versionTrafficFlow >> 4) & 0xF;
andrewboyson 11:c051adb70c5a 42 dataLength = NetToHost16(pHeader->dataLength);
andrewboyson 11:c051adb70c5a 43 protocol = pHeader->protocol;
andrewboyson 11:c051adb70c5a 44 hoplimit = pHeader->hoplimit;
andrewboyson 49:1a6336f2b3f9 45 Ip6AddressCopy(srcIp, pHeader->src);
andrewboyson 49:1a6336f2b3f9 46 Ip6AddressCopy(dstIp, pHeader->dst);
andrewboyson 59:e0e556c8bd46 47 pData = (char*)pHeader + sizeof(header);
andrewboyson 11:c051adb70c5a 48 }
andrewboyson 11:c051adb70c5a 49 static void writeHeader(struct header * pHeader)
andrewboyson 11:c051adb70c5a 50 {
andrewboyson 49:1a6336f2b3f9 51 pHeader->versionTrafficFlow = version << 4;
andrewboyson 49:1a6336f2b3f9 52 pHeader->protocol = protocol;
andrewboyson 49:1a6336f2b3f9 53 pHeader->hoplimit = hoplimit;
andrewboyson 49:1a6336f2b3f9 54 Ip6AddressCopy(pHeader->dst, dstIp);
andrewboyson 49:1a6336f2b3f9 55 Ip6AddressCopy(pHeader->src, srcIp);
andrewboyson 49:1a6336f2b3f9 56 pHeader->dataLength = NetToHost16(dataLength);
andrewboyson 11:c051adb70c5a 57 }
andrewboyson 11:c051adb70c5a 58
andrewboyson 37:793b39683406 59 static void logHeader()
andrewboyson 11:c051adb70c5a 60 {
andrewboyson 43:bc028d5a6424 61 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 62 {
andrewboyson 43:bc028d5a6424 63 Log("IP6 header\r\n");
andrewboyson 43:bc028d5a6424 64 LogF(" Version %d\r\n", version);
andrewboyson 43:bc028d5a6424 65 LogF(" Payload length %d\r\n", dataLength);
andrewboyson 43:bc028d5a6424 66 LogF(" Hop limit %d\r\n", hoplimit);
andrewboyson 47:73af5c0b0dc2 67 LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n");
andrewboyson 47:73af5c0b0dc2 68 Log (" Source IP "); Ip6AddressLog(srcIp); Log("\r\n");
andrewboyson 47:73af5c0b0dc2 69 Log (" Destination IP "); Ip6AddressLog(dstIp); Log("\r\n");
andrewboyson 43:bc028d5a6424 70 }
andrewboyson 43:bc028d5a6424 71 else
andrewboyson 43:bc028d5a6424 72 {
andrewboyson 44:83ce5ace337b 73 Log("IP6 header ");
andrewboyson 47:73af5c0b0dc2 74 IpProtocolLog(protocol);
andrewboyson 43:bc028d5a6424 75 Log(" ");
andrewboyson 47:73af5c0b0dc2 76 Ip6AddressLog(srcIp);
andrewboyson 43:bc028d5a6424 77 Log(" >>> ");
andrewboyson 47:73af5c0b0dc2 78 Ip6AddressLog(dstIp);
andrewboyson 43:bc028d5a6424 79 Log("\r\n");
andrewboyson 43:bc028d5a6424 80 }
andrewboyson 11:c051adb70c5a 81 }
andrewboyson 11:c051adb70c5a 82
andrewboyson 10:f0854784e960 83 static bool getIsSolicited(char* p)
andrewboyson 10:f0854784e960 84 {
andrewboyson 10:f0854784e960 85 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 86 if (*p++ != 0x02) return false;
andrewboyson 10:f0854784e960 87
andrewboyson 10:f0854784e960 88 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 89 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 90
andrewboyson 10:f0854784e960 91 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 92 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 93
andrewboyson 10:f0854784e960 94 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 95 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 96
andrewboyson 10:f0854784e960 97 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 98 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 99
andrewboyson 10:f0854784e960 100 if (*p++ != 0x00) return false;
andrewboyson 10:f0854784e960 101 if (*p++ != 0x01) return false;
andrewboyson 10:f0854784e960 102
andrewboyson 10:f0854784e960 103 if (*p++ != 0xff) return false;
andrewboyson 10:f0854784e960 104
andrewboyson 10:f0854784e960 105 return true;
andrewboyson 10:f0854784e960 106 }
andrewboyson 10:f0854784e960 107 static bool getIsSameGroup(char* pA, char* pB)
andrewboyson 10:f0854784e960 108 {
andrewboyson 10:f0854784e960 109 pA += 13;
andrewboyson 10:f0854784e960 110 pB += 13;
andrewboyson 10:f0854784e960 111 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 112 if (*pA++ != *pB++) return false;
andrewboyson 10:f0854784e960 113 return *pA == *pB;
andrewboyson 10:f0854784e960 114 }
andrewboyson 37:793b39683406 115 static void (*pTraceBack)(void);
andrewboyson 37:793b39683406 116 static void trace()
andrewboyson 10:f0854784e960 117 {
andrewboyson 37:793b39683406 118 pTraceBack();
andrewboyson 37:793b39683406 119 logHeader();
andrewboyson 37:793b39683406 120 }
andrewboyson 59:e0e556c8bd46 121 int Ip6HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote)
andrewboyson 37:793b39683406 122 {
andrewboyson 37:793b39683406 123 pTraceBack = traceback;
andrewboyson 37:793b39683406 124
andrewboyson 59:e0e556c8bd46 125 struct header* pHeaderRx = (header*)pPacketRx;
andrewboyson 59:e0e556c8bd46 126 struct header* pHeaderTx = (header*)pPacketTx;
andrewboyson 59:e0e556c8bd46 127
andrewboyson 59:e0e556c8bd46 128 char* pDataRx = (char*)pHeaderRx + sizeof(header);
andrewboyson 59:e0e556c8bd46 129 char* pDataTx = (char*)pHeaderTx + sizeof(header);
andrewboyson 59:e0e556c8bd46 130
andrewboyson 59:e0e556c8bd46 131 readHeader(pHeaderRx); //This also fetches the datalength out of the header
andrewboyson 59:e0e556c8bd46 132 int dataLengthRx = dataLength;
andrewboyson 59:e0e556c8bd46 133 if (dataLengthRx > sizeRx) dataLengthRx = sizeRx; //Do not exceed the buffer size
andrewboyson 59:e0e556c8bd46 134
andrewboyson 59:e0e556c8bd46 135 int dataLengthTx = *pSizeTx;
andrewboyson 10:f0854784e960 136
andrewboyson 44:83ce5ace337b 137 int scope = SlaacScope(dstIp);
andrewboyson 35:93c39d260a83 138 bool isMulticast = dstIp[0] == 0xFF;
andrewboyson 35:93c39d260a83 139 bool isSolicited = getIsSolicited(dstIp);
andrewboyson 35:93c39d260a83 140 bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp);
andrewboyson 10:f0854784e960 141
andrewboyson 44:83ce5ace337b 142 bool doIt = scope || (isMulticast && !isSolicited) || (isGroup && isSolicited);
andrewboyson 10:f0854784e960 143
andrewboyson 14:e75a59c1123d 144 if (!doIt)
andrewboyson 14:e75a59c1123d 145 {
andrewboyson 48:952dddb74b8b 146 if (Ip6Trace)
andrewboyson 15:6ca6778168b1 147 {
andrewboyson 47:73af5c0b0dc2 148 LogTime("IP6 filtered out ip ");
andrewboyson 47:73af5c0b0dc2 149 Ip6AddressLog(dstIp);
andrewboyson 47:73af5c0b0dc2 150 LogF(" from ");
andrewboyson 47:73af5c0b0dc2 151 Ip6AddressLog(srcIp);
andrewboyson 47:73af5c0b0dc2 152 Log("\r\n");
andrewboyson 15:6ca6778168b1 153 }
andrewboyson 14:e75a59c1123d 154 return DO_NOTHING;
andrewboyson 14:e75a59c1123d 155 }
andrewboyson 10:f0854784e960 156
andrewboyson 57:e0fb648acf48 157 NetTraceHostCheckIp6(srcIp);
andrewboyson 57:e0fb648acf48 158
andrewboyson 59:e0e556c8bd46 159 Ar6AddIpRecord(trace, macRemote, srcIp);
andrewboyson 50:492f2d2954e4 160 Nr6MakeRequestForNameFromIp(srcIp);
andrewboyson 11:c051adb70c5a 161
andrewboyson 10:f0854784e960 162 int action = DO_NOTHING;
andrewboyson 10:f0854784e960 163 switch (protocol)
andrewboyson 10:f0854784e960 164 {
andrewboyson 59:e0e556c8bd46 165 case HOPOPT: action = DO_NOTHING; break;
andrewboyson 59:e0e556c8bd46 166 case ICMP6: action = Icmp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
andrewboyson 59:e0e556c8bd46 167 case UDP: action = Udp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
andrewboyson 59:e0e556c8bd46 168 case TCP: action = Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
andrewboyson 10:f0854784e960 169 default:
andrewboyson 37:793b39683406 170 LogTimeF("IP6 protocol %d unhandled\r\n", protocol);
andrewboyson 10:f0854784e960 171 return DO_NOTHING;
andrewboyson 10:f0854784e960 172 }
andrewboyson 11:c051adb70c5a 173 if (!action) return DO_NOTHING;
andrewboyson 11:c051adb70c5a 174
andrewboyson 53:77f8a49adf89 175 if (NdpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 176 {
andrewboyson 59:e0e556c8bd46 177 MacCopy(macRemote, NdpRouterMac); //Send to the router MAC
andrewboyson 53:77f8a49adf89 178 hoplimit = NdpHopLimit;
andrewboyson 53:77f8a49adf89 179 }
andrewboyson 53:77f8a49adf89 180 else
andrewboyson 53:77f8a49adf89 181 {
andrewboyson 53:77f8a49adf89 182 hoplimit = 255;
andrewboyson 53:77f8a49adf89 183 }
andrewboyson 59:e0e556c8bd46 184
andrewboyson 59:e0e556c8bd46 185 dataLength = dataLengthTx;
andrewboyson 10:f0854784e960 186
andrewboyson 59:e0e556c8bd46 187 writeHeader(pHeaderTx);
andrewboyson 11:c051adb70c5a 188
andrewboyson 59:e0e556c8bd46 189 *pSizeTx = sizeof(header) + dataLength;
andrewboyson 10:f0854784e960 190
andrewboyson 37:793b39683406 191 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 192
andrewboyson 10:f0854784e960 193 return action;
andrewboyson 10:f0854784e960 194 }
andrewboyson 10:f0854784e960 195 int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
andrewboyson 10:f0854784e960 196 {
andrewboyson 59:e0e556c8bd46 197 pData = (char*)pPacket + sizeof(header);
andrewboyson 11:c051adb70c5a 198 dataLength = 0;
andrewboyson 11:c051adb70c5a 199 version = 6;
andrewboyson 10:f0854784e960 200
andrewboyson 10:f0854784e960 201 int action = DO_NOTHING;
andrewboyson 47:73af5c0b0dc2 202 if (!action)
andrewboyson 10:f0854784e960 203 {
andrewboyson 35:93c39d260a83 204 action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 205 protocol = ICMP6;
andrewboyson 10:f0854784e960 206 }
andrewboyson 10:f0854784e960 207
andrewboyson 47:73af5c0b0dc2 208 if (!action)
andrewboyson 10:f0854784e960 209 {
andrewboyson 35:93c39d260a83 210 action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
andrewboyson 10:f0854784e960 211 protocol = UDP;
andrewboyson 10:f0854784e960 212 }
andrewboyson 11:c051adb70c5a 213 if (!action) return DO_NOTHING;
andrewboyson 37:793b39683406 214
andrewboyson 37:793b39683406 215 int dest = ActionGetDestPart(action);
andrewboyson 37:793b39683406 216 switch (dest)
andrewboyson 11:c051adb70c5a 217 {
andrewboyson 11:c051adb70c5a 218 case UNICAST:
andrewboyson 11:c051adb70c5a 219 case UNICAST_DNS:
andrewboyson 11:c051adb70c5a 220 case UNICAST_DHCP:
andrewboyson 22:914b970356f0 221 case UNICAST_NTP:
andrewboyson 57:e0fb648acf48 222 case UNICAST_TFTP:
andrewboyson 53:77f8a49adf89 223 if (NdpIpNeedsToBeRouted(dstIp))
andrewboyson 53:77f8a49adf89 224 {
andrewboyson 53:77f8a49adf89 225 MacCopy(pDstMac, NdpRouterMac); //Send to the router MAC
andrewboyson 53:77f8a49adf89 226 hoplimit = NdpHopLimit;
andrewboyson 53:77f8a49adf89 227 }
andrewboyson 53:77f8a49adf89 228 else
andrewboyson 53:77f8a49adf89 229 {
andrewboyson 53:77f8a49adf89 230 Ar6IpToMac(dstIp, pDstMac); //Make the remote MAC from NP
andrewboyson 53:77f8a49adf89 231 hoplimit = 255;
andrewboyson 53:77f8a49adf89 232 }
andrewboyson 11:c051adb70c5a 233 break;
andrewboyson 22:914b970356f0 234 case MULTICAST_NODE:
andrewboyson 22:914b970356f0 235 case MULTICAST_ROUTER:
andrewboyson 22:914b970356f0 236 case MULTICAST_MDNS:
andrewboyson 22:914b970356f0 237 case MULTICAST_LLMNR:
andrewboyson 22:914b970356f0 238 case SOLICITED_NODE:
andrewboyson 53:77f8a49adf89 239 hoplimit = 255;
andrewboyson 22:914b970356f0 240 break;
andrewboyson 22:914b970356f0 241 default:
andrewboyson 37:793b39683406 242 LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest);
andrewboyson 53:77f8a49adf89 243 return DO_NOTHING;
andrewboyson 11:c051adb70c5a 244 }
andrewboyson 10:f0854784e960 245
andrewboyson 11:c051adb70c5a 246 writeHeader((header*)pPacket);
andrewboyson 11:c051adb70c5a 247
andrewboyson 59:e0e556c8bd46 248 *pSize = sizeof(header) + dataLength;
andrewboyson 10:f0854784e960 249
andrewboyson 37:793b39683406 250 if (ActionGetTracePart(action)) logHeader();
andrewboyson 37:793b39683406 251
andrewboyson 10:f0854784e960 252 return action;
andrewboyson 10:f0854784e960 253 }