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
ip6/ip6.cpp
- Committer:
- andrewboyson
- Date:
- 2017-12-14
- Revision:
- 59:e0e556c8bd46
- Parent:
- 57:e0fb648acf48
File content as of revision 59:e0e556c8bd46:
#include "mbed.h" #include "log.h" #include "net.h" #include "action.h" #include "icmp6.h" #include "udptcp6.h" #include "ar6.h" #include "nr6.h" #include "slaac.h" #include "eth.h" #include "ip.h" #include "ip6addr.h" #include "ndp.h" #include "io.h" #include "ntp.h" #include "mac.h" #include "http.h" bool Ip6Trace = true; __packed struct header { uint32_t versionTrafficFlow; uint16_t dataLength; uint8_t protocol; uint8_t hoplimit; char src[16]; char dst[16]; }; static uint8_t version; static int dataLength; static uint8_t protocol; static uint8_t hoplimit; static char srcIp[16]; static char dstIp[16]; static void* pData; static void readHeader(struct header * pHeader) { version = (pHeader->versionTrafficFlow >> 4) & 0xF; dataLength = NetToHost16(pHeader->dataLength); protocol = pHeader->protocol; hoplimit = pHeader->hoplimit; Ip6AddressCopy(srcIp, pHeader->src); Ip6AddressCopy(dstIp, pHeader->dst); pData = (char*)pHeader + sizeof(header); } static void writeHeader(struct header * pHeader) { pHeader->versionTrafficFlow = version << 4; pHeader->protocol = protocol; pHeader->hoplimit = hoplimit; Ip6AddressCopy(pHeader->dst, dstIp); Ip6AddressCopy(pHeader->src, srcIp); pHeader->dataLength = NetToHost16(dataLength); } static void logHeader() { if (NetTraceVerbose) { Log("IP6 header\r\n"); LogF(" Version %d\r\n", version); LogF(" Payload length %d\r\n", dataLength); LogF(" Hop limit %d\r\n", hoplimit); LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n"); Log (" Source IP "); Ip6AddressLog(srcIp); Log("\r\n"); Log (" Destination IP "); Ip6AddressLog(dstIp); Log("\r\n"); } else { Log("IP6 header "); IpProtocolLog(protocol); Log(" "); Ip6AddressLog(srcIp); Log(" >>> "); Ip6AddressLog(dstIp); Log("\r\n"); } } static bool getIsSolicited(char* p) { if (*p++ != 0xff) return false; if (*p++ != 0x02) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x00) return false; if (*p++ != 0x01) return false; if (*p++ != 0xff) return false; return true; } static bool getIsSameGroup(char* pA, char* pB) { pA += 13; pB += 13; if (*pA++ != *pB++) return false; if (*pA++ != *pB++) return false; return *pA == *pB; } static void (*pTraceBack)(void); static void trace() { pTraceBack(); logHeader(); } int Ip6HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote) { pTraceBack = traceback; struct header* pHeaderRx = (header*)pPacketRx; struct header* pHeaderTx = (header*)pPacketTx; char* pDataRx = (char*)pHeaderRx + sizeof(header); char* pDataTx = (char*)pHeaderTx + sizeof(header); readHeader(pHeaderRx); //This also fetches the datalength out of the header int dataLengthRx = dataLength; if (dataLengthRx > sizeRx) dataLengthRx = sizeRx; //Do not exceed the buffer size int dataLengthTx = *pSizeTx; int scope = SlaacScope(dstIp); bool isMulticast = dstIp[0] == 0xFF; bool isSolicited = getIsSolicited(dstIp); bool isGroup = getIsSameGroup(dstIp, SlaacLinkLocalIp); bool doIt = scope || (isMulticast && !isSolicited) || (isGroup && isSolicited); if (!doIt) { if (Ip6Trace) { LogTime("IP6 filtered out ip "); Ip6AddressLog(dstIp); LogF(" from "); Ip6AddressLog(srcIp); Log("\r\n"); } return DO_NOTHING; } NetTraceHostCheckIp6(srcIp); Ar6AddIpRecord(trace, macRemote, srcIp); Nr6MakeRequestForNameFromIp(srcIp); int action = DO_NOTHING; switch (protocol) { case HOPOPT: action = DO_NOTHING; break; case ICMP6: action = Icmp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; case UDP: action = Udp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; case TCP: action = Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break; default: LogTimeF("IP6 protocol %d unhandled\r\n", protocol); return DO_NOTHING; } if (!action) return DO_NOTHING; if (NdpIpNeedsToBeRouted(dstIp)) { MacCopy(macRemote, NdpRouterMac); //Send to the router MAC hoplimit = NdpHopLimit; } else { hoplimit = 255; } dataLength = dataLengthTx; writeHeader(pHeaderTx); *pSizeTx = sizeof(header) + dataLength; if (ActionGetTracePart(action)) logHeader(); return action; } int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac) { pData = (char*)pPacket + sizeof(header); dataLength = 0; version = 6; int action = DO_NOTHING; if (!action) { action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp); protocol = ICMP6; } if (!action) { action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp); protocol = UDP; } if (!action) return DO_NOTHING; int dest = ActionGetDestPart(action); switch (dest) { case UNICAST: case UNICAST_DNS: case UNICAST_DHCP: case UNICAST_NTP: case UNICAST_TFTP: if (NdpIpNeedsToBeRouted(dstIp)) { MacCopy(pDstMac, NdpRouterMac); //Send to the router MAC hoplimit = NdpHopLimit; } else { Ar6IpToMac(dstIp, pDstMac); //Make the remote MAC from NP hoplimit = 255; } break; case MULTICAST_NODE: case MULTICAST_ROUTER: case MULTICAST_MDNS: case MULTICAST_LLMNR: case SOLICITED_NODE: hoplimit = 255; break; default: LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest); return DO_NOTHING; } writeHeader((header*)pPacket); *pSize = sizeof(header) + dataLength; if (ActionGetTracePart(action)) logHeader(); return action; }