Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

ip6/icmp/ndp/ns.cpp

Committer:
andrewboyson
Date:
2017-11-02
Revision:
49:1a6336f2b3f9
Parent:
48:952dddb74b8b
Child:
50:492f2d2954e4

File content as of revision 49:1a6336f2b3f9:

#include   "mbed.h"
#include    "log.h"
#include    "net.h"
#include "action.h"
#include "ip6addr.h"
#include    "mac.h"
#include     "nr.h"
#include    "ar6.h"
#include    "ip6.h"
#include  "slaac.h"
#include    "ndp.h"

bool NsTraceRecvSol = false;
bool NsTraceRecvAdv = false;
bool NsTraceSendSol = false;

char NsAddressToResolve[16];
bool NsResolveRequestFlag = false;

__packed struct header
{
    uint32_t  reserved;
    char      target[16];
};
static struct header * pHeader;
static int size;

static void logHeader()
{
    char* pData = (char*)pHeader + sizeof(struct header);
    int dataLength = size - sizeof(struct header);
    
    if (NetTraceVerbose)
    {
        Log("NS header\r\n");
        LogF("  Size        %d\r\n", size);
        LogF("  Target      "); Ip6AddressLog(pHeader->target); Log("\r\n");
        NdpLogOptionsVerbose(pData, dataLength);
    }
    else
    {
        Log("NS    header ");
        Ip6AddressLog(pHeader->target);
        NdpLogOptionsQuiet(pData, dataLength); 
        Log("\r\n");
    }
}
static void (*pTraceBack)(void);
static void trace()
{
    pTraceBack();
    logHeader();
}
int NsHandleReceivedSolicitation(void (*traceback)(void), void* pPacket, int* pSize, uint8_t* pType, uint8_t* pCode)
{
    pTraceBack = traceback;
    pHeader = (header*)pPacket;
    size = *pSize;
    char* pData = (char*)pHeader + sizeof(struct header);
    
    //Check it is us
    if (!SlaacScope(pHeader->target)) return DO_NOTHING;

    if (NsTraceRecvSol)
    {
        if (NetTraceNewLine) Log("\r\n");
        LogTimeF("NDP received neighbour solicit\r\n");
        if (NetTraceStack) traceback();
        logHeader();
    }
    
    //Send advertisement
    *pType = 136;
    *pCode = 0;
    pHeader->reserved = 0x00000060; //R=0 (not a router); S=1 (solicited); O=1 (override)
                                    //pHeader->target is unchanged
    
    //Add target MAC
    char* p = pData;
    p += NdpAddOptionTargetMac(p, MacLocal);
    
    size = sizeof(struct header) + p - pData;
    *pSize = *pSize;
    
    if (NsTraceRecvSol) logHeader();
    
    return ActionMakeFromDestAndTrace(UNICAST, NsTraceRecvSol && NetTraceStack);

}
int NsHandleReceivedAdvertisement(void (*traceback)(void), void* pPacket, int* pSize)
{
    pTraceBack = traceback;
    pHeader = (header*)pPacket;
    size = *pSize;
    char* pData = (char*)pHeader + sizeof(struct header);
    int dataLength = size - sizeof(struct header);
    
    if (NsTraceRecvAdv)
    {
        if (NetTraceNewLine) Log("\r\n");
        LogTimeF("NDP received neighbour advertise\r\n");
        if (NetTraceStack) traceback();
        logHeader();
    }
    
    char tgtMac[6];
    NdpDecodeOptions(pData, dataLength, NULL, tgtMac);
    
    Ar6AddIpRecord(trace, tgtMac, pHeader->target);
    NrMakeRequestForNameFromIp6(pHeader->target);
    
    return DO_NOTHING;
}

int NsGetWaitingSolicitation(void* pPacket, int* pSize, uint8_t* pType, uint8_t* pCode)
{    
    if (!NsResolveRequestFlag) return DO_NOTHING;
    NsResolveRequestFlag = false;

    *pType = 135; //Neighbour solicitation
    *pCode = 0;
        
    pHeader = (header*)pPacket;
    size = *pSize;
    pHeader->reserved = 0;
    Ip6AddressCopy(pHeader->target, NsAddressToResolve);
    
    char* pData = (char*)pHeader + sizeof(struct header);
    char* p = pData;
    p += NdpAddOptionSourceMac(p, MacLocal);
    
    size = sizeof(struct header) + p - pData;
    *pSize = *pSize;

    if (NsTraceSendSol)
    {
        if (NetTraceNewLine) Log("\r\n");
        LogTimeF("NDP sent neighbour solicit\r\n");
        logHeader();
    }
    
    return ActionMakeFromDestAndTrace(MULTICAST_NODE, NsTraceSendSol && NetTraceStack);
    
}