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
Diff: ip4/ip4.c
- Revision:
- 136:8a65abb0dc63
- Parent:
- 116:60521b29e4c9
- Child:
- 142:a8c0890a58d1
--- a/ip4/ip4.c Sat Mar 23 12:25:48 2019 +0000 +++ b/ip4/ip4.c Sat Apr 06 11:20:20 2019 +0000 @@ -1,3 +1,4 @@ + #include <stdint.h> #include <stdbool.h> @@ -12,152 +13,107 @@ #include "eth.h" #include "ip.h" #include "ip4addr.h" +#include "ip4hdr.h" #include "ntp.h" #include "mac.h" #include "fault.h" +#include "checksum.h" bool Ip4Trace = true; #define OFF_LINK_TTL 64 -__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 totalLength; -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 readHeader(struct header * pHeader) -{ - version = pHeader->versionIhl >> 4; - uint8_t ihl = pHeader->versionIhl & 0xF; - headerLength = ihl * 4; - tos = pHeader->tos; - 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; -} -static 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(totalLength); - pHeader->checksum = 0; - pHeader->checksum = NetCheckSum(headerLength, pHeader); - calcsum = 0; -} - -static void logHeader() +static void logHeader(char* pPacket) { if (NetTraceVerbose) { Log ("IP4 header\r\n"); - LogF(" Version %d\r\n", version); + LogF(" Version %d\r\n", Ip4HdrGetVersion (pPacket)); + int headerLength = Ip4HdrGetHeaderLen (pPacket); LogF(" Header length %d\r\n", headerLength); - LogF(" Type of service %d\r\n", tos); - LogF(" Total length %d\r\n", totalLength); - 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"); + LogF(" Type of service %d\r\n", Ip4HdrGetTos (pPacket)); + LogF(" Total length %d\r\n", Ip4HdrGetLength (pPacket)); + LogF(" Identification %d\r\n", Ip4HdrGetId (pPacket)); + if (Ip4HdrGetDontFrag(pPacket)) LogF(" Don't fragment\r\n"); + else LogF(" Do fragment\r\n"); + if (Ip4HdrGetMoreFrags(pPacket)) LogF(" More fragments\r\n"); + else LogF(" No more fragments\r\n"); + LogF(" Frag offset %d\r\n", Ip4HdrGetFragOffset(pPacket)); + LogF(" Time to live %d\r\n", Ip4HdrGetTtl (pPacket)); + LogF(" Protocol "); IpProtocolLog(Ip4HdrGetProtocol(pPacket)); Log("\r\n"); + LogF(" Checksum (hex) %04hX\r\n", Ip4HdrGetChecksum(pPacket)); + LogF(" Calculated (hex) %04hX\r\n", CheckSum(headerLength, pPacket)); + LogF(" Source IP "); Ip4AddressLog(Ip4HdrGetSrc(pPacket)); Log("\r\n"); + LogF(" Destination IP "); Ip4AddressLog(Ip4HdrGetDst(pPacket)); Log("\r\n"); } else { Log ("IP4 header "); - IpProtocolLog(protocol); + IpProtocolLog(Ip4HdrGetProtocol(pPacket)); Log(" "); - Ip4AddressLog(srcIp); + Ip4AddressLog(Ip4HdrGetSrc(pPacket)); Log(" >>> "); - Ip4AddressLog(dstIp); + Ip4AddressLog(Ip4HdrGetDst(pPacket)); Log("\r\n"); } } +static void makeHeader(char* pPacket, uint16_t totalLength, uint8_t ttl, uint8_t protocol, uint32_t srcIp, uint32_t dstIp) +{ + static uint16_t id = 0; + Ip4HdrSetVersion (pPacket, 4 ); + Ip4HdrSetHeaderLen(pPacket, IP4_HEADER_LENGTH); + Ip4HdrSetTos (pPacket, 0 ); + Ip4HdrSetLength (pPacket, totalLength ); + Ip4HdrSetId (pPacket, id++ ); //Used by the recipient for collating packets fragmented in transit; unique per packet sent + Ip4HdrSetFragInfo (pPacket, 0 ); //No flags and no offset + Ip4HdrSetTtl (pPacket, ttl ); + Ip4HdrSetProtocol (pPacket, protocol ); + Ip4HdrSetSrc (pPacket, srcIp ); + Ip4HdrSetDst (pPacket, dstIp ); + Ip4HdrSetChecksum (pPacket, 0 ); + uint16_t checksum = CheckSum(IP4_HEADER_LENGTH, pPacket); + Ip4HdrSetChecksum (pPacket, checksum ); +} +static char* traceHeader; static void (*pTraceBack)(void); static void trace() { pTraceBack(); - logHeader(); + logHeader(traceHeader); } -int Ip4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote) + +int Ip4HandleReceivedPacket(void (*traceback)(void), char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* macRemote) { int lastFaultPoint = FaultPoint; FaultPoint = FAULT_POINT_Ip4HandleReceivedPacket; - + + traceHeader = pPacketRx; pTraceBack = traceback; - struct header * pHeaderRx = (struct header*)pPacketRx; - struct header * pHeaderTx = (struct header*)pPacketTx; + + int headerLengthRx = Ip4HdrGetHeaderLen(pPacketRx); + uint16_t totalLengthRx = Ip4HdrGetLength (pPacketRx); + uint8_t protocol = Ip4HdrGetProtocol (pPacketRx); + uint32_t srcIp = Ip4HdrGetSrc (pPacketRx); + uint32_t dstIp = Ip4HdrGetDst (pPacketRx); - char* pDataRx = (char*)pHeaderRx + headerLength; - char* pDataTx = (char*)pHeaderTx + headerLength; - - readHeader(pHeaderRx); - if (totalLength < sizeRx) sizeRx = totalLength; - int dataLengthRx = sizeRx - headerLength; - int dataLengthTx = *pSizeTx - sizeof(struct header); - + char* pDataRx = pPacketRx + headerLengthRx; + char* pDataTx = pPacketTx + IP4_HEADER_LENGTH; + + if (sizeRx > totalLengthRx) sizeRx = totalLengthRx; + int dataLengthRx = sizeRx - headerLengthRx; + int dataLengthTx = *pSizeTx - IP4_HEADER_LENGTH; + bool isMe = dstIp == DhcpLocalIp; bool isLocalBroadcast = dstIp == (DhcpLocalIp | 0xFF000000); // dstIp == 192.168.1.255; '|' is lower precendence than '==' bool isBroadcast = dstIp == IP4_BROADCAST_ADDRESS; // dstIp == 255.255.255.255 - bool isMulticast = (dstIp & 0xE0) == 0xE0; //224.x.x.x == 1110 0000 == E0.xx.xx.xx == xx.xx.xx.E0 in little endian - + 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); + LogTimeF("IP4 filtered out ip "); Ip4AddressLog(dstIp); Log(" from "); Ip4AddressLog(srcIp); Log("\r\n"); @@ -165,10 +121,10 @@ FaultPoint = lastFaultPoint; return DO_NOTHING; } - + int remArIndex = Ar4AddIpRecord(trace, macRemote, srcIp); Nr4MakeRequestForNameFromIp(srcIp); - + int action = DO_NOTHING; switch (protocol) { @@ -178,7 +134,7 @@ case TCP: action = Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp, remArIndex); break; case IP6IN4: break; default: - LogTimeF("IP4 received packet unknown protocol %d\r\n"); + LogTimeF("IP4 received packet unknown protocol %d\r\n", protocol); FaultPoint = lastFaultPoint; return DO_NOTHING; } @@ -187,7 +143,8 @@ FaultPoint = lastFaultPoint; return DO_NOTHING; } - + + uint8_t ttl = 0; if (DhcpIpNeedsToBeRouted(dstIp)) { Ar4IpToMac(DhcpRouterIp, macRemote); //Send back to the router @@ -198,36 +155,29 @@ ttl = 255; } - totalLength = sizeof(struct header) + dataLengthTx; - headerLength = sizeof(struct header); - - writeHeader(pHeaderTx); + *pSizeTx = IP4_HEADER_LENGTH + dataLengthTx; - *pSizeTx = totalLength; + makeHeader(pPacketTx, *pSizeTx, ttl, protocol, srcIp, dstIp); - if (ActionGetTracePart(action)) logHeader(); + if (ActionGetTracePart(action)) logHeader(pPacketTx); FaultPoint = lastFaultPoint; return action; } -int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac) -{ - headerLength = sizeof(struct header); - char* pData = (char*)pPacket + headerLength; - version = 4; - tos = 0; - id = 0; - dontFragment = true; - moreFragments = false; - offset = 0; - - int dataLength = *pSize - sizeof(struct header); - - int action = DO_NOTHING; +int Ip4PollForPacketToSend(char* pPacket, int* pSize, char* pDstMac) +{ + char* pData = pPacket + IP4_HEADER_LENGTH; + int dataLength = *pSize - IP4_HEADER_LENGTH; + + uint8_t protocol = 0; + uint32_t srcIp = 0; + uint32_t dstIp = 0; + int action = DO_NOTHING; if (!action) { action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = UDP; } if (!action) { action = Tcp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp); protocol = TCP; } if (!action) return DO_NOTHING; int dest = ActionGetDestPart(action); + uint8_t ttl = 0; switch (dest) { case UNICAST: @@ -259,16 +209,11 @@ return DO_NOTHING; } - struct header* pHeader = (struct header*)pPacket; - - totalLength = sizeof(struct header) + dataLength; - headerLength = sizeof(struct header); + *pSize = IP4_HEADER_LENGTH + dataLength; + + makeHeader(pPacket, *pSize, ttl, protocol, srcIp, dstIp); - writeHeader(pHeader); - - *pSize = totalLength; - - if (ActionGetTracePart(action)) logHeader(); + if (ActionGetTracePart(action)) logHeader(pPacket); return action; }