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:
61:aad055f1b0d1
Parent:
59:e0e556c8bd46
Child:
71:736a5747ade1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ip6/ip6.c	Thu Jan 11 17:38:21 2018 +0000
@@ -0,0 +1,254 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include     "log.h"
+#include     "net.h"
+#include  "action.h"
+#include   "icmp6.h"
+#include "udptcp6.h"
+#include     "ar6.h"
+#include     "nr6.h"
+#include   "slaac.h"
+#include     "eth.h"
+#include      "ip.h"
+#include "ip6addr.h"
+#include     "ndp.h"
+#include     "ntp.h"
+#include     "mac.h"
+#include    "http.h"
+
+bool Ip6Trace = true;
+
+__packed struct header
+{
+    uint32_t versionTrafficFlow;
+    uint16_t payloadLength;
+    uint8_t  protocol;
+    uint8_t  hoplimit;
+    char     src[16];
+    char     dst[16];
+};
+
+static uint8_t     version;
+static int   payloadLength;
+static uint8_t    protocol;
+static uint8_t    hoplimit;
+static char      srcIp[16];
+static char      dstIp[16];
+
+static void readHeader(struct header * pHeader)
+{
+    version    =            (pHeader->versionTrafficFlow >> 4) & 0x0F;
+ payloadLength = NetToHost16(pHeader->payloadLength);
+    protocol   =             pHeader->protocol;
+    hoplimit   =             pHeader->hoplimit;
+       Ip6AddressCopy(srcIp, pHeader->src);
+       Ip6AddressCopy(dstIp, pHeader->dst);
+}
+static void writeHeader(struct header * pHeader)
+{
+                   pHeader->versionTrafficFlow  = version << 4;
+                   pHeader->payloadLength       = NetToHost16(payloadLength);
+                   pHeader->protocol            = protocol;
+                   pHeader->hoplimit            = hoplimit;
+    Ip6AddressCopy(pHeader->dst, dstIp);
+    Ip6AddressCopy(pHeader->src, srcIp);
+}
+
+static void logHeader()
+{
+    if (NetTraceVerbose)
+    {
+        Log("IP6 header\r\n");
+        LogF("  Version           %d\r\n", version);
+        LogF("  Payload length    %d\r\n", payloadLength);
+        LogF("  Hop limit         %d\r\n", hoplimit);
+        LogF("  Protocol          "); IpProtocolLog(protocol); Log("\r\n");
+        Log ("  Source IP         "); Ip6AddressLog(srcIp);    Log("\r\n");
+        Log ("  Destination IP    "); Ip6AddressLog(dstIp);    Log("\r\n");
+    }
+    else
+    {
+        Log("IP6   header ");
+        IpProtocolLog(protocol);
+        Log(" ");
+        Ip6AddressLog(srcIp);
+        Log(" >>> ");
+        Ip6AddressLog(dstIp);
+        Log("\r\n");
+    }
+}
+
+static bool getIsSolicited(char* p)
+{
+    if (*p++ != 0xff) return false;
+    if (*p++ != 0x02) return false;
+    
+    if (*p++ != 0x00) return false;
+    if (*p++ != 0x00) return false;
+    
+    if (*p++ != 0x00) return false;
+    if (*p++ != 0x00) return false;
+    
+    if (*p++ != 0x00) return false;
+    if (*p++ != 0x00) return false;
+    
+    if (*p++ != 0x00) return false;
+    if (*p++ != 0x00) return false;
+    
+    if (*p++ != 0x00) return false;
+    if (*p++ != 0x01) return false;
+    
+    if (*p++ != 0xff) return false;
+    
+    return true;
+}
+static bool getIsSameGroup(char* pA, char* pB)
+{
+    pA += 13;
+    pB += 13;
+    if (*pA++ != *pB++) return false;
+    if (*pA++ != *pB++) return false;
+    return *pA == *pB;
+}
+static void (*pTraceBack)(void);
+static void trace()
+{
+    pTraceBack();
+    logHeader();
+}
+int Ip6HandleReceivedPacket(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 + sizeof(struct header);
+    char* pDataTx = (char*)pHeaderTx + sizeof(struct header);
+    
+    readHeader(pHeaderRx); //This also fetches the payload length out of the header
+    
+    int dataLengthRx = sizeRx - sizeof(struct header);
+    if (payloadLength < dataLengthRx) dataLengthRx = payloadLength; //Choose the lesser of the data length and the payload length
+    int dataLengthTx = *pSizeTx - sizeof(struct header);
+    
+    int  scope       = SlaacScope(dstIp);
+    bool isMe        = scope != SCOPE_NONE;
+    bool isMulticast = dstIp[0] == 0xFF;
+    bool isSolicited = getIsSolicited(dstIp);
+    bool isGroup     = getIsSameGroup(dstIp, SlaacLinkLocalIp);
+    
+    bool doIt = isMe || (isMulticast && !isSolicited) || (isGroup && isSolicited);
+    
+    if (!doIt)
+    {
+        if (Ip6Trace)
+        {
+            LogTime("IP6 filtered out ip ");
+            Ip6AddressLog(dstIp);
+            LogF(" from ");
+            Ip6AddressLog(srcIp);
+            Log("\r\n");
+        }
+        return DO_NOTHING;
+    }
+    
+    NetTraceHostCheckIp6(srcIp);
+    
+    Ar6AddIpRecord(trace, macRemote, srcIp);
+    Nr6MakeRequestForNameFromIp(srcIp);
+
+    int action = DO_NOTHING;
+    switch (protocol)
+    {
+        case HOPOPT: action = DO_NOTHING;                                                                                           break;
+        case ICMP6:  action = Icmp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
+        case UDP:    action =  Udp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
+        case TCP:    action =  Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;        
+        default:
+            LogTimeF("IP6 protocol %d unhandled\r\n", protocol);
+            return DO_NOTHING;
+    }
+    if (!action) return DO_NOTHING;
+    
+    if (NdpIpNeedsToBeRouted(dstIp))
+    {
+        MacCopy(macRemote, NdpRouterMac); //Send to the router MAC
+        hoplimit = NdpHopLimit;
+    }
+    else
+    {
+        hoplimit = 255;
+    }
+    
+    payloadLength = dataLengthTx;
+
+    writeHeader(pHeaderTx);
+      
+    *pSizeTx = sizeof(struct header) + payloadLength;
+    
+    if (ActionGetTracePart(action)) logHeader();
+
+    return action;
+}
+int Ip6PollForPacketToSend(void* pPacket, int* pSize, char* pDstMac)
+{    
+    char* pData = (char*)pPacket + sizeof(struct header);
+    int dataLength = *pSize - sizeof(struct header);
+    
+    int action = DO_NOTHING;
+    if (!action)
+    {
+        action = Icmp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
+        protocol = ICMP6;
+    }
+    
+    if (!action)
+    {
+        action = Udp6PollForPacketToSend(pData, &dataLength, srcIp, dstIp);
+        protocol = UDP;
+    }
+    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 (NdpIpNeedsToBeRouted(dstIp))
+            {
+                MacCopy(pDstMac, NdpRouterMac); //Send to the router MAC
+                hoplimit = NdpHopLimit;
+            }
+            else
+            {
+                Ar6IpToMac(dstIp, pDstMac); //Make the remote MAC from NP
+                hoplimit = 255;
+            }
+            break;
+        case MULTICAST_NODE:
+        case MULTICAST_ROUTER:
+        case MULTICAST_MDNS:
+        case MULTICAST_LLMNR:
+        case SOLICITED_NODE:
+            hoplimit = 255;
+            break;
+        default:
+            LogTimeF("Ip6PollForPacketToSend - undefined destination %d\r\n", dest);
+            return DO_NOTHING;
+    }
+
+    payloadLength  = dataLength;
+    version        = 6;
+    writeHeader((struct header*)pPacket);
+
+    *pSize = sizeof(struct header) + payloadLength;
+    
+    if (ActionGetTracePart(action)) logHeader();
+
+    return action;
+}