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:
11:c051adb70c5a
Parent:
10:f0854784e960
Child:
14:e75a59c1123d
--- a/ip4/ip4.cpp	Sun Apr 16 14:21:55 2017 +0000
+++ b/ip4/ip4.cpp	Tue Apr 18 19:07:05 2017 +0000
@@ -10,6 +10,30 @@
 
 #define DEBUG false
 
+#define IP4_BROADCAST_ADDRESS       0xFFFFFFFF
+#define IP4_MULTICAST_ALL_HOSTS     0x010000E0
+#define IP4_MULTICAST_ALL_ROUTERS   0x020000E0
+#define IP4_MULTICAST_DNS_ADDRESS   0xFB0000E0
+#define IP4_MULTICAST_LLMNR_ADDRESS 0xFC0000E0
+
+void Ip4DestIpFromAction(int action, uint32_t* pDstIp)
+{
+    switch (action)
+    {
+        case UNICAST:                                                 break;
+        case UNICAST_DNS:      *pDstIp = DhcpDnsServer;               break;
+        case UNICAST_DHCP:     *pDstIp = DhcpServer;                  break;
+        case MULTICAST_NODE:   *pDstIp = IP4_MULTICAST_ALL_HOSTS;     break;
+        case MULTICAST_ROUTER: *pDstIp = IP4_MULTICAST_ALL_ROUTERS;   break;
+        case MULTICAST_MDNS:   *pDstIp = IP4_MULTICAST_DNS_ADDRESS;   break;
+        case MULTICAST_LLMNR:  *pDstIp = IP4_MULTICAST_LLMNR_ADDRESS; break;
+        case BROADCAST:        *pDstIp = IP4_BROADCAST_ADDRESS;       break;
+        default:
+            LogTimeF("Ip4 DestIpFromAction unknown action %d\r\n", action);
+            break;
+    }
+}
+
 #define HEADER_LENGTH 20
 
 __packed struct header
@@ -43,41 +67,6 @@
 static void*          pData;
 static int       dataLength;
 
-static void protocolToString(uint16_t protocol, int size, char* text)
-{
-    switch (protocol)
-    {
-        case ICMP: strncpy (text, "ICMP", size);         break;
-        case  TCP: strncpy (text, "TCP" , size);         break;
-        case  UDP: strncpy (text, "UDP" , size);         break;
-        default:   snprintf(text, size, "%d", protocol); break;
-    }
-}
-
-void logHeader(char* title)
-{
-    char text[30];
-    LogTimeF("%s\r\n", title);
-    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("  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);
-    protocolToString(protocol, sizeof(text), text);
-    LogF("  Protocol          %s\r\n", text);
-    LogF("  Checksum (hex)    %04hX\r\n", checksum);
-    LogF("  Calculated (hex)  %04hX\r\n",  calcsum);
-    NetIp4AddressToString(srcIp, sizeof(text), text);
-    LogF("  Source IP         %s\r\n", text);
-    NetIp4AddressToString(dstIp, sizeof(text), text);
-    LogF("  Destination IP    %s\r\n", text);
-}
 void readHeader(struct header * pHeader)
 {
              version       =             pHeader->versionIhl >> 4;
@@ -120,6 +109,31 @@
     pHeader->checksum    = NetCheckSum(headerLength, pHeader);
     calcsum              = 0;
 }
+
+static void logHeader(char* title)
+{
+    char text[30];
+    LogTimeF("%s\r\n", title);
+    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("  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);
+    NetProtocolToString(protocol, sizeof(text), text);
+    LogF("  Protocol          %s\r\n", text);
+    LogF("  Checksum (hex)    %04hX\r\n", checksum);
+    LogF("  Calculated (hex)  %04hX\r\n",  calcsum);
+    NetIp4AddressToString(srcIp, sizeof(text), text);
+    LogF("  Source IP         %s\r\n", text);
+    NetIp4AddressToString(dstIp, sizeof(text), text);
+    LogF("  Destination IP    %s\r\n", text);
+}
 int Ip4HandleReceivedPacket(char* pSrcMac, void* pPacket, int* pSize, char* pDstMac)
 {
     struct header * pHeader = (header*)pPacket;
@@ -139,33 +153,17 @@
     switch (protocol)
     {
         case ICMP: action = IcmpHandleReceivedPacket(&srcIp, &dstIp, &dataLength, pData); break;
+        case IGMP: return DO_NOTHING;
         case UDP:  action = Udp4HandleReceivedPacket(&srcIp, &dstIp, &dataLength, pData); break;
         case TCP:  action = Tcp4HandleReceivedPacket(&srcIp, &dstIp, &dataLength, pData); break;        
         default:
             logHeader("IP4 packet unhandled");
             return DO_NOTHING;
     }
+    if (!action) return DO_NOTHING;
     
-    switch (action)
-    {
-        case DO_NOTHING:
-            return DO_NOTHING;
-        case UNICAST:
-        case UNICAST_DNS:
-        case UNICAST_DHCP:
-            memcpy(pDstMac, pSrcMac, 6);
-            break;
-        case MULTICAST_NODE:
-        case MULTICAST_ROUTER:
-        case MULTICAST_MDNS:
-        case MULTICAST_LLMNR:
-        case BROADCAST:
-            break;
-        default:
-            LogTimeF("Ip4HandleReceivedPacket unknown action %d\r\n", action);
-            return DO_NOTHING;
-    }
-
+    memcpy(pDstMac, pSrcMac, 6);
+    
     if (DEBUG) logHeader("IP4 packet replied to");
     
     writeHeader(pHeader);
@@ -176,36 +174,9 @@
 }
 int Ip4PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
 {
-    struct header * pHeader = (header*)pPacket;
-    
-    headerLength = HEADER_LENGTH;
-    pData = (char*)pPacket + headerLength;
-    
-    srcIp = 0;
-    dstIp = 0;
-    
-    dataLength = 0;
-    int action  = DO_NOTHING;
-    if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp);
-    
-    switch (action)
-    {
-        case DO_NOTHING:
-            return DO_NOTHING;
-        case UNICAST:
-        case UNICAST_DNS:
-        case UNICAST_DHCP:
-            ArRev4(dstIp, pDstMac); //Make the remote MAC from ARP
-            break;
-        case MULTICAST_MDNS:
-        case MULTICAST_LLMNR:
-        case BROADCAST:
-            break;
-        default:
-            LogTimeF("Ip4PollForPacketToSend unknown action %d\r\n", action);
-            return DO_NOTHING;
-    }
-
+    headerLength  = HEADER_LENGTH;
+    pData         = (char*)pPacket + headerLength;
+    dataLength    = 0;
     version       = 4;
     tos           = 0;
     id            = 0;
@@ -215,9 +186,22 @@
     ttl           = 255;
     protocol      = UDP;
     
-    if (DEBUG) logHeader("IP4 packet replied to");
+    int action  = DO_NOTHING;
+    if (!action) action = Udp4PollForPacketToSend(pData, &dataLength, &srcIp, &dstIp);
+    if (!action) return DO_NOTHING;
+    switch (action)
+    {
+        case UNICAST:
+        case UNICAST_DNS:
+        case UNICAST_DHCP:
+            ArRev4(dstIp, pDstMac);             //Make the remote MAC from ARP
+            break;
+    }
 
-    writeHeader(pHeader);
+    
+    if (DEBUG) logHeader("IP4 polled packet sent");
+
+    writeHeader((header*)pPacket);
     
     *pSize = headerLength + dataLength;