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:
59:e0e556c8bd46
Parent:
57:e0fb648acf48
--- a/ip4/ip4.cpp	Thu Dec 07 20:44:32 2017 +0000
+++ b/ip4/ip4.cpp	Thu Dec 14 20:55:40 2017 +0000
@@ -15,8 +15,6 @@
 
 bool Ip4Trace = true;
 
-#define HEADER_LENGTH 20
-
 #define OFF_LINK_TTL 64
 
 __packed struct header
@@ -37,6 +35,7 @@
 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;
@@ -47,16 +46,14 @@
 static uint16_t     calcsum;
 static uint32_t       srcIp;
 static uint32_t       dstIp;
-static void*          pData;
-static int       dataLength;
 
-void readHeader(struct header * pHeader)
+static 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);
+             totalLength   = NetToHost16(pHeader->length);
              id            = NetToHost16(pHeader->id);
     uint16_t flagsOffset   = NetToHost16(pHeader->flagsOffset);
              dontFragment  =             flagsOffset & 0x4000;
@@ -68,10 +65,8 @@
              calcsum       = NetCheckSum(headerLength, pHeader);
              srcIp         =             pHeader->src;
              dstIp         =             pHeader->dst;
-             pData         =      (char*)pHeader + headerLength;
-             dataLength    =         totalLength - headerLength;
 }
-void writeHeader(struct header * pHeader)
+static void writeHeader(struct header * pHeader)
 {
     uint16_t flagsOffset = offset;
     if (dontFragment)  flagsOffset |= 0x4000;
@@ -87,7 +82,7 @@
     
     pHeader->dst         = dstIp;
     pHeader->src         = srcIp;
-    pHeader->length      = NetToHost16(headerLength + dataLength);
+    pHeader->length      = NetToHost16(totalLength);
     pHeader->checksum    = 0;
     pHeader->checksum    = NetCheckSum(headerLength, pHeader);
     calcsum              = 0;
@@ -101,7 +96,7 @@
         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("  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");
@@ -132,11 +127,19 @@
     pTraceBack();
     logHeader();
 }
-int Ip4HandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
+int Ip4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* macRemote)
 {
     pTraceBack = traceback;
-    struct header * pHeader = (header*)pPacket;
-    readHeader(pHeader);
+    struct header * pHeaderRx = (header*)pPacketRx;
+    struct header * pHeaderTx = (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(header);
     
     bool isMe             = dstIp == DhcpLocalIp;
     bool isLocalBroadcast = dstIp == DhcpLocalIp | 0xFF000000;
@@ -158,18 +161,18 @@
     
     if (srcIp)
     {
-        Ar4AddIpRecord(trace, pSrcMac, srcIp);
+        Ar4AddIpRecord(trace, macRemote, 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;
+        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;
@@ -178,28 +181,29 @@
     
     if (DhcpIpNeedsToBeRouted(dstIp))
     {
-        Ar4IpToMac(DhcpRouter, pDstMac);  //Send back to the router
+        Ar4IpToMac(DhcpRouter, macRemote);  //Send back to the router
         ttl = OFF_LINK_TTL;
     }
     else
     {
-        MacCopy(pDstMac, pSrcMac);        //Send back to the source
         ttl = 255;
     }
+
+    totalLength = sizeof(header) + dataLengthTx;
+    headerLength = sizeof(header);
+
+    writeHeader(pHeaderTx);
     
-    writeHeader(pHeader);
-    
-    *pSize = headerLength + dataLength;
+    *pSizeTx = totalLength;
     
     if (ActionGetTracePart(action)) logHeader();
 
     return action;
 }
 int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
-{
-    headerLength  = HEADER_LENGTH;
-    pData         = (char*)pPacket + headerLength;
-    dataLength    = 0;
+{    
+    headerLength  = sizeof(header);
+    char* pData   = (char*)pPacket + headerLength;
     version       = 4;
     tos           = 0;
     id            = 0;
@@ -208,6 +212,8 @@
     offset        = 0;
     protocol      = UDP;
     
+    int dataLength = *pSize - sizeof(header);
+    
     int action  = DO_NOTHING;
     if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp);
     if (!action) return DO_NOTHING;
@@ -242,9 +248,14 @@
             return DO_NOTHING;
     }
 
-    writeHeader((header*)pPacket);
+    struct header* pHeader = (struct header*)pPacket;
+
+    totalLength = sizeof(header) + dataLength;
+    headerLength = sizeof(header);
+
+    writeHeader(pHeader);
     
-    *pSize = headerLength + dataLength;
+    *pSize = totalLength;
     
     if (ActionGetTracePart(action)) logHeader();