Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Revision:
58:d48c899e482f
Parent:
50:492f2d2954e4
Child:
59:e0e556c8bd46
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arp/arp.cpp	Thu Dec 07 20:44:32 2017 +0000
@@ -0,0 +1,149 @@
+#include   "mbed.h"
+#include    "log.h"
+#include "action.h"
+#include    "net.h"
+#include    "eth.h"
+#include    "mac.h"
+#include   "dhcp.h"
+#include    "ar4.h"
+#include    "nr4.h"
+#include     "io.h"
+#include "ip4addr.h"
+
+#define REQUEST   1
+#define REPLY     2
+
+bool ArpTrace = false;
+
+uint32_t ArpAddressToResolve;
+bool     ArpResolveRequestFlag = false;
+
+__packed struct header
+{
+    int16_t  hardwareType;             //16.bit: (ar$hrd) Hardware address space (e.g., Ethernet, Packet Radio Net). Always 1.
+    int16_t  protocolType;             //16.bit: (ar$pro) Protocol address space.  For Ethernet hardware, this is from the set of type fields ether_typ$<protocol>. As held in eth.h, eg IPv4 = 0x8000.
+    int8_t   hardwareLength;           // 8.bit: (ar$hln) byte length of each hardware address. Always 6 bytes.
+    int8_t   protocolLength;           // 8.bit: (ar$pln) byte length of each protocol address. Always 4 bytes.
+    int16_t  opCode;                   //16.bit: (ar$op)  opcode (ares_op$REQUEST = 1 | ares_op$REPLY = 2), high byte transmitted first.
+    char     senderHardwareAddress[6]; //nbytes: (ar$sha) Hardware address of sender of this packet, n from the ar$hln field.
+    uint32_t senderProtocolAddress;    //mbytes: (ar$spa) Protocol address of sender of this packet, m from the ar$pln field.
+    char     targetHardwareAddress[6]; //nbytes: (ar$tha) Hardware address of target of this packet (if known).
+    uint32_t targetProtocolAddress;    //mbytes: (ar$tpa) Protocol address of target.
+};
+static struct header* pHeader;
+
+static void logHeader()
+{    
+    if (NetTraceVerbose)
+    {
+        LogTime("ARP header\r\n");
+        if (NetToHost16(pHeader->hardwareType) == ETHERNET) Log ("  hardwareType          = ETHERNET\r\n");
+        else                                                LogF("  hardwareType          = %d\r\n", NetToHost16(pHeader->hardwareType));
+        Log ("  protocolType          = ");      EthProtocolLog(pHeader->protocolType);          Log("\r\n");
+        LogF("  hardwareLength        = %d\r\n",                pHeader->hardwareLength);
+        LogF("  protocolLength        = %d\r\n",                pHeader->protocolLength);
+        if      (NetToHost16(pHeader->opCode) == REQUEST)   Log ("  opCode                = REQUEST\r\n");
+        else if (NetToHost16(pHeader->opCode) == REPLY  )   Log ("  opCode                = REPLY\r\n");
+        else                                                LogF("  opCode                = %d\r\n", NetToHost16(pHeader->opCode));
+        Log("  senderHardwareAddress = ");               MacLog(pHeader->senderHardwareAddress); Log("\r\n");
+        Log("  senderProtocolAddress = ");        Ip4AddressLog(pHeader->senderProtocolAddress); Log("\r\n");
+        Log("  targetHardwareAddress = ");               MacLog(pHeader->targetHardwareAddress); Log("\r\n");
+        Log("  targetProtocolAddress = ");        Ip4AddressLog(pHeader->targetProtocolAddress); Log("\r\n");
+    }
+    else
+    {
+        Log("ARP header ");
+               MacLog(pHeader->senderHardwareAddress); Log("==");
+        Ip4AddressLog(pHeader->senderProtocolAddress); Log(" >>> ");
+               MacLog(pHeader->targetHardwareAddress); Log("==");
+        Ip4AddressLog(pHeader->targetProtocolAddress); Log("\r\n");
+        
+    }
+}
+static void (*pTraceBack)(void);
+static void trace()
+{
+    pTraceBack();
+    logHeader();
+}
+
+int ArpHandleReceivedPacket(void (*traceback)(void), char* pSrcMac, void * pPacket, int* pSize, char* pDstMac)
+{
+    pTraceBack = traceback;
+    pHeader = (header*)pPacket;
+    int16_t           hardwareType = NetToHost16(pHeader->hardwareType);
+    int16_t           protocolType = NetToHost16(pHeader->protocolType);
+    int8_t          hardwareLength =             pHeader->hardwareLength;
+    int8_t          protocolLength =             pHeader->protocolLength;
+    int16_t                 opCode = NetToHost16(pHeader->opCode);
+    uint32_t targetProtocolAddress =             pHeader->targetProtocolAddress;
+
+    if (hardwareType          != ETHERNET     ) return DO_NOTHING; //This is not ethernet
+    if (protocolType          != IPV4         ) return DO_NOTHING; //This is not IPv4
+    if (hardwareLength        != 6            ) return DO_NOTHING; //This is not a MAC hardware address
+    if (protocolLength        != 4            ) return DO_NOTHING; //This is not an IPv4 IP address
+    if (targetProtocolAddress != DhcpLocalIp  ) return DO_NOTHING; //This packet was not addressed to us
+    
+    switch (opCode)
+    {
+        case REQUEST:
+            if (ArpTrace)
+            {
+                if (NetTraceNewLine) Log("\r\n");
+                LogTime("ARP received request\r\n");
+                if (NetTraceStack) traceback();
+                logHeader();
+            }   
+            MacCopy(pHeader->targetHardwareAddress,  pHeader->senderHardwareAddress);
+                    pHeader->targetProtocolAddress = pHeader->senderProtocolAddress;
+            MacCopy(pHeader->senderHardwareAddress,  MacLocal);
+                    pHeader->senderProtocolAddress = DhcpLocalIp;
+                    pHeader->opCode                = NetToHost16(REPLY);
+            MacCopy(pDstMac, pSrcMac);
+            if (ArpTrace) logHeader();
+            return ActionMakeFromDestAndTrace(UNICAST, ArpTrace && NetTraceStack);
+            
+        case REPLY:
+            if (ArpTrace)
+            {
+                if (NetTraceNewLine) Log("\r\n");
+                LogTime("ARP received reply\r\n");
+                if (NetTraceStack) traceback();
+                logHeader();
+            }   
+            Ar4AddIpRecord(trace, pHeader->senderHardwareAddress, pHeader->senderProtocolAddress);
+            Nr4MakeRequestForNameFromIp(pHeader->senderProtocolAddress);
+            return DO_NOTHING;
+            
+        default:
+            return DO_NOTHING;
+    }
+}
+int ArpPollForPacketToSend(void* pPacket, int* pSize)
+{
+    if (!ArpResolveRequestFlag) return DO_NOTHING;
+    ArpResolveRequestFlag = false;
+
+    pHeader = (header*)pPacket;
+
+    pHeader->hardwareType   = NetToHost16(ETHERNET);
+    pHeader->protocolType   = NetToHost16(IPV4);
+    pHeader->hardwareLength = 6;
+    pHeader->protocolLength = 4;
+    pHeader->opCode         = NetToHost16(REQUEST);
+
+    MacClear(pHeader->targetHardwareAddress);
+             pHeader->targetProtocolAddress = ArpAddressToResolve;
+    MacCopy (pHeader->senderHardwareAddress,  MacLocal);
+             pHeader->senderProtocolAddress = DhcpLocalIp;
+
+    *pSize = sizeof(header);
+    
+    if (ArpTrace)
+    {
+        if (NetTraceNewLine) Log("\r\n");
+        LogTime("ARP send request\r\n");
+        logHeader();
+    }
+    return ActionMakeFromDestAndTrace(BROADCAST, ArpTrace && NetTraceStack);
+}