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

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;
 }