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

ip6/ip6addr.c

Committer:
andrewboyson
Date:
2019-01-21
Revision:
112:f8694d0b8858
Parent:
107:cc58b4c2090b
Child:
113:904b40231907

File content as of revision 112:f8694d0b8858:

#include <stdbool.h>
#include <string.h>

#include     "log.h"
#include "ip6addr.h"
#include    "http.h"
#include  "action.h"
#include     "ndp.h"
#include "ntpclient.h"
#include   "slaac.h"
#include    "tftp.h"

void Ip6AddressClear(char* ip)
{
    *ip = 0; //Just set the first byte to zero
}
bool Ip6AddressIsEmpty(const char* ip)
{
    return !*ip; //Just check for the first byte being non zero
}
static void addHexNibble(bool* pAdded, int number, int index, char** pp)
{
    int nibble = number;
    if (index) nibble >>= 4;
    nibble &= 0xF;
    
    if (nibble || *pAdded)
    {
        **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
        *pp += 1;
        *pAdded = true;
    }
}
int Ip6AddressToString(char* pIp, int size, char* pText)
{
    char* pIpE = pIp + 16;
    char* p = pText;
    while (true)
    {
        bool added = false;
        if (*pIp || *(pIp + 1))
        {
            if (p > pText + size - 2) break;  addHexNibble(&added, *(pIp + 0), 1, &p);
            if (p > pText + size - 2) break;  addHexNibble(&added, *(pIp + 0), 0, &p);
            if (p > pText + size - 2) break;  addHexNibble(&added, *(pIp + 1), 1, &p);
            if (p > pText + size - 2) break;  addHexNibble(&added, *(pIp + 1), 0, &p);
        }
        
        pIp += 2;
        if (pIp >= pIpE) break;
        
        if (p > pText + size - 2) break; *p++ = ':';
    }
    *p = 0;
    return p - pText;
}
static void logHexNibble(bool* pAdded, int number, int index)
{
    int nibble = number;
    if (index) nibble >>= 4;
    nibble &= 0xF;
    
    if (nibble || *pAdded)
    {
        LogPush(nibble < 10 ? nibble + '0' : nibble - 10 + 'a');
        *pAdded = true;
    }
}
int Ip6AddressLog(char* pIp)
{
    int count = 0;
    char* pIpE = pIp + 16;
    while (true)
    {
        bool added = false;
        if (*pIp || *(pIp + 1))
        {
            logHexNibble(&added, *(pIp + 0), 1); if (added) count++;
            logHexNibble(&added, *(pIp + 0), 0); if (added) count++;
            logHexNibble(&added, *(pIp + 1), 1); if (added) count++;
            logHexNibble(&added, *(pIp + 1), 0); if (added) count++;
        }
        
        pIp += 2;
        if (pIp >= pIpE) break;
        
        LogPush(':'); count++;
    }
    return count;
}
static void httpHexNibble(bool* pAdded, int number, int index)
{
    int nibble = number;
    if (index) nibble >>= 4;
    nibble &= 0xF;
    
    if (nibble || *pAdded)
    {
        HttpAddChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a');
        *pAdded = true;
    }
}
int Ip6AddressHttp(char* pIp)
{
    int count = 0;
    char* pIpE = pIp + 16;
    while (true)
    {
        bool added = false;
        if (*pIp || *(pIp + 1))
        {
            httpHexNibble(&added, *(pIp + 0), 1); if (added) count++;
            httpHexNibble(&added, *(pIp + 0), 0); if (added) count++;
            httpHexNibble(&added, *(pIp + 1), 1); if (added) count++;
            httpHexNibble(&added, *(pIp + 1), 0); if (added) count++;
        }
        
        pIp += 2;
        if (pIp >= pIpE) break;
        
        HttpAddChar(':'); count++;
    }
    return count;
}
bool Ip6AddressIsSame(const char* ipA, const char* ipB)
{
    return !memcmp(ipA, ipB, 16); //Though about optimising by doing a reverse loop but unlikely to be faster than an optimised assembly coded library function
}
void Ip6AddressCopy(char* ipTo, const char* ipFrom)
{
    memcpy(ipTo, ipFrom, 16);
}

const char Ip6AddressAllNodes  [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
const char Ip6AddressAllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
const char Ip6AddressMdns      [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
const char Ip6AddressLlmnr     [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03};
const char Ip6AddressNtp       [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};

void Ip6AddressFromDest(int dest, char* pDstIp)
{
    switch (dest)
    {
        case   UNICAST:        /*No change*/                                 break;
        case   UNICAST_DNS:    Ip6AddressCopy(pDstIp, NdpDnsServer        ); break;
        case   UNICAST_NTP:    Ip6AddressCopy(pDstIp, NtpClientServerIp6  ); break;
        case   UNICAST_TFTP:   Ip6AddressCopy(pDstIp, TftpServerIp6       ); break;
        case MULTICAST_NODE:   Ip6AddressCopy(pDstIp, Ip6AddressAllNodes  ); break;
        case MULTICAST_ROUTER: Ip6AddressCopy(pDstIp, Ip6AddressAllRouters); break;
        case MULTICAST_MDNS:   Ip6AddressCopy(pDstIp, Ip6AddressMdns      ); break;
        case MULTICAST_LLMNR:  Ip6AddressCopy(pDstIp, Ip6AddressLlmnr     ); break;
        case MULTICAST_NTP:    Ip6AddressCopy(pDstIp, Ip6AddressNtp       ); break;
        default:
            LogTimeF("Ip6AddressFromDest unknown destination %d\r\n", dest);
            break;           
    }
}