Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
Diff: ip4/ip4.c
- Revision:
- 61:aad055f1b0d1
- Parent:
- 59:e0e556c8bd46
- Child:
- 71:736a5747ade1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ip4/ip4.c Thu Jan 11 17:38:21 2018 +0000 @@ -0,0 +1,265 @@ +#include <stdint.h> +#include <stdbool.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 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() +{ + 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(" 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"); + } + 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), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote) +{ + pTraceBack = traceback; + struct header * pHeaderRx = (struct header*)pPacketRx; + struct header * pHeaderTx = (struct header*)pPacketTx; + + 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); + + 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 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, macRemote, srcIp); + Nr4MakeRequestForNameFromIp(srcIp); + } + + int action = DO_NOTHING; + switch (protocol) + { + case ICMP: action = Icmp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break; + case IGMP: break; + case UDP: action = Udp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break; + case TCP: action = Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); 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, macRemote); //Send back to the router + ttl = OFF_LINK_TTL; + } + else + { + ttl = 255; + } + + totalLength = sizeof(struct header) + dataLengthTx; + headerLength = sizeof(struct header); + + writeHeader(pHeaderTx); + + *pSizeTx = totalLength; + + if (ActionGetTracePart(action)) logHeader(); + + 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; + protocol = UDP; + + int dataLength = *pSize - sizeof(struct header); + + 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: + case UNICAST_TFTP: + if (DhcpIpNeedsToBeRouted(dstIp)) + { + Ar4IpToMac(DhcpRouter, pDstMac); //send via router + ttl = OFF_LINK_TTL; + } + else + { + Ar4IpToMac(dstIp, pDstMac); //Send direct + ttl = 255; + } + break; + case MULTICAST_NODE: + case MULTICAST_ROUTER: + case MULTICAST_MDNS: + case MULTICAST_LLMNR: + case BROADCAST: + ttl = 255; + break; + default: + LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest); + return DO_NOTHING; + } + + struct header* pHeader = (struct header*)pPacket; + + totalLength = sizeof(struct header) + dataLength; + headerLength = sizeof(struct header); + + writeHeader(pHeader); + + *pSize = totalLength; + + if (ActionGetTracePart(action)) logHeader(); + + return action; +}