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-04-16
- Revision:
- 10:f0854784e960
- Child:
- 11:c051adb70c5a
File content as of revision 10:f0854784e960:
#include "mbed.h" #include "log.h" #include "net.h" #include "icmp6.h" #include "udp6.h" #include "tcp6.h" #include "ar.h" #include "dhcp.h" #include "slaac.h" #include "eth.h" #include "ip6.h" #define HEADER_LENGTH 40 char Ip6AllNodes[] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; char Ip6AllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; char Ip6Mdns[] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}; char Ip6Llmnr[] = { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}; __packed struct header { uint32_t versionTrafficFlow; uint16_t dataLength; uint8_t protocol; uint8_t hoplimit; char src[16]; char dst[16]; }; 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 getIsSame(char* pA, char* pB) { return memcmp(pA, pB, 16) == 0; } static bool getIsSameGroup(char* pA, char* pB) { pA += 13; pB += 13; if (*pA++ != *pB++) return false; if (*pA++ != *pB++) return false; return *pA == *pB; } int Ip6HandleReceivedPacket(char* pSrcMac, void* pPacket, int* pSize, char* pDstMac) { struct header * pHeader = (header*)pPacket; uint8_t version = (pHeader->versionTrafficFlow >> 4) & 0xF; int dataLength = NetToHost16(pHeader->dataLength); uint8_t protocol = pHeader->protocol; uint8_t hoplimit = pHeader->hoplimit; char src[16]; memcpy(src, pHeader->src, 16); char dst[16]; memcpy(dst, pHeader->dst, 16); void* pData = (char*)pPacket + HEADER_LENGTH; bool isMe = getIsSame(dst, SlaacLinkLocalIp); bool isMulticast = dst[0] == 0xFF; bool isSolicited = getIsSolicited(dst); bool isGroup = isSolicited && getIsSameGroup(dst, SlaacLinkLocalIp); bool doIt = isMe || (isMulticast && !isSolicited) || isGroup; if (!doIt) return DO_NOTHING; ArAdd6(pSrcMac, src); int action = DO_NOTHING; switch (protocol) { case ICMP6: action = Icmp6HandleReceivedPacket(src, dst, &dataLength, pData); break; case UDP: action = Udp6HandleReceivedPacket(src, dst, &dataLength, pData); break; case TCP: action = Tcp6HandleReceivedPacket(src, dst, &dataLength, pData); break; default: char text[100]; LogTimeF("IP6 packet unhandled\r\n"); LogF(" Size %d\r\n", *pSize); LogF(" Version %d\r\n", version); LogF(" Payload length %d\r\n", dataLength); LogF(" Hop limit %d\r\n", hoplimit); NetProtocolToString(protocol, sizeof(text), text); LogF(" Protocol %s\r\n", text); NetIp6AddressToString(src, sizeof(text), text); LogF(" Source IP %s\r\n", text); NetIp6AddressToString(dst, sizeof(text), text); LogF(" Destination IP %s\r\n", text); return DO_NOTHING; } switch (action) { case DO_NOTHING: return DO_NOTHING; case UNICAST: memcpy(pDstMac, pSrcMac, 6); break; case MULTICAST_ROUTER: break; default: LogTimeF("Ip6 unknown action %d\r\n", action); return DO_NOTHING; } memcpy(pHeader->dst, dst, 16); memcpy(pHeader->src, src, 16); pHeader->dataLength = NetToHost16(dataLength); *pSize = HEADER_LENGTH + dataLength; return action; } int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac) { void* pData = (char*)pPacket + HEADER_LENGTH; int dataLength = 0; char pSrcIp[16]; char pDstIp[16]; uint8_t protocol = 0; int action = DO_NOTHING; if (action == DO_NOTHING) { action = Icmp6PollForPacketToSend(pData, &dataLength, pSrcIp, pDstIp); protocol = ICMP6; } if (action == DO_NOTHING) { action = Udp6PollForPacketToSend(pData, &dataLength, pSrcIp, pDstIp); protocol = UDP; } if (action == DO_NOTHING) return DO_NOTHING; ArRev6(pDstIp, pDstMac); //Make the remote MAC from ARP uint8_t version = 6; uint8_t hoplimit = 255; struct header * pHeader = (header*)pPacket; pHeader->versionTrafficFlow = version << 4; pHeader->protocol = protocol; pHeader->hoplimit = 255; memcpy(pHeader->dst, pDstIp, 16); memcpy(pHeader->src, pSrcIp, 16); pHeader->dataLength = NetToHost16(dataLength); *pSize = HEADER_LENGTH + dataLength; LogTimeF("Ip6 sending waiting packet\r\n"); char text[100]; LogF(" Size %d\r\n", *pSize); LogF(" Version %d\r\n", version); LogF(" Payload length %d\r\n", dataLength); LogF(" Hop limit %d\r\n", hoplimit); NetProtocolToString(protocol, sizeof(text), text); LogF(" Protocol %s\r\n", text); NetIp6AddressToString(pSrcIp, sizeof(text), text); LogF(" Source IP %s\r\n", text); NetIp6AddressToString(pDstIp, sizeof(text), text); LogF(" Destination IP %s\r\n", text); return action; }