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:
- 2021-05-20
- Revision:
- 200:5acbc41bf469
- Parent:
- 193:47a953ab571b
File content as of revision 200:5acbc41bf469:
#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 Ip6AddrClear(char* ip) { ip[ 0] = 0; //Just set the first byte to zero } bool Ip6AddrIsEmpty(const char* ip) { return !ip[0]; //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 Ip6AddrToString(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; } void Ip6AddrParse(const char *pText, char *address) //Contains an empty address if invalid { int field = 0; int word = 0; while(true) { switch (*pText) { case ':': address[field] = (word >> 8) & 0xFF; field++; if (field > 15) { address[0] = 0; return; } address[field] = word & 0xFF; field++; if (field > 15) { address[0] = 0; return; } word = 0; break; case '0': word <<= 4; word |= 0; break; case '1': word <<= 4; word |= 1; break; case '2': word <<= 4; word |= 2; break; case '3': word <<= 4; word |= 3; break; case '4': word <<= 4; word |= 4; break; case '5': word <<= 4; word |= 5; break; case '6': word <<= 4; word |= 6; break; case '7': word <<= 4; word |= 7; break; case '8': word <<= 4; word |= 8; break; case '9': word <<= 4; word |= 9; break; case 'a': case 'A': word <<= 4; word |= 10; break; case 'b': case 'B': word <<= 4; word |= 11; break; case 'c': case 'C': word <<= 4; word |= 12; break; case 'd': case 'D': word <<= 4; word |= 13; break; case 'e': case 'E': word <<= 4; word |= 14; break; case 'f': case 'F': word <<= 4; word |= 15; break; case 0: address[field] = (word >> 8) & 0xFF; field++; if (field != 15) { address[0] = 0; return; } address[field] = word & 0xFF; return; default: address[0] = 0; return; } 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 Ip6AddrLog(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 Ip6AddrHttp(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 Ip6AddrIsSame(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 Ip6AddrCopy(char* ipTo, const char* ipFrom) { memcpy(ipTo, ipFrom, 16); } bool Ip6AddrIsLinkLocal(const char* p) { if (p[0] != 0xFE) return false; if (p[1] != 0x80) return false; return true; } bool Ip6AddrIsUniqueLocal(const char* p) { if (p[0] != 0xFD) return false; if (p[1] != 0x00) return false; return true; } bool Ip6AddrIsGlobal(const char* p) { //[RFC 4291] designates 2000::/3 to be global unicast address space that the Internet Assigned Numbers Authority (IANA) may allocate to the RIRs. //The top byte AND 0b11100000 (0xE0)must be 0x20 return (p[0] & 0xE0) == 0x20; } bool Ip6AddrIsExternal(const char* p) { //Logic is address must be global and not have the global prefix if (!Ip6AddrIsGlobal(p)) return false; if (!NdpGlobalPrefixLength) return false; if (memcmp(NdpGlobalPrefix, p, NdpGlobalPrefixLength) != 0) return false; //Only 0 if the same return true; } 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 Ip6AddrAllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; const char Ip6AddrAllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; const char Ip6AddrMdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}; const char Ip6AddrLlmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}; const char Ip6AddrNtp [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}; void Ip6AddrFromDest(int dest, char* pDstIp) { switch (dest) { case UNICAST: /*No change*/ break; case UNICAST_DNS: Ip6AddrCopy(pDstIp, NdpDnsServer ); break; case UNICAST_NTP: Ip6AddrCopy(pDstIp, NtpClientQueryServerIp6); break; case UNICAST_TFTP: Ip6AddrCopy(pDstIp, TftpServerIp6 ); break; case MULTICAST_NODE: Ip6AddrCopy(pDstIp, Ip6AddrAllNodes ); break; case MULTICAST_ROUTER: Ip6AddrCopy(pDstIp, Ip6AddrAllRouters ); break; case MULTICAST_MDNS: Ip6AddrCopy(pDstIp, Ip6AddrMdns ); break; case MULTICAST_LLMNR: Ip6AddrCopy(pDstIp, Ip6AddrLlmnr ); break; case MULTICAST_NTP: Ip6AddrCopy(pDstIp, Ip6AddrNtp ); break; default: LogTimeF("Ip6AddressFromDest unknown destination %d\r\n", dest); break; } }