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@171:f708d6776752, 2020-12-12 (annotated)
- Committer:
- andrewboyson
- Date:
- Sat Dec 12 20:10:02 2020 +0000
- Revision:
- 171:f708d6776752
- Parent:
- 143:8cec8f08dc54
- Child:
- 172:9bc3c7b2cca1
Modified NR to accept both IPV6 and IPV4 addresses instead of having two modules with diffrent address lengths. Encapsulated 32but address into lsb 128 bit address
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 61:aad055f1b0d1 | 1 | #include <stdbool.h> |
andrewboyson | 61:aad055f1b0d1 | 2 | #include <string.h> |
andrewboyson | 61:aad055f1b0d1 | 3 | |
andrewboyson | 49:1a6336f2b3f9 | 4 | #include "log.h" |
andrewboyson | 49:1a6336f2b3f9 | 5 | #include "ip6addr.h" |
andrewboyson | 49:1a6336f2b3f9 | 6 | #include "http.h" |
andrewboyson | 49:1a6336f2b3f9 | 7 | #include "action.h" |
andrewboyson | 49:1a6336f2b3f9 | 8 | #include "ndp.h" |
andrewboyson | 112:f8694d0b8858 | 9 | #include "ntpclient.h" |
andrewboyson | 49:1a6336f2b3f9 | 10 | #include "slaac.h" |
andrewboyson | 57:e0fb648acf48 | 11 | #include "tftp.h" |
andrewboyson | 49:1a6336f2b3f9 | 12 | |
andrewboyson | 49:1a6336f2b3f9 | 13 | void Ip6AddressClear(char* ip) |
andrewboyson | 49:1a6336f2b3f9 | 14 | { |
andrewboyson | 171:f708d6776752 | 15 | ip[ 0] = 0; //Just set the first byte to zero |
andrewboyson | 171:f708d6776752 | 16 | ip[12] = 0; //and the 12 (the first byte of a IP4 address) |
andrewboyson | 49:1a6336f2b3f9 | 17 | } |
andrewboyson | 107:cc58b4c2090b | 18 | bool Ip6AddressIsEmpty(const char* ip) |
andrewboyson | 49:1a6336f2b3f9 | 19 | { |
andrewboyson | 171:f708d6776752 | 20 | return !ip[0] && !ip[12]; //Check for the first and 12th byte being non zero |
andrewboyson | 171:f708d6776752 | 21 | } |
andrewboyson | 171:f708d6776752 | 22 | void Ip6AddressFromIp4(char* ip6, uint32_t ip4) |
andrewboyson | 171:f708d6776752 | 23 | { |
andrewboyson | 171:f708d6776752 | 24 | memset(ip6, 0, 16); |
andrewboyson | 171:f708d6776752 | 25 | *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; |
andrewboyson | 171:f708d6776752 | 26 | *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; |
andrewboyson | 171:f708d6776752 | 27 | *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; *ip6++ = 0; |
andrewboyson | 171:f708d6776752 | 28 | *ip6++ = (ip4 >> 0) & 0xFF; |
andrewboyson | 171:f708d6776752 | 29 | *ip6++ = (ip4 >> 8) & 0xFF; |
andrewboyson | 171:f708d6776752 | 30 | *ip6++ = (ip4 >> 16) & 0xFF; |
andrewboyson | 171:f708d6776752 | 31 | *ip6++ = (ip4 >> 24) & 0xFF; |
andrewboyson | 171:f708d6776752 | 32 | } |
andrewboyson | 171:f708d6776752 | 33 | uint32_t Ip6AddressToIp4(char* ip6) |
andrewboyson | 171:f708d6776752 | 34 | { |
andrewboyson | 171:f708d6776752 | 35 | uint32_t ip4; |
andrewboyson | 171:f708d6776752 | 36 | ip4 = ip6[12] << 0; |
andrewboyson | 171:f708d6776752 | 37 | ip4 |= ip6[13] << 8; |
andrewboyson | 171:f708d6776752 | 38 | ip4 |= ip6[14] << 16; |
andrewboyson | 171:f708d6776752 | 39 | ip4 |= ip6[15] << 24; |
andrewboyson | 171:f708d6776752 | 40 | return ip4; |
andrewboyson | 49:1a6336f2b3f9 | 41 | } |
andrewboyson | 49:1a6336f2b3f9 | 42 | static void addHexNibble(bool* pAdded, int number, int index, char** pp) |
andrewboyson | 49:1a6336f2b3f9 | 43 | { |
andrewboyson | 49:1a6336f2b3f9 | 44 | int nibble = number; |
andrewboyson | 49:1a6336f2b3f9 | 45 | if (index) nibble >>= 4; |
andrewboyson | 49:1a6336f2b3f9 | 46 | nibble &= 0xF; |
andrewboyson | 49:1a6336f2b3f9 | 47 | |
andrewboyson | 49:1a6336f2b3f9 | 48 | if (nibble || *pAdded) |
andrewboyson | 49:1a6336f2b3f9 | 49 | { |
andrewboyson | 49:1a6336f2b3f9 | 50 | **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a'; |
andrewboyson | 49:1a6336f2b3f9 | 51 | *pp += 1; |
andrewboyson | 49:1a6336f2b3f9 | 52 | *pAdded = true; |
andrewboyson | 49:1a6336f2b3f9 | 53 | } |
andrewboyson | 49:1a6336f2b3f9 | 54 | } |
andrewboyson | 143:8cec8f08dc54 | 55 | int Ip6AddressToString(const char* pIp, int size, char* pText) |
andrewboyson | 49:1a6336f2b3f9 | 56 | { |
andrewboyson | 143:8cec8f08dc54 | 57 | const char* pIpE = pIp + 16; |
andrewboyson | 49:1a6336f2b3f9 | 58 | char* p = pText; |
andrewboyson | 49:1a6336f2b3f9 | 59 | while (true) |
andrewboyson | 49:1a6336f2b3f9 | 60 | { |
andrewboyson | 49:1a6336f2b3f9 | 61 | bool added = false; |
andrewboyson | 49:1a6336f2b3f9 | 62 | if (*pIp || *(pIp + 1)) |
andrewboyson | 49:1a6336f2b3f9 | 63 | { |
andrewboyson | 49:1a6336f2b3f9 | 64 | if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 1, &p); |
andrewboyson | 49:1a6336f2b3f9 | 65 | if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 0, &p); |
andrewboyson | 49:1a6336f2b3f9 | 66 | if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 1, &p); |
andrewboyson | 49:1a6336f2b3f9 | 67 | if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 0, &p); |
andrewboyson | 49:1a6336f2b3f9 | 68 | } |
andrewboyson | 49:1a6336f2b3f9 | 69 | |
andrewboyson | 49:1a6336f2b3f9 | 70 | pIp += 2; |
andrewboyson | 49:1a6336f2b3f9 | 71 | if (pIp >= pIpE) break; |
andrewboyson | 49:1a6336f2b3f9 | 72 | |
andrewboyson | 49:1a6336f2b3f9 | 73 | if (p > pText + size - 2) break; *p++ = ':'; |
andrewboyson | 49:1a6336f2b3f9 | 74 | } |
andrewboyson | 49:1a6336f2b3f9 | 75 | *p = 0; |
andrewboyson | 49:1a6336f2b3f9 | 76 | return p - pText; |
andrewboyson | 49:1a6336f2b3f9 | 77 | } |
andrewboyson | 49:1a6336f2b3f9 | 78 | static void logHexNibble(bool* pAdded, int number, int index) |
andrewboyson | 49:1a6336f2b3f9 | 79 | { |
andrewboyson | 49:1a6336f2b3f9 | 80 | int nibble = number; |
andrewboyson | 49:1a6336f2b3f9 | 81 | if (index) nibble >>= 4; |
andrewboyson | 49:1a6336f2b3f9 | 82 | nibble &= 0xF; |
andrewboyson | 49:1a6336f2b3f9 | 83 | |
andrewboyson | 49:1a6336f2b3f9 | 84 | if (nibble || *pAdded) |
andrewboyson | 49:1a6336f2b3f9 | 85 | { |
andrewboyson | 121:bc048b65a630 | 86 | LogChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a'); |
andrewboyson | 49:1a6336f2b3f9 | 87 | *pAdded = true; |
andrewboyson | 49:1a6336f2b3f9 | 88 | } |
andrewboyson | 49:1a6336f2b3f9 | 89 | } |
andrewboyson | 143:8cec8f08dc54 | 90 | int Ip6AddressLog(const char* pIp) |
andrewboyson | 49:1a6336f2b3f9 | 91 | { |
andrewboyson | 49:1a6336f2b3f9 | 92 | int count = 0; |
andrewboyson | 143:8cec8f08dc54 | 93 | const char* pIpE = pIp + 16; |
andrewboyson | 49:1a6336f2b3f9 | 94 | while (true) |
andrewboyson | 49:1a6336f2b3f9 | 95 | { |
andrewboyson | 49:1a6336f2b3f9 | 96 | bool added = false; |
andrewboyson | 49:1a6336f2b3f9 | 97 | if (*pIp || *(pIp + 1)) |
andrewboyson | 49:1a6336f2b3f9 | 98 | { |
andrewboyson | 49:1a6336f2b3f9 | 99 | logHexNibble(&added, *(pIp + 0), 1); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 100 | logHexNibble(&added, *(pIp + 0), 0); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 101 | logHexNibble(&added, *(pIp + 1), 1); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 102 | logHexNibble(&added, *(pIp + 1), 0); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 103 | } |
andrewboyson | 49:1a6336f2b3f9 | 104 | |
andrewboyson | 49:1a6336f2b3f9 | 105 | pIp += 2; |
andrewboyson | 49:1a6336f2b3f9 | 106 | if (pIp >= pIpE) break; |
andrewboyson | 49:1a6336f2b3f9 | 107 | |
andrewboyson | 121:bc048b65a630 | 108 | LogChar(':'); count++; |
andrewboyson | 49:1a6336f2b3f9 | 109 | } |
andrewboyson | 49:1a6336f2b3f9 | 110 | return count; |
andrewboyson | 49:1a6336f2b3f9 | 111 | } |
andrewboyson | 49:1a6336f2b3f9 | 112 | static void httpHexNibble(bool* pAdded, int number, int index) |
andrewboyson | 49:1a6336f2b3f9 | 113 | { |
andrewboyson | 49:1a6336f2b3f9 | 114 | int nibble = number; |
andrewboyson | 49:1a6336f2b3f9 | 115 | if (index) nibble >>= 4; |
andrewboyson | 49:1a6336f2b3f9 | 116 | nibble &= 0xF; |
andrewboyson | 49:1a6336f2b3f9 | 117 | |
andrewboyson | 49:1a6336f2b3f9 | 118 | if (nibble || *pAdded) |
andrewboyson | 49:1a6336f2b3f9 | 119 | { |
andrewboyson | 54:84ef2b29cf7e | 120 | HttpAddChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a'); |
andrewboyson | 49:1a6336f2b3f9 | 121 | *pAdded = true; |
andrewboyson | 49:1a6336f2b3f9 | 122 | } |
andrewboyson | 49:1a6336f2b3f9 | 123 | } |
andrewboyson | 143:8cec8f08dc54 | 124 | int Ip6AddressHttp(const char* pIp) |
andrewboyson | 49:1a6336f2b3f9 | 125 | { |
andrewboyson | 49:1a6336f2b3f9 | 126 | int count = 0; |
andrewboyson | 143:8cec8f08dc54 | 127 | const char* pIpE = pIp + 16; |
andrewboyson | 49:1a6336f2b3f9 | 128 | while (true) |
andrewboyson | 49:1a6336f2b3f9 | 129 | { |
andrewboyson | 49:1a6336f2b3f9 | 130 | bool added = false; |
andrewboyson | 49:1a6336f2b3f9 | 131 | if (*pIp || *(pIp + 1)) |
andrewboyson | 49:1a6336f2b3f9 | 132 | { |
andrewboyson | 49:1a6336f2b3f9 | 133 | httpHexNibble(&added, *(pIp + 0), 1); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 134 | httpHexNibble(&added, *(pIp + 0), 0); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 135 | httpHexNibble(&added, *(pIp + 1), 1); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 136 | httpHexNibble(&added, *(pIp + 1), 0); if (added) count++; |
andrewboyson | 49:1a6336f2b3f9 | 137 | } |
andrewboyson | 49:1a6336f2b3f9 | 138 | |
andrewboyson | 49:1a6336f2b3f9 | 139 | pIp += 2; |
andrewboyson | 49:1a6336f2b3f9 | 140 | if (pIp >= pIpE) break; |
andrewboyson | 49:1a6336f2b3f9 | 141 | |
andrewboyson | 54:84ef2b29cf7e | 142 | HttpAddChar(':'); count++; |
andrewboyson | 49:1a6336f2b3f9 | 143 | } |
andrewboyson | 49:1a6336f2b3f9 | 144 | return count; |
andrewboyson | 49:1a6336f2b3f9 | 145 | } |
andrewboyson | 107:cc58b4c2090b | 146 | bool Ip6AddressIsSame(const char* ipA, const char* ipB) |
andrewboyson | 49:1a6336f2b3f9 | 147 | { |
andrewboyson | 49:1a6336f2b3f9 | 148 | 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 |
andrewboyson | 49:1a6336f2b3f9 | 149 | } |
andrewboyson | 107:cc58b4c2090b | 150 | void Ip6AddressCopy(char* ipTo, const char* ipFrom) |
andrewboyson | 49:1a6336f2b3f9 | 151 | { |
andrewboyson | 49:1a6336f2b3f9 | 152 | memcpy(ipTo, ipFrom, 16); |
andrewboyson | 49:1a6336f2b3f9 | 153 | } |
andrewboyson | 49:1a6336f2b3f9 | 154 | |
andrewboyson | 143:8cec8f08dc54 | 155 | bool Ip6AddrIsSolicited(const char* p) |
andrewboyson | 136:8a65abb0dc63 | 156 | { |
andrewboyson | 136:8a65abb0dc63 | 157 | if (*p++ != 0xff) return false; |
andrewboyson | 136:8a65abb0dc63 | 158 | if (*p++ != 0x02) return false; |
andrewboyson | 136:8a65abb0dc63 | 159 | |
andrewboyson | 136:8a65abb0dc63 | 160 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 161 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 162 | |
andrewboyson | 136:8a65abb0dc63 | 163 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 164 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 165 | |
andrewboyson | 136:8a65abb0dc63 | 166 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 167 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 168 | |
andrewboyson | 136:8a65abb0dc63 | 169 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 170 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 171 | |
andrewboyson | 136:8a65abb0dc63 | 172 | if (*p++ != 0x00) return false; |
andrewboyson | 136:8a65abb0dc63 | 173 | if (*p++ != 0x01) return false; |
andrewboyson | 136:8a65abb0dc63 | 174 | |
andrewboyson | 136:8a65abb0dc63 | 175 | if (*p++ != 0xff) return false; |
andrewboyson | 136:8a65abb0dc63 | 176 | |
andrewboyson | 136:8a65abb0dc63 | 177 | return true; |
andrewboyson | 136:8a65abb0dc63 | 178 | } |
andrewboyson | 143:8cec8f08dc54 | 179 | bool Ip6AddrIsMulticast(const char *p) |
andrewboyson | 136:8a65abb0dc63 | 180 | { |
andrewboyson | 136:8a65abb0dc63 | 181 | return *p == 0xFF; |
andrewboyson | 136:8a65abb0dc63 | 182 | } |
andrewboyson | 171:f708d6776752 | 183 | bool Ip6AddrIsIp4(const char *p) |
andrewboyson | 171:f708d6776752 | 184 | { |
andrewboyson | 171:f708d6776752 | 185 | return p[0] == 0 && p[12] != 0; |
andrewboyson | 171:f708d6776752 | 186 | } |
andrewboyson | 143:8cec8f08dc54 | 187 | bool Ip6AddrIsSameGroup(const char* pA, const char* pB) |
andrewboyson | 136:8a65abb0dc63 | 188 | { |
andrewboyson | 136:8a65abb0dc63 | 189 | pA += 13; |
andrewboyson | 136:8a65abb0dc63 | 190 | pB += 13; |
andrewboyson | 136:8a65abb0dc63 | 191 | if (*pA++ != *pB++) return false; |
andrewboyson | 136:8a65abb0dc63 | 192 | if (*pA++ != *pB++) return false; |
andrewboyson | 136:8a65abb0dc63 | 193 | return *pA == *pB; |
andrewboyson | 136:8a65abb0dc63 | 194 | } |
andrewboyson | 136:8a65abb0dc63 | 195 | |
andrewboyson | 107:cc58b4c2090b | 196 | const char Ip6AddressAllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; |
andrewboyson | 107:cc58b4c2090b | 197 | const char Ip6AddressAllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; |
andrewboyson | 107:cc58b4c2090b | 198 | const char Ip6AddressMdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}; |
andrewboyson | 107:cc58b4c2090b | 199 | const char Ip6AddressLlmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}; |
andrewboyson | 107:cc58b4c2090b | 200 | const char Ip6AddressNtp [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}; |
andrewboyson | 49:1a6336f2b3f9 | 201 | |
andrewboyson | 49:1a6336f2b3f9 | 202 | void Ip6AddressFromDest(int dest, char* pDstIp) |
andrewboyson | 49:1a6336f2b3f9 | 203 | { |
andrewboyson | 49:1a6336f2b3f9 | 204 | switch (dest) |
andrewboyson | 49:1a6336f2b3f9 | 205 | { |
andrewboyson | 171:f708d6776752 | 206 | case UNICAST: /*No change*/ break; |
andrewboyson | 171:f708d6776752 | 207 | case UNICAST_DNS: Ip6AddressCopy(pDstIp, NdpDnsServer ); break; |
andrewboyson | 171:f708d6776752 | 208 | case UNICAST_NTP: Ip6AddressCopy(pDstIp, NtpClientQueryServerIp6); break; |
andrewboyson | 171:f708d6776752 | 209 | case UNICAST_TFTP: Ip6AddressCopy(pDstIp, TftpServerIp6 ); break; |
andrewboyson | 171:f708d6776752 | 210 | case MULTICAST_NODE: Ip6AddressCopy(pDstIp, Ip6AddressAllNodes ); break; |
andrewboyson | 171:f708d6776752 | 211 | case MULTICAST_ROUTER: Ip6AddressCopy(pDstIp, Ip6AddressAllRouters ); break; |
andrewboyson | 171:f708d6776752 | 212 | case MULTICAST_MDNS: Ip6AddressCopy(pDstIp, Ip6AddressMdns ); break; |
andrewboyson | 171:f708d6776752 | 213 | case MULTICAST_LLMNR: Ip6AddressCopy(pDstIp, Ip6AddressLlmnr ); break; |
andrewboyson | 171:f708d6776752 | 214 | case MULTICAST_NTP: Ip6AddressCopy(pDstIp, Ip6AddressNtp ); break; |
andrewboyson | 49:1a6336f2b3f9 | 215 | default: |
andrewboyson | 52:fbc5a46b5e16 | 216 | LogTimeF("Ip6AddressFromDest unknown destination %d\r\n", dest); |
andrewboyson | 49:1a6336f2b3f9 | 217 | break; |
andrewboyson | 49:1a6336f2b3f9 | 218 | } |
andrewboyson | 49:1a6336f2b3f9 | 219 | } |