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
ip6addr.c
00001 #include <stdbool.h> 00002 #include <string.h> 00003 00004 #include "log.h" 00005 #include "ip6addr.h" 00006 #include "http.h" 00007 #include "action.h" 00008 #include "ndp.h" 00009 #include "ntpclient.h" 00010 #include "slaac.h" 00011 #include "tftp.h" 00012 00013 void Ip6AddrClear(char* ip) 00014 { 00015 ip[ 0] = 0; //Just set the first byte to zero 00016 } 00017 bool Ip6AddrIsEmpty(const char* ip) 00018 { 00019 return !ip[0]; //Check for the first byte being non zero 00020 } 00021 static void addHexNibble(bool* pAdded, int number, int index, char** pp) 00022 { 00023 int nibble = number; 00024 if (index) nibble >>= 4; 00025 nibble &= 0xF; 00026 00027 if (nibble || *pAdded) 00028 { 00029 **pp = nibble < 10 ? nibble + '0' : nibble - 10 + 'a'; 00030 *pp += 1; 00031 *pAdded = true; 00032 } 00033 } 00034 int Ip6AddrToString(const char* pIp, int size, char* pText) 00035 { 00036 const char* pIpE = pIp + 16; 00037 char* p = pText; 00038 while (true) 00039 { 00040 bool added = false; 00041 if (*pIp || *(pIp + 1)) 00042 { 00043 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 1, &p); 00044 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 0), 0, &p); 00045 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 1, &p); 00046 if (p > pText + size - 2) break; addHexNibble(&added, *(pIp + 1), 0, &p); 00047 } 00048 00049 pIp += 2; 00050 if (pIp >= pIpE) break; 00051 00052 if (p > pText + size - 2) break; *p++ = ':'; 00053 } 00054 *p = 0; 00055 return p - pText; 00056 } 00057 void Ip6AddrParse(const char *pText, char *address) //Contains an empty address if invalid 00058 { 00059 int field = 0; 00060 int word = 0; 00061 while(true) 00062 { 00063 switch (*pText) 00064 { 00065 case ':': 00066 address[field] = (word >> 8) & 0xFF; 00067 field++; 00068 if (field > 15) { address[0] = 0; return; } 00069 address[field] = word & 0xFF; 00070 field++; 00071 if (field > 15) { address[0] = 0; return; } 00072 word = 0; 00073 break; 00074 case '0': word <<= 4; word |= 0; break; 00075 case '1': word <<= 4; word |= 1; break; 00076 case '2': word <<= 4; word |= 2; break; 00077 case '3': word <<= 4; word |= 3; break; 00078 case '4': word <<= 4; word |= 4; break; 00079 case '5': word <<= 4; word |= 5; break; 00080 case '6': word <<= 4; word |= 6; break; 00081 case '7': word <<= 4; word |= 7; break; 00082 case '8': word <<= 4; word |= 8; break; 00083 case '9': word <<= 4; word |= 9; break; 00084 case 'a': 00085 case 'A': word <<= 4; word |= 10; break; 00086 case 'b': 00087 case 'B': word <<= 4; word |= 11; break; 00088 case 'c': 00089 case 'C': word <<= 4; word |= 12; break; 00090 case 'd': 00091 case 'D': word <<= 4; word |= 13; break; 00092 case 'e': 00093 case 'E': word <<= 4; word |= 14; break; 00094 case 'f': 00095 case 'F': word <<= 4; word |= 15; break; 00096 case 0: 00097 address[field] = (word >> 8) & 0xFF; 00098 field++; 00099 if (field != 15) { address[0] = 0; return; } 00100 address[field] = word & 0xFF; 00101 return; 00102 default: 00103 address[0] = 0; 00104 return; 00105 } 00106 pText++; 00107 } 00108 } 00109 static void logHexNibble(bool* pAdded, int number, int index) 00110 { 00111 int nibble = number; 00112 if (index) nibble >>= 4; 00113 nibble &= 0xF; 00114 00115 if (nibble || *pAdded) 00116 { 00117 LogChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a'); 00118 *pAdded = true; 00119 } 00120 } 00121 int Ip6AddrLog(const char* pIp) 00122 { 00123 int count = 0; 00124 const char* pIpE = pIp + 16; 00125 while (true) 00126 { 00127 bool added = false; 00128 if (*pIp || *(pIp + 1)) 00129 { 00130 logHexNibble(&added, *(pIp + 0), 1); if (added) count++; 00131 logHexNibble(&added, *(pIp + 0), 0); if (added) count++; 00132 logHexNibble(&added, *(pIp + 1), 1); if (added) count++; 00133 logHexNibble(&added, *(pIp + 1), 0); if (added) count++; 00134 } 00135 00136 pIp += 2; 00137 if (pIp >= pIpE) break; 00138 00139 LogChar(':'); count++; 00140 } 00141 return count; 00142 } 00143 static void httpHexNibble(bool* pAdded, int number, int index) 00144 { 00145 int nibble = number; 00146 if (index) nibble >>= 4; 00147 nibble &= 0xF; 00148 00149 if (nibble || *pAdded) 00150 { 00151 HttpAddChar(nibble < 10 ? nibble + '0' : nibble - 10 + 'a'); 00152 *pAdded = true; 00153 } 00154 } 00155 int Ip6AddrHttp(const char* pIp) 00156 { 00157 int count = 0; 00158 const char* pIpE = pIp + 16; 00159 while (true) 00160 { 00161 bool added = false; 00162 if (*pIp || *(pIp + 1)) 00163 { 00164 httpHexNibble(&added, *(pIp + 0), 1); if (added) count++; 00165 httpHexNibble(&added, *(pIp + 0), 0); if (added) count++; 00166 httpHexNibble(&added, *(pIp + 1), 1); if (added) count++; 00167 httpHexNibble(&added, *(pIp + 1), 0); if (added) count++; 00168 } 00169 00170 pIp += 2; 00171 if (pIp >= pIpE) break; 00172 00173 HttpAddChar(':'); count++; 00174 } 00175 return count; 00176 } 00177 bool Ip6AddrIsSame(const char* ipA, const char* ipB) 00178 { 00179 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 00180 } 00181 void Ip6AddrCopy(char* ipTo, const char* ipFrom) 00182 { 00183 memcpy(ipTo, ipFrom, 16); 00184 } 00185 00186 bool Ip6AddrIsLinkLocal(const char* p) 00187 { 00188 if (p[0] != 0xFE) return false; 00189 if (p[1] != 0x80) return false; 00190 return true; 00191 } 00192 bool Ip6AddrIsUniqueLocal(const char* p) 00193 { 00194 if (p[0] != 0xFD) return false; 00195 if (p[1] != 0x00) return false; 00196 return true; 00197 } 00198 bool Ip6AddrIsGlobal(const char* p) 00199 { 00200 //[RFC 4291] designates 2000::/3 to be global unicast address space that the Internet Assigned Numbers Authority (IANA) may allocate to the RIRs. 00201 //The top byte AND 0b11100000 (0xE0)must be 0x20 00202 return (p[0] & 0xE0) == 0x20; 00203 } 00204 bool Ip6AddrIsExternal(const char* p) 00205 { 00206 //Logic is address must be global and not have the global prefix 00207 if (!Ip6AddrIsGlobal(p)) return false; 00208 if (!NdpGlobalPrefixLength) return false; 00209 if (memcmp(NdpGlobalPrefix, p, NdpGlobalPrefixLength) != 0) return false; //Only 0 if the same 00210 return true; 00211 00212 } 00213 bool Ip6AddrIsSolicited(const char* p) 00214 { 00215 if (*p++ != 0xff) return false; 00216 if (*p++ != 0x02) return false; 00217 00218 if (*p++ != 0x00) return false; 00219 if (*p++ != 0x00) return false; 00220 00221 if (*p++ != 0x00) return false; 00222 if (*p++ != 0x00) return false; 00223 00224 if (*p++ != 0x00) return false; 00225 if (*p++ != 0x00) return false; 00226 00227 if (*p++ != 0x00) return false; 00228 if (*p++ != 0x00) return false; 00229 00230 if (*p++ != 0x00) return false; 00231 if (*p++ != 0x01) return false; 00232 00233 if (*p++ != 0xff) return false; 00234 00235 return true; 00236 } 00237 bool Ip6AddrIsMulticast(const char *p) 00238 { 00239 return *p == 0xFF; 00240 } 00241 bool Ip6AddrIsSameGroup(const char* pA, const char* pB) 00242 { 00243 pA += 13; 00244 pB += 13; 00245 if (*pA++ != *pB++) return false; 00246 if (*pA++ != *pB++) return false; 00247 return *pA == *pB; 00248 } 00249 00250 const char Ip6AddrAllNodes [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; 00251 const char Ip6AddrAllRouters[] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}; 00252 const char Ip6AddrMdns [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}; 00253 const char Ip6AddrLlmnr [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03}; 00254 const char Ip6AddrNtp [] = {0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}; 00255 00256 void Ip6AddrFromDest(int dest, char* pDstIp) 00257 { 00258 switch (dest) 00259 { 00260 case UNICAST: /*No change*/ break; 00261 case UNICAST_DNS: Ip6AddrCopy(pDstIp, NdpDnsServer ); break; 00262 case UNICAST_NTP: Ip6AddrCopy(pDstIp, NtpClientQueryServerIp6); break; 00263 case UNICAST_TFTP: Ip6AddrCopy(pDstIp, TftpServerIp6 ); break; 00264 case MULTICAST_NODE: Ip6AddrCopy(pDstIp, Ip6AddrAllNodes ); break; 00265 case MULTICAST_ROUTER: Ip6AddrCopy(pDstIp, Ip6AddrAllRouters ); break; 00266 case MULTICAST_MDNS: Ip6AddrCopy(pDstIp, Ip6AddrMdns ); break; 00267 case MULTICAST_LLMNR: Ip6AddrCopy(pDstIp, Ip6AddrLlmnr ); break; 00268 case MULTICAST_NTP: Ip6AddrCopy(pDstIp, Ip6AddrNtp ); break; 00269 default: 00270 LogTimeF("Ip6AddressFromDest unknown destination %d\r\n", dest); 00271 break; 00272 } 00273 }
Generated on Tue Jul 12 2022 18:53:40 by 1.7.2