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

Committer:
andrewboyson
Date:
Thu May 20 14:32:52 2021 +0000
Revision:
200:5acbc41bf469
Parent:
193:47a953ab571b
Increased number of arp entries from 20 to 30 to accommodate the number of WIZ devices plus a few incoming port 80 calls from the internet.

Who changed what in which revision?

UserRevisionLine numberNew 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 172:9bc3c7b2cca1 13 void Ip6AddrClear(char* ip)
andrewboyson 49:1a6336f2b3f9 14 {
andrewboyson 171:f708d6776752 15 ip[ 0] = 0; //Just set the first byte to zero
andrewboyson 49:1a6336f2b3f9 16 }
andrewboyson 172:9bc3c7b2cca1 17 bool Ip6AddrIsEmpty(const char* ip)
andrewboyson 49:1a6336f2b3f9 18 {
andrewboyson 176:7eb916c22084 19 return !ip[0]; //Check for the first byte being non zero
andrewboyson 49:1a6336f2b3f9 20 }
andrewboyson 49:1a6336f2b3f9 21 static void addHexNibble(bool* pAdded, int number, int index, char** pp)
andrewboyson 49:1a6336f2b3f9 22 {
andrewboyson 49:1a6336f2b3f9 23 int nibble = number;
andrewboyson 49:1a6336f2b3f9 24 if (index) nibble >>= 4;
andrewboyson 49:1a6336f2b3f9 25 nibble &= 0xF;
andrewboyson 49:1a6336f2b3f9 26
andrewboyson 49:1a6336f2b3f9 27 if (nibble || *pAdded)
andrewboyson 49:1a6336f2b3f9 28 {
andrewboyson 49:1a6336f2b3f9 29 **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a';
andrewboyson 49:1a6336f2b3f9 30 *pp += 1;
andrewboyson 49:1a6336f2b3f9 31 *pAdded = true;
andrewboyson 49:1a6336f2b3f9 32 }
andrewboyson 49:1a6336f2b3f9 33 }
andrewboyson 172:9bc3c7b2cca1 34 int Ip6AddrToString(const char* pIp, int size, char* pText)
andrewboyson 49:1a6336f2b3f9 35 {
andrewboyson 143:8cec8f08dc54 36 const char* pIpE = pIp + 16;
andrewboyson 49:1a6336f2b3f9 37 char* p = pText;
andrewboyson 49:1a6336f2b3f9 38 while (true)
andrewboyson 49:1a6336f2b3f9 39 {
andrewboyson 49:1a6336f2b3f9 40 bool added = false;
andrewboyson 49:1a6336f2b3f9 41 if (*pIp || *(pIp + 1))
andrewboyson 49:1a6336f2b3f9 42 {
andrewboyson 49:1a6336f2b3f9 43 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 1, &p);
andrewboyson 49:1a6336f2b3f9 44 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 0, &p);
andrewboyson 49:1a6336f2b3f9 45 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 1, &p);
andrewboyson 49:1a6336f2b3f9 46 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 0, &p);
andrewboyson 49:1a6336f2b3f9 47 }
andrewboyson 49:1a6336f2b3f9 48
andrewboyson 49:1a6336f2b3f9 49 pIp += 2;
andrewboyson 49:1a6336f2b3f9 50 if (pIp >= pIpE) break;
andrewboyson 49:1a6336f2b3f9 51
andrewboyson 49:1a6336f2b3f9 52 if (p > pText + size - 2) break; *p++ = ':';
andrewboyson 49:1a6336f2b3f9 53 }
andrewboyson 49:1a6336f2b3f9 54 *p = 0;
andrewboyson 49:1a6336f2b3f9 55 return p - pText;
andrewboyson 49:1a6336f2b3f9 56 }
andrewboyson 193:47a953ab571b 57 void Ip6AddrParse(const char *pText, char *address) //Contains an empty address if invalid
andrewboyson 193:47a953ab571b 58 {
andrewboyson 193:47a953ab571b 59 int field = 0;
andrewboyson 193:47a953ab571b 60 int word = 0;
andrewboyson 193:47a953ab571b 61 while(true)
andrewboyson 193:47a953ab571b 62 {
andrewboyson 193:47a953ab571b 63 switch (*pText)
andrewboyson 193:47a953ab571b 64 {
andrewboyson 193:47a953ab571b 65 case ':':
andrewboyson 193:47a953ab571b 66 address[field] = (word >> 8) & 0xFF;
andrewboyson 193:47a953ab571b 67 field++;
andrewboyson 193:47a953ab571b 68 if (field > 15) { address[0] = 0; return; }
andrewboyson 193:47a953ab571b 69 address[field] = word & 0xFF;
andrewboyson 193:47a953ab571b 70 field++;
andrewboyson 193:47a953ab571b 71 if (field > 15) { address[0] = 0; return; }
andrewboyson 193:47a953ab571b 72 word = 0;
andrewboyson 193:47a953ab571b 73 break;
andrewboyson 193:47a953ab571b 74 case '0': word <<= 4; word |= 0; break;
andrewboyson 193:47a953ab571b 75 case '1': word <<= 4; word |= 1; break;
andrewboyson 193:47a953ab571b 76 case '2': word <<= 4; word |= 2; break;
andrewboyson 193:47a953ab571b 77 case '3': word <<= 4; word |= 3; break;
andrewboyson 193:47a953ab571b 78 case '4': word <<= 4; word |= 4; break;
andrewboyson 193:47a953ab571b 79 case '5': word <<= 4; word |= 5; break;
andrewboyson 193:47a953ab571b 80 case '6': word <<= 4; word |= 6; break;
andrewboyson 193:47a953ab571b 81 case '7': word <<= 4; word |= 7; break;
andrewboyson 193:47a953ab571b 82 case '8': word <<= 4; word |= 8; break;
andrewboyson 193:47a953ab571b 83 case '9': word <<= 4; word |= 9; break;
andrewboyson 193:47a953ab571b 84 case 'a':
andrewboyson 193:47a953ab571b 85 case 'A': word <<= 4; word |= 10; break;
andrewboyson 193:47a953ab571b 86 case 'b':
andrewboyson 193:47a953ab571b 87 case 'B': word <<= 4; word |= 11; break;
andrewboyson 193:47a953ab571b 88 case 'c':
andrewboyson 193:47a953ab571b 89 case 'C': word <<= 4; word |= 12; break;
andrewboyson 193:47a953ab571b 90 case 'd':
andrewboyson 193:47a953ab571b 91 case 'D': word <<= 4; word |= 13; break;
andrewboyson 193:47a953ab571b 92 case 'e':
andrewboyson 193:47a953ab571b 93 case 'E': word <<= 4; word |= 14; break;
andrewboyson 193:47a953ab571b 94 case 'f':
andrewboyson 193:47a953ab571b 95 case 'F': word <<= 4; word |= 15; break;
andrewboyson 193:47a953ab571b 96 case 0:
andrewboyson 193:47a953ab571b 97 address[field] = (word >> 8) & 0xFF;
andrewboyson 193:47a953ab571b 98 field++;
andrewboyson 193:47a953ab571b 99 if (field != 15) { address[0] = 0; return; }
andrewboyson 193:47a953ab571b 100 address[field] = word & 0xFF;
andrewboyson 193:47a953ab571b 101 return;
andrewboyson 193:47a953ab571b 102 default:
andrewboyson 193:47a953ab571b 103 address[0] = 0;
andrewboyson 193:47a953ab571b 104 return;
andrewboyson 193:47a953ab571b 105 }
andrewboyson 193:47a953ab571b 106 pText++;
andrewboyson 193:47a953ab571b 107 }
andrewboyson 193:47a953ab571b 108 }
andrewboyson 49:1a6336f2b3f9 109 static void logHexNibble(bool* pAdded, int number, int index)
andrewboyson 49:1a6336f2b3f9 110 {
andrewboyson 49:1a6336f2b3f9 111 int nibble = number;
andrewboyson 49:1a6336f2b3f9 112 if (index) nibble >>= 4;
andrewboyson 49:1a6336f2b3f9 113 nibble &= 0xF;
andrewboyson 49:1a6336f2b3f9 114
andrewboyson 49:1a6336f2b3f9 115 if (nibble || *pAdded)
andrewboyson 49:1a6336f2b3f9 116 {
andrewboyson 121:bc048b65a630 117 LogChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a');
andrewboyson 49:1a6336f2b3f9 118 *pAdded = true;
andrewboyson 49:1a6336f2b3f9 119 }
andrewboyson 49:1a6336f2b3f9 120 }
andrewboyson 172:9bc3c7b2cca1 121 int Ip6AddrLog(const char* pIp)
andrewboyson 49:1a6336f2b3f9 122 {
andrewboyson 49:1a6336f2b3f9 123 int count = 0;
andrewboyson 143:8cec8f08dc54 124 const char* pIpE = pIp + 16;
andrewboyson 49:1a6336f2b3f9 125 while (true)
andrewboyson 49:1a6336f2b3f9 126 {
andrewboyson 49:1a6336f2b3f9 127 bool added = false;
andrewboyson 49:1a6336f2b3f9 128 if (*pIp || *(pIp + 1))
andrewboyson 49:1a6336f2b3f9 129 {
andrewboyson 49:1a6336f2b3f9 130 logHexNibble(&added, *(pIp + 0), 1); if (added) count++;
andrewboyson 49:1a6336f2b3f9 131 logHexNibble(&added, *(pIp + 0), 0); if (added) count++;
andrewboyson 49:1a6336f2b3f9 132 logHexNibble(&added, *(pIp + 1), 1); if (added) count++;
andrewboyson 49:1a6336f2b3f9 133 logHexNibble(&added, *(pIp + 1), 0); if (added) count++;
andrewboyson 49:1a6336f2b3f9 134 }
andrewboyson 49:1a6336f2b3f9 135
andrewboyson 49:1a6336f2b3f9 136 pIp += 2;
andrewboyson 49:1a6336f2b3f9 137 if (pIp >= pIpE) break;
andrewboyson 49:1a6336f2b3f9 138
andrewboyson 121:bc048b65a630 139 LogChar(':'); count++;
andrewboyson 49:1a6336f2b3f9 140 }
andrewboyson 49:1a6336f2b3f9 141 return count;
andrewboyson 49:1a6336f2b3f9 142 }
andrewboyson 49:1a6336f2b3f9 143 static void httpHexNibble(bool* pAdded, int number, int index)
andrewboyson 49:1a6336f2b3f9 144 {
andrewboyson 49:1a6336f2b3f9 145 int nibble = number;
andrewboyson 49:1a6336f2b3f9 146 if (index) nibble >>= 4;
andrewboyson 49:1a6336f2b3f9 147 nibble &= 0xF;
andrewboyson 49:1a6336f2b3f9 148
andrewboyson 49:1a6336f2b3f9 149 if (nibble || *pAdded)
andrewboyson 49:1a6336f2b3f9 150 {
andrewboyson 54:84ef2b29cf7e 151 HttpAddChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a');
andrewboyson 49:1a6336f2b3f9 152 *pAdded = true;
andrewboyson 49:1a6336f2b3f9 153 }
andrewboyson 49:1a6336f2b3f9 154 }
andrewboyson 172:9bc3c7b2cca1 155 int Ip6AddrHttp(const char* pIp)
andrewboyson 49:1a6336f2b3f9 156 {
andrewboyson 49:1a6336f2b3f9 157 int count = 0;
andrewboyson 143:8cec8f08dc54 158 const char* pIpE = pIp + 16;
andrewboyson 49:1a6336f2b3f9 159 while (true)
andrewboyson 49:1a6336f2b3f9 160 {
andrewboyson 49:1a6336f2b3f9 161 bool added = false;
andrewboyson 49:1a6336f2b3f9 162 if (*pIp || *(pIp + 1))
andrewboyson 49:1a6336f2b3f9 163 {
andrewboyson 49:1a6336f2b3f9 164 httpHexNibble(&added, *(pIp + 0), 1); if (added) count++;
andrewboyson 49:1a6336f2b3f9 165 httpHexNibble(&added, *(pIp + 0), 0); if (added) count++;
andrewboyson 49:1a6336f2b3f9 166 httpHexNibble(&added, *(pIp + 1), 1); if (added) count++;
andrewboyson 49:1a6336f2b3f9 167 httpHexNibble(&added, *(pIp + 1), 0); if (added) count++;
andrewboyson 49:1a6336f2b3f9 168 }
andrewboyson 49:1a6336f2b3f9 169
andrewboyson 49:1a6336f2b3f9 170 pIp += 2;
andrewboyson 49:1a6336f2b3f9 171 if (pIp >= pIpE) break;
andrewboyson 49:1a6336f2b3f9 172
andrewboyson 54:84ef2b29cf7e 173 HttpAddChar(':'); count++;
andrewboyson 49:1a6336f2b3f9 174 }
andrewboyson 49:1a6336f2b3f9 175 return count;
andrewboyson 49:1a6336f2b3f9 176 }
andrewboyson 172:9bc3c7b2cca1 177 bool Ip6AddrIsSame(const char* ipA, const char* ipB)
andrewboyson 49:1a6336f2b3f9 178 {
andrewboyson 49:1a6336f2b3f9 179 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 180 }
andrewboyson 172:9bc3c7b2cca1 181 void Ip6AddrCopy(char* ipTo, const char* ipFrom)
andrewboyson 49:1a6336f2b3f9 182 {
andrewboyson 49:1a6336f2b3f9 183 memcpy(ipTo, ipFrom, 16);
andrewboyson 49:1a6336f2b3f9 184 }
andrewboyson 49:1a6336f2b3f9 185
andrewboyson 172:9bc3c7b2cca1 186 bool Ip6AddrIsLinkLocal(const char* p)
andrewboyson 172:9bc3c7b2cca1 187 {
andrewboyson 172:9bc3c7b2cca1 188 if (p[0] != 0xFE) return false;
andrewboyson 172:9bc3c7b2cca1 189 if (p[1] != 0x80) return false;
andrewboyson 172:9bc3c7b2cca1 190 return true;
andrewboyson 172:9bc3c7b2cca1 191 }
andrewboyson 172:9bc3c7b2cca1 192 bool Ip6AddrIsUniqueLocal(const char* p)
andrewboyson 172:9bc3c7b2cca1 193 {
andrewboyson 172:9bc3c7b2cca1 194 if (p[0] != 0xFD) return false;
andrewboyson 172:9bc3c7b2cca1 195 if (p[1] != 0x00) return false;
andrewboyson 172:9bc3c7b2cca1 196 return true;
andrewboyson 172:9bc3c7b2cca1 197 }
andrewboyson 172:9bc3c7b2cca1 198 bool Ip6AddrIsGlobal(const char* p)
andrewboyson 172:9bc3c7b2cca1 199 {
andrewboyson 172:9bc3c7b2cca1 200 //[RFC 4291] designates 2000::/3 to be global unicast address space that the Internet Assigned Numbers Authority (IANA) may allocate to the RIRs.
andrewboyson 172:9bc3c7b2cca1 201 //The top byte AND 0b11100000 (0xE0)must be 0x20
andrewboyson 172:9bc3c7b2cca1 202 return (p[0] & 0xE0) == 0x20;
andrewboyson 172:9bc3c7b2cca1 203 }
andrewboyson 187:122fc1996c86 204 bool Ip6AddrIsExternal(const char* p)
andrewboyson 187:122fc1996c86 205 {
andrewboyson 187:122fc1996c86 206 //Logic is address must be global and not have the global prefix
andrewboyson 187:122fc1996c86 207 if (!Ip6AddrIsGlobal(p)) return false;
andrewboyson 187:122fc1996c86 208 if (!NdpGlobalPrefixLength) return false;
andrewboyson 187:122fc1996c86 209 if (memcmp(NdpGlobalPrefix, p, NdpGlobalPrefixLength) != 0) return false; //Only 0 if the same
andrewboyson 187:122fc1996c86 210 return true;
andrewboyson 187:122fc1996c86 211
andrewboyson 187:122fc1996c86 212 }
andrewboyson 143:8cec8f08dc54 213 bool Ip6AddrIsSolicited(const char* p)
andrewboyson 136:8a65abb0dc63 214 {
andrewboyson 136:8a65abb0dc63 215 if (*p++ != 0xff) return false;
andrewboyson 136:8a65abb0dc63 216 if (*p++ != 0x02) return false;
andrewboyson 136:8a65abb0dc63 217
andrewboyson 136:8a65abb0dc63 218 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 219 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 220
andrewboyson 136:8a65abb0dc63 221 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 222 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 223
andrewboyson 136:8a65abb0dc63 224 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 225 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 226
andrewboyson 136:8a65abb0dc63 227 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 228 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 229
andrewboyson 136:8a65abb0dc63 230 if (*p++ != 0x00) return false;
andrewboyson 136:8a65abb0dc63 231 if (*p++ != 0x01) return false;
andrewboyson 136:8a65abb0dc63 232
andrewboyson 136:8a65abb0dc63 233 if (*p++ != 0xff) return false;
andrewboyson 136:8a65abb0dc63 234
andrewboyson 136:8a65abb0dc63 235 return true;
andrewboyson 136:8a65abb0dc63 236 }
andrewboyson 143:8cec8f08dc54 237 bool Ip6AddrIsMulticast(const char *p)
andrewboyson 136:8a65abb0dc63 238 {
andrewboyson 136:8a65abb0dc63 239 return *p == 0xFF;
andrewboyson 136:8a65abb0dc63 240 }
andrewboyson 143:8cec8f08dc54 241 bool Ip6AddrIsSameGroup(const char* pA, const char* pB)
andrewboyson 136:8a65abb0dc63 242 {
andrewboyson 136:8a65abb0dc63 243 pA += 13;
andrewboyson 136:8a65abb0dc63 244 pB += 13;
andrewboyson 136:8a65abb0dc63 245 if (*pA++ != *pB++) return false;
andrewboyson 136:8a65abb0dc63 246 if (*pA++ != *pB++) return false;
andrewboyson 136:8a65abb0dc63 247 return *pA == *pB;
andrewboyson 136:8a65abb0dc63 248 }
andrewboyson 136:8a65abb0dc63 249
andrewboyson 172:9bc3c7b2cca1 250 const char Ip6AddrAllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
andrewboyson 172:9bc3c7b2cca1 251 const char Ip6AddrAllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
andrewboyson 172:9bc3c7b2cca1 252 const char Ip6AddrMdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb};
andrewboyson 172:9bc3c7b2cca1 253 const char Ip6AddrLlmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03};
andrewboyson 172:9bc3c7b2cca1 254 const char Ip6AddrNtp [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
andrewboyson 49:1a6336f2b3f9 255
andrewboyson 172:9bc3c7b2cca1 256 void Ip6AddrFromDest(int dest, char* pDstIp)
andrewboyson 49:1a6336f2b3f9 257 {
andrewboyson 49:1a6336f2b3f9 258 switch (dest)
andrewboyson 49:1a6336f2b3f9 259 {
andrewboyson 171:f708d6776752 260 case UNICAST: /*No change*/ break;
andrewboyson 172:9bc3c7b2cca1 261 case UNICAST_DNS: Ip6AddrCopy(pDstIp, NdpDnsServer ); break;
andrewboyson 172:9bc3c7b2cca1 262 case UNICAST_NTP: Ip6AddrCopy(pDstIp, NtpClientQueryServerIp6); break;
andrewboyson 172:9bc3c7b2cca1 263 case UNICAST_TFTP: Ip6AddrCopy(pDstIp, TftpServerIp6 ); break;
andrewboyson 172:9bc3c7b2cca1 264 case MULTICAST_NODE: Ip6AddrCopy(pDstIp, Ip6AddrAllNodes ); break;
andrewboyson 172:9bc3c7b2cca1 265 case MULTICAST_ROUTER: Ip6AddrCopy(pDstIp, Ip6AddrAllRouters ); break;
andrewboyson 172:9bc3c7b2cca1 266 case MULTICAST_MDNS: Ip6AddrCopy(pDstIp, Ip6AddrMdns ); break;
andrewboyson 172:9bc3c7b2cca1 267 case MULTICAST_LLMNR: Ip6AddrCopy(pDstIp, Ip6AddrLlmnr ); break;
andrewboyson 172:9bc3c7b2cca1 268 case MULTICAST_NTP: Ip6AddrCopy(pDstIp, Ip6AddrNtp ); break;
andrewboyson 49:1a6336f2b3f9 269 default:
andrewboyson 52:fbc5a46b5e16 270 LogTimeF("Ip6AddressFromDest unknown destination %d\r\n", dest);
andrewboyson 49:1a6336f2b3f9 271 break;
andrewboyson 49:1a6336f2b3f9 272 }
andrewboyson 49:1a6336f2b3f9 273 }