Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

ip6/icmp/ns.cpp

Committer:
andrewboyson
Date:
2017-10-22
Revision:
45:3dd57903ec99

File content as of revision 45:3dd57903ec99:

#include   "mbed.h"
#include    "log.h"
#include    "net.h"
#include "action.h"
#include    "ip6.h"
#include    "mac.h"
#include     "nr.h"
#include     "ar.h"
#include    "ip6.h"
#include  "slaac.h"

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

static char srcMAC[6];
static char tgtMAC[6];

char NsAddressToResolve[16];
bool NsResolveRequestFlag = false;

static int logOptions(char* p)
{
    int type = *p++;
    int size = *p++;
    char text[100];
    switch (type)
    {
        case 1:
            MacToString(p, sizeof(text), text);
            LogF("  Src MAC     %s\r\n", text);
            break;
        case 2:
            MacToString(p, sizeof(text), text);
            LogF("  Tgt MAC     %s\r\n", text);
            break;
        default:
            LogF("  Unknown option %d\r\n", type);
            break;
    }
    return size * 8;
}

void logHeader(void* pPacket, int* pSize)
{
    __packed struct header
    {
        uint32_t  reserved;
        char      target[16];
    };
    struct header* pHeader = (header*)pPacket;
    char* pData = (char*)pHeader + sizeof(struct header);
    int dataLength = *pSize - sizeof(struct header);
    
    Log("NDP header\r\n");
    LogF("  Size        %d\r\n", *pSize);
    char text[100];
    Ip6AddressToString(pHeader->target, sizeof(text), text);
    LogF("  Target      %s\r\n", text);
    
    char* p = pData;
    char* pE = pData + dataLength;
    
    while(p < pE) p += logOptions(p);
}

static int decodeOptions(char* p)
{
    int type = *p++;
    int size = *p++;
    switch (type)
    {
        case 1:
            memcpy(srcMAC, p, 6);
            break;
        case 2:
            memcpy(tgtMAC, p, 6);
            break;
        default:
            LogF("  Unknown option %d\r\n", type);
            break;
    }
    return size * 8;
}

int NsHandleReceivedSolicitation(void (*traceback)(void), void* pPacket, int* pSize, uint8_t* pType, uint8_t* pCode)
{
    __packed struct header
    {
        uint32_t  reserved;
        char      target[16];
    };
    struct header* pHeader = (header*)pPacket;
    char* pData = (char*)pHeader + sizeof(struct header);
    int dataLength = *pSize - 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(pPacket, pSize);
    }
    char* p = pData;
    char* pE = pData + dataLength;
    
    while(p < pE) p += decodeOptions(p);
    
    //Send advertisement
    *pType = 136;
    *pCode = 0;
    pHeader->reserved = 0x00000060; //R=0 (not a router); S=1 (solicited); O=1 (override)
                                    //pHeader->target is unchanged
    
    p = pData;
    *p++ = 2; //Target MAC option
    *p++ = 1; //8 bytes
    memcpy(p, MacLocal, 6);
    p += 6;
    
    *pSize = sizeof(struct header) + p - pData;
    
    if (NsTraceRecvSol) logHeader(pPacket, pSize);
    
    return ActionMakeFromDestAndTrace(UNICAST, NsTraceRecvSol && NetTraceStack);

}
int NsHandleReceivedAdvertisement(void (*traceback)(void), void* pPacket, int* pSize)
{
    __packed struct header
    {
        uint32_t  reserved;
        char      target[16];
    };
    struct header* pHeader = (header*)pPacket;
    char* pData = (char*)pHeader + sizeof(struct header);
    int dataLength = *pSize - sizeof(struct header);
    
    if (NsTraceRecvAdv)
    {
        if (NetTraceNewLine) Log("\r\n");
        LogTimeF("NDP received neighbour advertise\r\n");
        if (NetTraceStack) traceback();
        logHeader(pPacket, pSize);
    }
    
    char* p = pData;
    char* pE = pData + dataLength;
    
    while(p < pE) p += decodeOptions(p);
    
    ArAddIp6Record(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;
        
    __packed struct header
    {
        uint32_t  reserved;
        char      target[16];
    };
    struct header* pHeader = (header*)pPacket;
    pHeader->reserved = 0;
    memcpy(pHeader->target, NsAddressToResolve, 16);

    *pSize = sizeof(struct header);
    *pType = 135; //Neighbour solicitation
    *pCode = 0;
    
    char* pData = (char*)pHeader + sizeof(struct header);
    char* p = pData;
    *p++ = 1; //Source MAC option
    *p++ = 1; //8 bytes
    memcpy(p, MacLocal, 6);
    p += 6;
    
    *pSize = sizeof(struct header) + p - pData;

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