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

eth/arp.cpp

Committer:
andrewboyson
Date:
2017-09-22
Revision:
35:93c39d260a83
Parent:
30:e34173b7585c
Child:
36:900e24b27bfb

File content as of revision 35:93c39d260a83:

#include "mbed.h"
#include  "log.h"
#include  "net.h"
#include  "eth.h"
#include  "mac.h"
#include "dhcp.h"
#include   "ar.h"
#include   "nr.h"
#include   "io.h"

#define REQUEST   1
#define REPLY     2

#define DEBUG 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.
};
int ArpHandleReceivedPacket(char* pSrcMac, void * pPacket, int* pSize, char* pDstMac)
{
    struct header*         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:
            memcpy(pHeader->targetHardwareAddress,  pHeader->senderHardwareAddress, 6);
                   pHeader->targetProtocolAddress = pHeader->senderProtocolAddress;
            memcpy(pHeader->senderHardwareAddress,  MacLocal,6);
                   pHeader->senderProtocolAddress = DhcpLocalIp;
                   pHeader->opCode                = NetToHost16(REPLY);
            memcpy(pDstMac, pSrcMac, 6);
            return UNICAST;
        case REPLY:
            ArAddIp4Record(pHeader->senderHardwareAddress, pHeader->senderProtocolAddress);
            NrMakeRequestForNameFromIp4(pHeader->senderProtocolAddress);
            return DO_NOTHING;
        default:
            return DO_NOTHING;
    }
}
int ArpPollForPacketToSend(void* pPacket, int* pSize)
{
    if (!ArpResolveRequestFlag) return DO_NOTHING;
    ArpResolveRequestFlag = false;
    
    struct header* pHeader = (header*)pPacket;
    
    pHeader->hardwareType   = NetToHost16(ETHERNET);
    pHeader->protocolType   = NetToHost16(IPV4);
    pHeader->hardwareLength = 6;
    pHeader->protocolLength = 4;
    pHeader->opCode         = NetToHost16(REQUEST);
    
    memset(pHeader->targetHardwareAddress,  0, 6);
           pHeader->targetProtocolAddress = ArpAddressToResolve;
    memcpy(pHeader->senderHardwareAddress,  MacLocal,6);
           pHeader->senderProtocolAddress = DhcpLocalIp;
           
    *pSize = sizeof(header);
    
    return BROADCAST;
}