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.c
- Committer:
- andrewboyson
- Date:
- 2019-09-29
- Revision:
- 160:6a1d1d368f80
- Parent:
- 142:a8c0890a58d1
- Child:
- 172:9bc3c7b2cca1
File content as of revision 160:6a1d1d368f80:
#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 "ip4hdr.h" #include "ntp.h" #include "mac.h" #include "restart.h" #include "checksum.h" bool Ip4Trace = true; #define OFF_LINK_TTL 64 static void logHeader(char* pPacket) { if (NetTraceVerbose) { Log ("IP4 header\r\n"); 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", 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(Ip4HdrGetProtocol(pPacket)); Log(" "); Ip4AddressLog(Ip4HdrGetSrc(pPacket)); Log(" >>> "); 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(traceHeader); } int Ip4HandleReceivedPacket(void (*traceback)(void), char* pPacketRx, int sizeRx, char* pPacketTx, int* pSizeTx, char* macRemote) { int lastRestartPoint = RestartPoint; RestartPoint = FAULT_POINT_Ip4HandleReceivedPacket; traceHeader = pPacketRx; pTraceBack = traceback; 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 = 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 doIt = isMe || isLocalBroadcast || isBroadcast || isMulticast; if (!doIt) { if (Ip4Trace) { LogTimeF("IP4 filtered out ip "); Ip4AddressLog(dstIp); Log(" from "); Ip4AddressLog(srcIp); Log("\r\n"); } RestartPoint = lastRestartPoint; return DO_NOTHING; } int remArIndex = 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, remArIndex); break; case IP6IN4: break; default: LogTimeF("IP4 received packet unknown protocol %d\r\n", protocol); RestartPoint = lastRestartPoint; return DO_NOTHING; } if (!action) { RestartPoint = lastRestartPoint; return DO_NOTHING; } uint8_t ttl = 0; if (DhcpIpNeedsToBeRouted(dstIp)) { Ar4IpToMac(DhcpRouterIp, macRemote); //Send back to the router ttl = OFF_LINK_TTL; } else { ttl = 255; } *pSizeTx = IP4_HEADER_LENGTH + dataLengthTx; makeHeader(pPacketTx, *pSizeTx, ttl, protocol, srcIp, dstIp); if (ActionGetTracePart(action)) logHeader(pPacketTx); RestartPoint = lastRestartPoint; return action; } 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: case UNICAST_DNS: case UNICAST_DHCP: case UNICAST_NTP: case UNICAST_TFTP: if (DhcpIpNeedsToBeRouted(dstIp)) { Ar4IpToMac(DhcpRouterIp, 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 MULTICAST_NTP: case BROADCAST: ttl = 255; break; default: LogTimeF("Ip4PollForPacketToSend - undefined destination %d\r\n", dest); return DO_NOTHING; } *pSize = IP4_HEADER_LENGTH + dataLength; makeHeader(pPacket, *pSize, ttl, protocol, srcIp, dstIp); if (ActionGetTracePart(action)) logHeader(pPacket); return action; }