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:
2020-04-02
Revision:
167:3ba4e3c49631
Parent:
143:8cec8f08dc54
Child:
171:f708d6776752

File content as of revision 167:3ba4e3c49631:

#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(const char* pIp, int size, char* pText)
{
    const 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)
    {
        LogChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a');
        *pAdded = true;
    }
}
int Ip6AddressLog(const char* pIp)
{
    int count = 0;
    const 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;
        
        LogChar(':'); 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(const char* pIp)
{
    int count = 0;
    const 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);
}

bool Ip6AddrIsSolicited(const char* p)
{
    if (*p++ != 0xff) return false;
    if (*p++ != 0x02) return false;
    
    if (*p++ != 0x00) return false;
    if (*p++ != 0x00) return false;
    
    if (*p++ != 0x00) return false;
    if (*p++ != 0x00) return false;
    
    if (*p++ != 0x00) return false;
    if (*p++ != 0x00) return false;
    
    if (*p++ != 0x00) return false;
    if (*p++ != 0x00) return false;
    
    if (*p++ != 0x00) return false;
    if (*p++ != 0x01) return false;
    
    if (*p++ != 0xff) return false;
    
    return true;
}
bool Ip6AddrIsMulticast(const char *p)
{
    return *p == 0xFF;
}
bool Ip6AddrIsSameGroup(const char* pA, const char* pB)
{
    pA += 13;
    pB += 13;
    if (*pA++ != *pB++) return false;
    if (*pA++ != *pB++) return false;
    return *pA == *pB;
}

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, NtpClientQueryServerIp6  ); 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;           
    }
}