Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

ip6/icmp/ndp/ndp.cpp

Committer:
andrewboyson
Date:
2017-10-24
Revision:
46:40d33e9037e4
Child:
47:73af5c0b0dc2

File content as of revision 46:40d33e9037e4:

#include "mbed.h"
#include "log.h"
#include "mac.h"
#include "ip6.h"
#include "slaac.h"
#include "clock.h"
#include "rs.h"

int      NdpHopLimit                = 0;
bool     NdpManagedAddressConfiguration = false;
bool     NdpOtherConfiguration      = false;
int      NdpLifetime                = 0;

char     NdpRouterMac[6];

int      NdpPrefixLength            = 0;
uint8_t  NdpPrefixLA                = 0;
uint32_t NdpPrefixValidLifetime     = 0;
uint32_t NdpPrefixPreferredLifetime = 0;
char     NdpPrefix[16];

uint32_t NdpDnsLifetime = 0;
char     NdpDnsServer[16];

int      NdpMtu = 0;

uint32_t NdpElapsedTime = 0;         //Reset whenever an IP address request has been acknowledged 

static char dstMAC[6];

bool NdpIpNeedsToBeRouted(char* ip)
{
    //Check address is assigned to internet
    if (*(ip + 0) != 0x20) return false;
    if (*(ip + 1) != 0x00) return false;
    
    //Check it is not our own prefix
    if (memcmp(ip, NdpPrefix, 8) == 0) return false;
    
    return true;
}

static uint32_t decodeUint32(char* p)
{
    uint32_t value = 0;
    value |= *p++ << 24;
    value |= *p++ << 12;
    value |= *p++ <<  8;
    value |= *p++ <<  0;
    return value;
}
static int decodeOption(char* p)
{
    int type = *p++;
    int size = *p++;
    switch (type)
    {
        case 1:
            MacCopy(NdpRouterMac, p);
            break;
        case 2:
            MacCopy(dstMAC, p);
            break;
        case 3:
            NdpPrefixLength = *p++;
            NdpPrefixLA     = *p++;
            NdpPrefixValidLifetime = decodeUint32(p);
            p += 4;
            NdpPrefixPreferredLifetime = decodeUint32(p);
            p += 4;
            p += 4; //Skip gracefully past the Reserved2 field
            Ip6Copy(NdpPrefix, p);
            SlaacMakeGlobal(NdpPrefix);
            break;
        case 5:
            p += 2; //Skip past the reserved field
            NdpMtu = decodeUint32(p);
            break;
        case 25:
            p += 2; //Skip past the reserved field
            NdpDnsLifetime = decodeUint32(p);
            p += 4;
            Ip6Copy(NdpDnsServer, p);
            break;
        default:
            LogF("    Unknown option %d\r\n", type);
            break;
    }
    return size * 8;
}
int NdpAddOptionSourceMac(char* p, char* pMac)
{
    *p++ = 1; //Source MAC option
    *p++ = 1; //8 bytes
    MacCopy(p, pMac);
    return 8;
}
static int logOption(char* p)
{
    char text[100];
    uint32_t value;
    int type = *p++;
    int size = *p++;
    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("    Dst MAC          %s\r\n", text);
            break;
        case 3:
            LogF("    Prefix length    %d\r\n", *p++);
            LogF("    Prefix LA        %X\r\n", *p++);
            value = decodeUint32(p);           p += 4;
            LogF("    Prefix valid     %u seconds\r\n", value);
            value = decodeUint32(p);           p += 4;
            LogF("    Prefix preferred %u seconds\r\n", value);
            p += 4; //Skip gracefully past the Reserved2 field
            Ip6AddressToString(p, sizeof(text), text);
            LogF("    Prefix           %s\r\n", text);
            break;
        case 5:
            p += 2; //Skip past the reserved field
            value = decodeUint32(p);
            p += 4;
            LogF("    MTU              %u\r\n", value);
            break;
        case 25:
            p += 2; //Skip past the reserved field
            value = decodeUint32(p);
            p += 4;
            LogF("    DNS lifetime     %u\r\n", value);
            Ip6AddressToString(p, sizeof(text), text);
            LogF("    DNS Server       %s\r\n", text);
            break;
        default:
            LogF("    Unknown option   %d\r\n", type);
            break;
    }
    return size * 8;
}
void NdpDecodeOptions(char* pData, int dataLength)
{
    char* p = pData;
    char* pE = pData + dataLength;
    while(p < pE) p += decodeOption(p);
}
void NdpLogOptions(char* pData, int dataLength)
{
    char* p = pData;
    char* pE = pData + dataLength;
    while(p < pE) p += logOption(p);
}