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
ip4/ip4.cpp
- Committer:
- andrewboyson
- Date:
- 2017-11-03
- Revision:
- 50:492f2d2954e4
- Parent:
- 49:1a6336f2b3f9
- Child:
- 53:77f8a49adf89
File content as of revision 50:492f2d2954e4:
#include "mbed.h" #include "log.h" #include "net.h" #include "action.h" #include "icmp4.h" #include "udptcp4.h" #include "ar4.h" #include "nr4.h" #include "dhcp.h" #include "eth.h" #include "ip.h" #include "ip4addr.h" #include "ntp.h" #include "mac.h" bool Ip4Trace = true; #define HEADER_LENGTH 20 __packed struct header { uint8_t versionIhl; uint8_t tos; uint16_t length; uint16_t id; uint16_t flagsOffset; uint8_t ttl; uint8_t protocol; uint16_t checksum; uint32_t src; uint32_t dst; }; //Header variables static uint8_t version; static int headerLength; static uint8_t tos; static uint16_t id; static bool dontFragment; static bool moreFragments; static uint16_t offset; static uint8_t ttl; static uint8_t protocol; static uint16_t checksum; static uint16_t calcsum; static uint32_t srcIp; static uint32_t dstIp; static void* pData; static int dataLength; void readHeader(struct header * pHeader) { version = pHeader->versionIhl >> 4; uint8_t ihl = pHeader->versionIhl & 0xF; headerLength = ihl * 4; tos = pHeader->tos; uint16_t totalLength = NetToHost16(pHeader->length); id = NetToHost16(pHeader->id); uint16_t flagsOffset = NetToHost16(pHeader->flagsOffset); dontFragment = flagsOffset & 0x4000; moreFragments = flagsOffset & 0x8000; offset = flagsOffset & 0x1FFF; ttl = pHeader->ttl; protocol = pHeader->protocol; checksum = NetToHost16(pHeader->checksum); calcsum = NetCheckSum(headerLength, pHeader); srcIp = pHeader->src; dstIp = pHeader->dst; pData = (char*)pHeader + headerLength; dataLength = totalLength - headerLength; } void writeHeader(struct header * pHeader) { uint16_t flagsOffset = offset; if (dontFragment) flagsOffset |= 0x4000; if (moreFragments) flagsOffset |= 0x8000; uint8_t ihl = headerLength >> 2; pHeader->versionIhl = (version << 4) + ihl; pHeader->tos = tos; pHeader->id = NetToHost16(id); pHeader->flagsOffset = NetToHost16(flagsOffset); pHeader->ttl = ttl; pHeader->protocol = protocol; pHeader->dst = dstIp; pHeader->src = srcIp; pHeader->length = NetToHost16(headerLength + dataLength); pHeader->checksum = 0; pHeader->checksum = NetCheckSum(headerLength, pHeader); calcsum = 0; } static void logHeader() { if (NetTraceVerbose) { Log ("IP4 header\r\n"); LogF(" Version %d\r\n", version); LogF(" Header length %d\r\n", headerLength); LogF(" Type of service %d\r\n", tos); LogF(" Data length %d\r\n", dataLength); LogF(" Identification %d\r\n", id); if (dontFragment) LogF(" Don't fragment\r\n"); else LogF(" Do fragment\r\n"); if (moreFragments) LogF(" More fragments\r\n"); else LogF(" No more fragments\r\n"); LogF(" Offset %d\r\n", offset); LogF(" Time to live %d\r\n", ttl); LogF(" Protocol "); IpProtocolLog(protocol); Log("\r\n"); LogF(" Checksum (hex) %04hX\r\n", checksum); LogF(" Calculated (hex) %04hX\r\n", calcsum); LogF(" Source IP "); Ip4AddressLog(srcIp); Log("\r\n"); LogF(" Destination IP "); Ip4AddressLog(dstIp); Log("\r\n"); } else { Log ("IP4 header "); IpProtocolLog(protocol); Log(" "); Ip4AddressLog(srcIp); Log(" >>> "); Ip4AddressLog(dstIp); Log("\r\n"); } } static void (*pTraceBack)(void); static void trace() { pTraceBack(); logHeader(); } int Ip4HandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void* pPacket, int* pSize, char* pDstMac) { pTraceBack = traceback; struct header * pHeader = (header*)pPacket; readHeader(pHeader); bool isMe = dstIp == DhcpLocalIp; bool isLocalBroadcast = dstIp == DhcpLocalIp | 0xFF000000; bool isBroadcast = dstIp == IP4_BROADCAST_ADDRESS; bool isMulticast = (dstIp & 0xE0) == 0xE0; //224.x.x.x == 1110 0000 == E0.xx.xx.xx == xx.xx.xx.E0 in little endian bool doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast; if (!doIt) { if (Ip4Trace); { LogTimeF("IP4 filtered out ip "); Ip4AddressLog(dstIp); Log(" from "); Ip4AddressLog(srcIp); Log("\r\n"); } return DO_NOTHING; } if (srcIp) { Ar4AddIpRecord(trace, pSrcMac, srcIp); Nr4MakeRequestForNameFromIp(srcIp); } int action = DO_NOTHING; switch (protocol) { case ICMP: action = Icmp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break; case IGMP: break; case UDP: action = Udp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break; case TCP: action = Tcp4HandleReceivedPacket(trace, &srcIp, &dstIp, &dataLength, pData); break; case IP6IN4: break; default: LogTimeF("IP4 received packet unknown protocol %d\r\n"); return DO_NOTHING; } if (!action) return DO_NOTHING; if (DhcpIpNeedsToBeRouted(dstIp)) Ar4IpToMac(DhcpRouter, pDstMac); //Send back to the router else MacCopy(pDstMac, pSrcMac); //Send back to the source writeHeader(pHeader); *pSize = headerLength + dataLength; if (ActionGetTracePart(action)) logHeader(); return action; } int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac) { headerLength = HEADER_LENGTH; pData = (char*)pPacket + headerLength; dataLength = 0; version = 4; tos = 0; id = 0; dontFragment = true; moreFragments = false; offset = 0; ttl = 255; protocol = UDP; int action = DO_NOTHING; if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); if (!action) return DO_NOTHING; int dest = ActionGetDestPart(action); switch (dest) { case UNICAST: case UNICAST_DNS: case UNICAST_DHCP: case UNICAST_NTP: if (DhcpIpNeedsToBeRouted(dstIp)) Ar4IpToMac(DhcpRouter, pDstMac); //send via router else Ar4IpToMac(dstIp, pDstMac); //Send direct break; case MULTICAST_NODE: case MULTICAST_ROUTER: case MULTICAST_MDNS: case MULTICAST_LLMNR: case BROADCAST: break; default: LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest); break; } writeHeader((header*)pPacket); *pSize = headerLength + dataLength; if (ActionGetTracePart(action)) logHeader(); return action; }