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 Aug 17 14:21:02 2017 +0000
Revision:
32:679654f2d023
Parent:
23:b641979389b2
Child:
36:900e24b27bfb
Corrected issues with .local in llmnr and mdns

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 13:9cd54f7db57a 1 #include "mbed.h"
andrewboyson 13:9cd54f7db57a 2 #include "dnshdr.h"
andrewboyson 13:9cd54f7db57a 3 #include "ctype.h"
andrewboyson 13:9cd54f7db57a 4 #include "log.h"
andrewboyson 13:9cd54f7db57a 5
andrewboyson 22:914b970356f0 6 #define DEBUG false
andrewboyson 22:914b970356f0 7
andrewboyson 13:9cd54f7db57a 8 #define MAX_PACKET_SIZE 512
andrewboyson 13:9cd54f7db57a 9 #define MAX_DEPTH 10
andrewboyson 13:9cd54f7db57a 10
andrewboyson 13:9cd54f7db57a 11 static bool isOffset(char c) { return (c & 0xC0) == 0xC0; }
andrewboyson 13:9cd54f7db57a 12 static char* derefOffset(char* p)
andrewboyson 13:9cd54f7db57a 13 {
andrewboyson 13:9cd54f7db57a 14 int offset = (*p & 0x3F) << 8; //Any bits in the upper byte are added
andrewboyson 13:9cd54f7db57a 15 p++; //Move to the lower byte
andrewboyson 13:9cd54f7db57a 16 offset |= *p; //And add it
andrewboyson 13:9cd54f7db57a 17 return DnsHdrPacket + offset; //Return a pointer
andrewboyson 13:9cd54f7db57a 18 }
andrewboyson 13:9cd54f7db57a 19
andrewboyson 13:9cd54f7db57a 20 int DnsNameLength(char* pStart) //Returns 0 on error
andrewboyson 13:9cd54f7db57a 21 {
andrewboyson 13:9cd54f7db57a 22 char* p = pStart;
andrewboyson 13:9cd54f7db57a 23
andrewboyson 13:9cd54f7db57a 24 while (true)
andrewboyson 13:9cd54f7db57a 25 {
andrewboyson 13:9cd54f7db57a 26 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 13:9cd54f7db57a 27 {
andrewboyson 22:914b970356f0 28 if (DEBUG) LogTimeF("DnsNameLength strayed out of the packet\r\n");
andrewboyson 13:9cd54f7db57a 29 return 0;
andrewboyson 13:9cd54f7db57a 30 }
andrewboyson 13:9cd54f7db57a 31
andrewboyson 13:9cd54f7db57a 32 int length = *p++;
andrewboyson 13:9cd54f7db57a 33 if (length == 0) //Its the last field so finish
andrewboyson 13:9cd54f7db57a 34 {
andrewboyson 13:9cd54f7db57a 35 return p - pStart;
andrewboyson 13:9cd54f7db57a 36 }
andrewboyson 13:9cd54f7db57a 37 else if (isOffset(length)) //it's a pointer so skip the length byte and return
andrewboyson 13:9cd54f7db57a 38 {
andrewboyson 13:9cd54f7db57a 39 p++;
andrewboyson 13:9cd54f7db57a 40 return p - pStart;
andrewboyson 13:9cd54f7db57a 41 }
andrewboyson 13:9cd54f7db57a 42 else //it's a length plus a field eg 3www
andrewboyson 13:9cd54f7db57a 43 {
andrewboyson 13:9cd54f7db57a 44 p += length;
andrewboyson 13:9cd54f7db57a 45 }
andrewboyson 13:9cd54f7db57a 46 }
andrewboyson 13:9cd54f7db57a 47 }
andrewboyson 13:9cd54f7db57a 48
andrewboyson 13:9cd54f7db57a 49 int DnsNameIndexFromPointer(char* p)
andrewboyson 13:9cd54f7db57a 50 {
andrewboyson 13:9cd54f7db57a 51 int depth = 0;
andrewboyson 13:9cd54f7db57a 52 while (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 13:9cd54f7db57a 53 {
andrewboyson 13:9cd54f7db57a 54 depth++;
andrewboyson 13:9cd54f7db57a 55 if (depth > MAX_DEPTH)
andrewboyson 13:9cd54f7db57a 56 {
andrewboyson 22:914b970356f0 57 if (DEBUG) LogTimeF("DnsNameIndexFromPointer exceeded depth limit\r\n");
andrewboyson 13:9cd54f7db57a 58 return -1;
andrewboyson 13:9cd54f7db57a 59 }
andrewboyson 13:9cd54f7db57a 60 p = derefOffset(p);
andrewboyson 13:9cd54f7db57a 61 }
andrewboyson 13:9cd54f7db57a 62 return p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 63 }
andrewboyson 13:9cd54f7db57a 64
andrewboyson 32:679654f2d023 65 bool DnsNameCompare(char* pStart, char* pTarget)
andrewboyson 32:679654f2d023 66 {
andrewboyson 32:679654f2d023 67 char* p = pStart;
andrewboyson 32:679654f2d023 68
andrewboyson 32:679654f2d023 69 int depth = 0;
andrewboyson 32:679654f2d023 70
andrewboyson 32:679654f2d023 71 while (true)
andrewboyson 32:679654f2d023 72 {
andrewboyson 32:679654f2d023 73 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 32:679654f2d023 74 {
andrewboyson 32:679654f2d023 75 if (DEBUG) LogTimeF("DnsNameCompare strayed out of the packet\r\n");
andrewboyson 32:679654f2d023 76 return false;
andrewboyson 32:679654f2d023 77 }
andrewboyson 32:679654f2d023 78
andrewboyson 32:679654f2d023 79 int length = *p;
andrewboyson 32:679654f2d023 80 if (length == 0) //Its the last field so should be on the target's terminating NUL
andrewboyson 32:679654f2d023 81 {
andrewboyson 32:679654f2d023 82 if (*pTarget) return false;
andrewboyson 32:679654f2d023 83 return true;
andrewboyson 32:679654f2d023 84 }
andrewboyson 32:679654f2d023 85 else if (isOffset(length)) //it's a pointer so go up one
andrewboyson 32:679654f2d023 86 {
andrewboyson 32:679654f2d023 87 depth++;
andrewboyson 32:679654f2d023 88 if (depth > MAX_DEPTH)
andrewboyson 32:679654f2d023 89 {
andrewboyson 32:679654f2d023 90 if (DEBUG) LogTimeF("DnsNameCompare exceeded depth limit\r\n");
andrewboyson 32:679654f2d023 91 return false;
andrewboyson 32:679654f2d023 92 }
andrewboyson 32:679654f2d023 93 p = derefOffset(p);
andrewboyson 32:679654f2d023 94 }
andrewboyson 32:679654f2d023 95 else //it's a length plus a field eg 3www
andrewboyson 32:679654f2d023 96 {
andrewboyson 32:679654f2d023 97 if (p > pStart) if (*pTarget++ != '.') return false;
andrewboyson 32:679654f2d023 98 p++;
andrewboyson 32:679654f2d023 99 for (int i = 0; i < length; i++)
andrewboyson 32:679654f2d023 100 {
andrewboyson 32:679654f2d023 101 if (toupper(*pTarget++) != toupper(*p++)) return false;
andrewboyson 32:679654f2d023 102 }
andrewboyson 32:679654f2d023 103 }
andrewboyson 32:679654f2d023 104 }
andrewboyson 32:679654f2d023 105 }
andrewboyson 32:679654f2d023 106 bool DnsNameCompareIp4(char *pStart, uint32_t ip)
andrewboyson 32:679654f2d023 107 {
andrewboyson 32:679654f2d023 108 int field = 0;
andrewboyson 32:679654f2d023 109 int depth = 0;
andrewboyson 32:679654f2d023 110 char* p = pStart;
andrewboyson 32:679654f2d023 111 while (true)
andrewboyson 32:679654f2d023 112 {
andrewboyson 32:679654f2d023 113 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 32:679654f2d023 114 {
andrewboyson 32:679654f2d023 115 LogTimeF("DnsNameCompareIp4 could not find name end\r\n");
andrewboyson 32:679654f2d023 116 return false;
andrewboyson 32:679654f2d023 117 }
andrewboyson 32:679654f2d023 118
andrewboyson 32:679654f2d023 119 int length = *p;
andrewboyson 32:679654f2d023 120 if (length == 0) //Its the last field so return the ip if it is the correct length
andrewboyson 32:679654f2d023 121 {
andrewboyson 32:679654f2d023 122 if (field != 6) return false;
andrewboyson 32:679654f2d023 123 return true;
andrewboyson 32:679654f2d023 124 }
andrewboyson 32:679654f2d023 125 else if (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 32:679654f2d023 126 {
andrewboyson 32:679654f2d023 127 depth++;
andrewboyson 32:679654f2d023 128 if (depth > MAX_DEPTH)
andrewboyson 32:679654f2d023 129 {
andrewboyson 32:679654f2d023 130 LogTimeF("DnsNameCompareIp4 exceeded depth limit\r\n");
andrewboyson 32:679654f2d023 131 return false;
andrewboyson 32:679654f2d023 132 }
andrewboyson 32:679654f2d023 133 p = derefOffset(p);
andrewboyson 32:679654f2d023 134 }
andrewboyson 32:679654f2d023 135 else //it's a length plus a field eg 3www
andrewboyson 32:679654f2d023 136 {
andrewboyson 32:679654f2d023 137 p++; // move past the length
andrewboyson 32:679654f2d023 138 if (field <= 3)
andrewboyson 32:679654f2d023 139 {
andrewboyson 32:679654f2d023 140 if (length > 3) return false; // expect 90.1.168.192.in-addr.arpa
andrewboyson 32:679654f2d023 141 int byte = 0;
andrewboyson 32:679654f2d023 142 for (int i = 0; i < length; i++)
andrewboyson 32:679654f2d023 143 {
andrewboyson 32:679654f2d023 144 byte = byte * 10;
andrewboyson 32:679654f2d023 145 if (*p > '9' || *p < '0') return false; // expect 90.1.168.192.in-addr.arpa
andrewboyson 32:679654f2d023 146 byte += *p - '0';
andrewboyson 32:679654f2d023 147 p++;
andrewboyson 32:679654f2d023 148 }
andrewboyson 32:679654f2d023 149 if (byte != ip & 0xFF) return false;
andrewboyson 32:679654f2d023 150 ip >>= 8;
andrewboyson 32:679654f2d023 151 }
andrewboyson 32:679654f2d023 152 else if (field == 4)
andrewboyson 32:679654f2d023 153 {
andrewboyson 32:679654f2d023 154 if (length != 7) return false; // expect 90.1.168.192.in-addr.arpa
andrewboyson 32:679654f2d023 155 p+= length;
andrewboyson 32:679654f2d023 156 }
andrewboyson 32:679654f2d023 157 else if (field == 5)
andrewboyson 32:679654f2d023 158 {
andrewboyson 32:679654f2d023 159 if (length != 4) return false; // expect 90.1.168.192.in-addr.arpa
andrewboyson 32:679654f2d023 160 p+= length;
andrewboyson 32:679654f2d023 161 }
andrewboyson 32:679654f2d023 162 else
andrewboyson 32:679654f2d023 163 {
andrewboyson 32:679654f2d023 164 return false; // expect 90.1.168.192.in-addr.arpa
andrewboyson 32:679654f2d023 165 }
andrewboyson 32:679654f2d023 166 field++;
andrewboyson 32:679654f2d023 167 }
andrewboyson 32:679654f2d023 168 }
andrewboyson 32:679654f2d023 169 }
andrewboyson 32:679654f2d023 170 bool DnsNameCompareIp6(char* pStart, char* pIp)
andrewboyson 32:679654f2d023 171 {
andrewboyson 32:679654f2d023 172 int field = 0;
andrewboyson 32:679654f2d023 173 int depth = 0;
andrewboyson 32:679654f2d023 174 char* p = pStart;
andrewboyson 32:679654f2d023 175 while (true)
andrewboyson 32:679654f2d023 176 {
andrewboyson 32:679654f2d023 177 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 32:679654f2d023 178 {
andrewboyson 32:679654f2d023 179 LogTimeF("DnsNameDecodeIp6 could not find name end\r\n");
andrewboyson 32:679654f2d023 180 return false;
andrewboyson 32:679654f2d023 181 }
andrewboyson 32:679654f2d023 182
andrewboyson 32:679654f2d023 183 int length = *p;
andrewboyson 32:679654f2d023 184 if (length == 0) //Its the last field so return the ip if it is the correct length
andrewboyson 32:679654f2d023 185 {
andrewboyson 32:679654f2d023 186 if (field != 34) return false;
andrewboyson 32:679654f2d023 187 return true;
andrewboyson 32:679654f2d023 188 }
andrewboyson 32:679654f2d023 189 else if (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 32:679654f2d023 190 {
andrewboyson 32:679654f2d023 191 depth++;
andrewboyson 32:679654f2d023 192 if (depth > MAX_DEPTH)
andrewboyson 32:679654f2d023 193 {
andrewboyson 32:679654f2d023 194 LogTimeF("DnsNameDecodeIp6 exceeded depth limit\r\n");
andrewboyson 32:679654f2d023 195 return false;
andrewboyson 32:679654f2d023 196 }
andrewboyson 32:679654f2d023 197 p = derefOffset(p);
andrewboyson 32:679654f2d023 198 }
andrewboyson 32:679654f2d023 199 else //it's a length plus a field eg 3www
andrewboyson 32:679654f2d023 200 {
andrewboyson 32:679654f2d023 201 p++; // move past the length
andrewboyson 32:679654f2d023 202 if (field <= 31)
andrewboyson 32:679654f2d023 203 {
andrewboyson 32:679654f2d023 204 if (length > 1) return false; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 205 int nibble = 0;
andrewboyson 32:679654f2d023 206 if (*p >= '0' && *p <= '9') nibble = *p - '0';
andrewboyson 32:679654f2d023 207 else if (*p >= 'a' && *p <= 'f') nibble = *p - 'a' + 10;
andrewboyson 32:679654f2d023 208 else if (*p >= 'A' && *p <= 'F') nibble = *p - 'A' + 10;
andrewboyson 32:679654f2d023 209 else return false; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 210 if ((field & 1) == 0)
andrewboyson 32:679654f2d023 211 {
andrewboyson 32:679654f2d023 212 if (pIp[15 - (field >> 1)] & 0x0F != nibble) return false;
andrewboyson 32:679654f2d023 213 }
andrewboyson 32:679654f2d023 214 else
andrewboyson 32:679654f2d023 215 {
andrewboyson 32:679654f2d023 216 nibble <<= 4;
andrewboyson 32:679654f2d023 217 if (pIp[15 - (field >> 1)] & 0xF0 != nibble) return false;
andrewboyson 32:679654f2d023 218 }
andrewboyson 32:679654f2d023 219 p += length;
andrewboyson 32:679654f2d023 220 }
andrewboyson 32:679654f2d023 221 else if (field == 32)
andrewboyson 32:679654f2d023 222 {
andrewboyson 32:679654f2d023 223 if (length != 3) return false; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 224 p+= length;
andrewboyson 32:679654f2d023 225 }
andrewboyson 32:679654f2d023 226 else if (field == 33)
andrewboyson 32:679654f2d023 227 {
andrewboyson 32:679654f2d023 228 if (length != 4) return false; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 229 p+= length;
andrewboyson 32:679654f2d023 230 }
andrewboyson 32:679654f2d023 231 else
andrewboyson 32:679654f2d023 232 {
andrewboyson 32:679654f2d023 233 return false; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 32:679654f2d023 234 }
andrewboyson 32:679654f2d023 235 field++;
andrewboyson 32:679654f2d023 236 }
andrewboyson 32:679654f2d023 237 }
andrewboyson 32:679654f2d023 238 }
andrewboyson 32:679654f2d023 239
andrewboyson 13:9cd54f7db57a 240 void DnsNameDecode(int offset, int lenName, char* pName)
andrewboyson 13:9cd54f7db57a 241 {
andrewboyson 13:9cd54f7db57a 242 bool nameStarted = false;
andrewboyson 13:9cd54f7db57a 243 int depth = 0;
andrewboyson 13:9cd54f7db57a 244 char* p = DnsHdrPacket + offset;
andrewboyson 13:9cd54f7db57a 245 while (true)
andrewboyson 13:9cd54f7db57a 246 {
andrewboyson 13:9cd54f7db57a 247 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 13:9cd54f7db57a 248 {
andrewboyson 13:9cd54f7db57a 249 *pName = 0;
andrewboyson 23:b641979389b2 250 if (DEBUG) LogTimeF("DnsNameDecode could not find name end\r\n");
andrewboyson 13:9cd54f7db57a 251 return;
andrewboyson 13:9cd54f7db57a 252 }
andrewboyson 13:9cd54f7db57a 253
andrewboyson 13:9cd54f7db57a 254 int length = *p;
andrewboyson 13:9cd54f7db57a 255 if (length == 0) //Its the last field so terminate the string
andrewboyson 13:9cd54f7db57a 256 {
andrewboyson 13:9cd54f7db57a 257 *pName = 0;
andrewboyson 13:9cd54f7db57a 258 return;
andrewboyson 13:9cd54f7db57a 259 }
andrewboyson 13:9cd54f7db57a 260 else if (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 13:9cd54f7db57a 261 {
andrewboyson 13:9cd54f7db57a 262 depth++;
andrewboyson 13:9cd54f7db57a 263 if (depth > MAX_DEPTH)
andrewboyson 13:9cd54f7db57a 264 {
andrewboyson 13:9cd54f7db57a 265 LogTimeF("DnsNameDecode exceeded depth limit\r\n");
andrewboyson 13:9cd54f7db57a 266 *pName = 0;
andrewboyson 13:9cd54f7db57a 267 return;
andrewboyson 13:9cd54f7db57a 268 }
andrewboyson 13:9cd54f7db57a 269 p = derefOffset(p);
andrewboyson 13:9cd54f7db57a 270 }
andrewboyson 13:9cd54f7db57a 271 else //it's a length plus a field eg 3www
andrewboyson 13:9cd54f7db57a 272 {
andrewboyson 13:9cd54f7db57a 273 if (pName)
andrewboyson 13:9cd54f7db57a 274 {
andrewboyson 13:9cd54f7db57a 275 if (length + 1 > lenName) //Leave room to terminate the string
andrewboyson 13:9cd54f7db57a 276 {
andrewboyson 13:9cd54f7db57a 277 *pName = 0;
andrewboyson 13:9cd54f7db57a 278 LogTimeF("DnsNameDecode overran name buffer\r\n");
andrewboyson 13:9cd54f7db57a 279 return;
andrewboyson 13:9cd54f7db57a 280 }
andrewboyson 13:9cd54f7db57a 281 lenName -= length + 1; //name chunk plus a '.'
andrewboyson 13:9cd54f7db57a 282 if (nameStarted) *pName++ = '.';
andrewboyson 13:9cd54f7db57a 283 p++;
andrewboyson 13:9cd54f7db57a 284 for (int i = 0; i < length; i++) *pName++ = *p++;
andrewboyson 13:9cd54f7db57a 285 nameStarted = true;
andrewboyson 13:9cd54f7db57a 286 }
andrewboyson 13:9cd54f7db57a 287 else
andrewboyson 13:9cd54f7db57a 288 {
andrewboyson 13:9cd54f7db57a 289 p += length + 1;
andrewboyson 13:9cd54f7db57a 290 }
andrewboyson 13:9cd54f7db57a 291 }
andrewboyson 13:9cd54f7db57a 292 }
andrewboyson 13:9cd54f7db57a 293 }
andrewboyson 13:9cd54f7db57a 294 void DnsNameDecodeIp4(int offset, uint32_t* pIp)
andrewboyson 13:9cd54f7db57a 295 {
andrewboyson 13:9cd54f7db57a 296 int field = 0;
andrewboyson 13:9cd54f7db57a 297 int depth = 0;
andrewboyson 13:9cd54f7db57a 298 char* p = DnsHdrPacket + offset;
andrewboyson 13:9cd54f7db57a 299 while (true)
andrewboyson 13:9cd54f7db57a 300 {
andrewboyson 13:9cd54f7db57a 301 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 13:9cd54f7db57a 302 {
andrewboyson 13:9cd54f7db57a 303 *pIp = 0;
andrewboyson 13:9cd54f7db57a 304 LogTimeF("DnsNameDecodeIp4 could not find name end\r\n");
andrewboyson 13:9cd54f7db57a 305 return;
andrewboyson 13:9cd54f7db57a 306 }
andrewboyson 13:9cd54f7db57a 307
andrewboyson 13:9cd54f7db57a 308 int length = *p;
andrewboyson 13:9cd54f7db57a 309 if (length == 0) //Its the last field so return the ip if it is the correct length
andrewboyson 13:9cd54f7db57a 310 {
andrewboyson 13:9cd54f7db57a 311 if (field != 6) *pIp = 0;
andrewboyson 13:9cd54f7db57a 312 return;
andrewboyson 13:9cd54f7db57a 313 }
andrewboyson 13:9cd54f7db57a 314 else if (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 13:9cd54f7db57a 315 {
andrewboyson 13:9cd54f7db57a 316 depth++;
andrewboyson 13:9cd54f7db57a 317 if (depth > MAX_DEPTH)
andrewboyson 13:9cd54f7db57a 318 {
andrewboyson 13:9cd54f7db57a 319 LogTimeF("DnsNameDecodeIp4 exceeded depth limit\r\n");
andrewboyson 13:9cd54f7db57a 320 *pIp = 0;
andrewboyson 13:9cd54f7db57a 321 return;
andrewboyson 13:9cd54f7db57a 322 }
andrewboyson 13:9cd54f7db57a 323 p = derefOffset(p);
andrewboyson 13:9cd54f7db57a 324 }
andrewboyson 13:9cd54f7db57a 325 else //it's a length plus a field eg 3www
andrewboyson 13:9cd54f7db57a 326 {
andrewboyson 13:9cd54f7db57a 327 p++; // move past the length
andrewboyson 13:9cd54f7db57a 328 if (field <= 3)
andrewboyson 13:9cd54f7db57a 329 {
andrewboyson 13:9cd54f7db57a 330 if (length > 3) {*pIp = 0; return; } // expect 90.1.168.192.in-addr.arpa
andrewboyson 13:9cd54f7db57a 331 int byte = 0;
andrewboyson 13:9cd54f7db57a 332 for (int i = 0; i < length; i++)
andrewboyson 13:9cd54f7db57a 333 {
andrewboyson 13:9cd54f7db57a 334 byte = byte * 10;
andrewboyson 13:9cd54f7db57a 335 if (*p > '9' || *p < '0') {*pIp = 0; return; } // expect 90.1.168.192.in-addr.arpa
andrewboyson 13:9cd54f7db57a 336 byte += *p - '0';
andrewboyson 13:9cd54f7db57a 337 p++;
andrewboyson 13:9cd54f7db57a 338 }
andrewboyson 13:9cd54f7db57a 339 *pIp <<= 8;
andrewboyson 13:9cd54f7db57a 340 *pIp |= byte;
andrewboyson 13:9cd54f7db57a 341 }
andrewboyson 13:9cd54f7db57a 342 else if (field == 4)
andrewboyson 13:9cd54f7db57a 343 {
andrewboyson 13:9cd54f7db57a 344 if (length != 7) {*pIp = 0; return; } // expect 90.1.168.192.in-addr.arpa
andrewboyson 13:9cd54f7db57a 345 p+= length;
andrewboyson 13:9cd54f7db57a 346 }
andrewboyson 13:9cd54f7db57a 347 else if (field == 5)
andrewboyson 13:9cd54f7db57a 348 {
andrewboyson 13:9cd54f7db57a 349 if (length != 4) {*pIp = 0; return; } // expect 90.1.168.192.in-addr.arpa
andrewboyson 13:9cd54f7db57a 350 p+= length;
andrewboyson 13:9cd54f7db57a 351 }
andrewboyson 13:9cd54f7db57a 352 else
andrewboyson 13:9cd54f7db57a 353 {
andrewboyson 13:9cd54f7db57a 354 *pIp = 0; return; // expect 90.1.168.192.in-addr.arpa
andrewboyson 13:9cd54f7db57a 355 }
andrewboyson 13:9cd54f7db57a 356 field++;
andrewboyson 13:9cd54f7db57a 357 }
andrewboyson 13:9cd54f7db57a 358 }
andrewboyson 13:9cd54f7db57a 359 }
andrewboyson 13:9cd54f7db57a 360 void DnsNameDecodeIp6(int offset, char* pIp)
andrewboyson 13:9cd54f7db57a 361 {
andrewboyson 13:9cd54f7db57a 362 int field = 0;
andrewboyson 13:9cd54f7db57a 363 int depth = 0;
andrewboyson 13:9cd54f7db57a 364 char* p = DnsHdrPacket + offset;
andrewboyson 13:9cd54f7db57a 365 while (true)
andrewboyson 13:9cd54f7db57a 366 {
andrewboyson 13:9cd54f7db57a 367 if (p > DnsHdrPacket + MAX_PACKET_SIZE)
andrewboyson 13:9cd54f7db57a 368 {
andrewboyson 13:9cd54f7db57a 369 pIp[0] = 0;
andrewboyson 13:9cd54f7db57a 370 LogTimeF("DnsNameDecodeIp6 could not find name end\r\n");
andrewboyson 13:9cd54f7db57a 371 return;
andrewboyson 13:9cd54f7db57a 372 }
andrewboyson 13:9cd54f7db57a 373
andrewboyson 13:9cd54f7db57a 374 int length = *p;
andrewboyson 13:9cd54f7db57a 375 if (length == 0) //Its the last field so return the ip if it is the correct length
andrewboyson 13:9cd54f7db57a 376 {
andrewboyson 13:9cd54f7db57a 377 if (field != 34) pIp[0] = 0;
andrewboyson 13:9cd54f7db57a 378 return;
andrewboyson 13:9cd54f7db57a 379 }
andrewboyson 13:9cd54f7db57a 380 else if (isOffset(*p)) //it's a pointer so jump to the new offset eg ^C0 ^0C
andrewboyson 13:9cd54f7db57a 381 {
andrewboyson 13:9cd54f7db57a 382 depth++;
andrewboyson 13:9cd54f7db57a 383 if (depth > MAX_DEPTH)
andrewboyson 13:9cd54f7db57a 384 {
andrewboyson 13:9cd54f7db57a 385 LogTimeF("DnsNameDecodeIp6 exceeded depth limit\r\n");
andrewboyson 13:9cd54f7db57a 386 *pIp = 0;
andrewboyson 13:9cd54f7db57a 387 return;
andrewboyson 13:9cd54f7db57a 388 }
andrewboyson 13:9cd54f7db57a 389 p = derefOffset(p);
andrewboyson 13:9cd54f7db57a 390 }
andrewboyson 13:9cd54f7db57a 391 else //it's a length plus a field eg 3www
andrewboyson 13:9cd54f7db57a 392 {
andrewboyson 13:9cd54f7db57a 393 p++; // move past the length
andrewboyson 13:9cd54f7db57a 394 if (field <= 31)
andrewboyson 13:9cd54f7db57a 395 {
andrewboyson 13:9cd54f7db57a 396 if (length > 1) {pIp[0] = 0; return; } // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 13:9cd54f7db57a 397 int nibble = 0;
andrewboyson 13:9cd54f7db57a 398 if (*p >= '0' && *p <= '9') nibble = *p - '0';
andrewboyson 13:9cd54f7db57a 399 else if (*p >= 'a' && *p <= 'f') nibble = *p - 'a' + 10;
andrewboyson 13:9cd54f7db57a 400 else if (*p >= 'A' && *p <= 'F') nibble = *p - 'A' + 10;
andrewboyson 13:9cd54f7db57a 401 else {pIp[0] = 0; return; } // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 13:9cd54f7db57a 402 if ((field & 1) == 0)
andrewboyson 13:9cd54f7db57a 403 {
andrewboyson 13:9cd54f7db57a 404 pIp[15 - (field >> 1)] = nibble;
andrewboyson 13:9cd54f7db57a 405 }
andrewboyson 13:9cd54f7db57a 406 else
andrewboyson 13:9cd54f7db57a 407 {
andrewboyson 13:9cd54f7db57a 408 nibble <<= 4;
andrewboyson 13:9cd54f7db57a 409 pIp[15 - (field >> 1)] |= nibble;
andrewboyson 13:9cd54f7db57a 410 }
andrewboyson 13:9cd54f7db57a 411 p += length;
andrewboyson 13:9cd54f7db57a 412 }
andrewboyson 13:9cd54f7db57a 413 else if (field == 32)
andrewboyson 13:9cd54f7db57a 414 {
andrewboyson 13:9cd54f7db57a 415 if (length != 3) {pIp[0] = 0; return; } // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 13:9cd54f7db57a 416 p+= length;
andrewboyson 13:9cd54f7db57a 417 }
andrewboyson 13:9cd54f7db57a 418 else if (field == 33)
andrewboyson 13:9cd54f7db57a 419 {
andrewboyson 13:9cd54f7db57a 420 if (length != 4) {pIp[0] = 0; return; } // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 13:9cd54f7db57a 421 p+= length;
andrewboyson 13:9cd54f7db57a 422 }
andrewboyson 13:9cd54f7db57a 423 else
andrewboyson 13:9cd54f7db57a 424 {
andrewboyson 13:9cd54f7db57a 425 pIp[0] = 0; return; // expect 5.8.c.c.0.1.e.f.f.f.2.3.1.1.2.0.8.7.d.0.9.0.f.1.0.7.4.0.1.0.0.2.ip6.arpa
andrewboyson 13:9cd54f7db57a 426 }
andrewboyson 13:9cd54f7db57a 427 field++;
andrewboyson 13:9cd54f7db57a 428 }
andrewboyson 13:9cd54f7db57a 429 }
andrewboyson 13:9cd54f7db57a 430 }
andrewboyson 13:9cd54f7db57a 431 void DnsNameEncodeIp4(uint32_t ip, char** pp)
andrewboyson 13:9cd54f7db57a 432 {
andrewboyson 13:9cd54f7db57a 433 char* p = *pp; //Get a convenient pointer to the next byte
andrewboyson 13:9cd54f7db57a 434
andrewboyson 13:9cd54f7db57a 435 char* pLen = p;
andrewboyson 13:9cd54f7db57a 436 p++;
andrewboyson 13:9cd54f7db57a 437
andrewboyson 13:9cd54f7db57a 438 *pLen = sprintf(p, "%d", (ip & 0xff000000) >> 24);
andrewboyson 13:9cd54f7db57a 439 p += *pLen;
andrewboyson 13:9cd54f7db57a 440 pLen = p;
andrewboyson 13:9cd54f7db57a 441 p++;
andrewboyson 13:9cd54f7db57a 442
andrewboyson 13:9cd54f7db57a 443 *pLen = sprintf(p, "%d", (ip & 0x00ff0000) >> 16);
andrewboyson 13:9cd54f7db57a 444 p += *pLen;
andrewboyson 13:9cd54f7db57a 445 pLen = p;
andrewboyson 13:9cd54f7db57a 446 p++;
andrewboyson 13:9cd54f7db57a 447
andrewboyson 13:9cd54f7db57a 448 *pLen = sprintf(p, "%d", (ip & 0x0000ff00) >> 8);
andrewboyson 13:9cd54f7db57a 449 p += *pLen;
andrewboyson 13:9cd54f7db57a 450 pLen = p;
andrewboyson 13:9cd54f7db57a 451 p++;
andrewboyson 13:9cd54f7db57a 452
andrewboyson 13:9cd54f7db57a 453 *pLen = sprintf(p, "%d", (ip & 0x000000ff) >> 0);
andrewboyson 13:9cd54f7db57a 454 p += *pLen;
andrewboyson 13:9cd54f7db57a 455 pLen = p;
andrewboyson 13:9cd54f7db57a 456 p++;
andrewboyson 13:9cd54f7db57a 457
andrewboyson 13:9cd54f7db57a 458 *pLen = sprintf(p, "in-addr");
andrewboyson 13:9cd54f7db57a 459 p += *pLen;
andrewboyson 13:9cd54f7db57a 460 pLen = p;
andrewboyson 13:9cd54f7db57a 461 p++;
andrewboyson 13:9cd54f7db57a 462
andrewboyson 13:9cd54f7db57a 463 *pLen = sprintf(p, "arpa");
andrewboyson 13:9cd54f7db57a 464 p += *pLen;
andrewboyson 13:9cd54f7db57a 465 pLen = p;
andrewboyson 13:9cd54f7db57a 466 p++;
andrewboyson 13:9cd54f7db57a 467
andrewboyson 13:9cd54f7db57a 468 *pLen = 0;
andrewboyson 13:9cd54f7db57a 469
andrewboyson 13:9cd54f7db57a 470 *pp = p; //Save the convenient pointer back into the pointer to pointer
andrewboyson 13:9cd54f7db57a 471
andrewboyson 13:9cd54f7db57a 472 }
andrewboyson 13:9cd54f7db57a 473
andrewboyson 13:9cd54f7db57a 474 void DnsNameEncodeIp6(char* ip, char** pp)
andrewboyson 13:9cd54f7db57a 475 {
andrewboyson 13:9cd54f7db57a 476 char* p = *pp; //Get a convenient pointer to the next byte
andrewboyson 13:9cd54f7db57a 477
andrewboyson 13:9cd54f7db57a 478 ip += 16;
andrewboyson 13:9cd54f7db57a 479 for (int i = 0; i < 16; i++)
andrewboyson 13:9cd54f7db57a 480 {
andrewboyson 13:9cd54f7db57a 481 ip--;
andrewboyson 13:9cd54f7db57a 482
andrewboyson 13:9cd54f7db57a 483 int v;
andrewboyson 13:9cd54f7db57a 484
andrewboyson 13:9cd54f7db57a 485 *p++ = 1;
andrewboyson 13:9cd54f7db57a 486 v = *ip & 0x0F;
andrewboyson 13:9cd54f7db57a 487 *p++ = v < 10 ? v + '0' : v - 10 + 'a';
andrewboyson 13:9cd54f7db57a 488
andrewboyson 13:9cd54f7db57a 489 *p++ = 1;
andrewboyson 13:9cd54f7db57a 490 v = *ip >> 4;
andrewboyson 13:9cd54f7db57a 491 *p++ = v < 10 ? v + '0' : v - 10 + 'a';
andrewboyson 13:9cd54f7db57a 492 }
andrewboyson 13:9cd54f7db57a 493 char* pLen = p;
andrewboyson 13:9cd54f7db57a 494 p++;
andrewboyson 13:9cd54f7db57a 495
andrewboyson 13:9cd54f7db57a 496 *pLen = sprintf(p, "ip6");
andrewboyson 13:9cd54f7db57a 497 p += *pLen;
andrewboyson 13:9cd54f7db57a 498 pLen = p;
andrewboyson 13:9cd54f7db57a 499 p++;
andrewboyson 13:9cd54f7db57a 500
andrewboyson 13:9cd54f7db57a 501 *pLen = sprintf(p, "arpa");
andrewboyson 13:9cd54f7db57a 502 p += *pLen;
andrewboyson 13:9cd54f7db57a 503 pLen = p;
andrewboyson 13:9cd54f7db57a 504 p++;
andrewboyson 13:9cd54f7db57a 505
andrewboyson 13:9cd54f7db57a 506 *pLen = 0;
andrewboyson 13:9cd54f7db57a 507
andrewboyson 13:9cd54f7db57a 508 *pp = p; //Save the convenient pointer back into the pointer to pointer
andrewboyson 13:9cd54f7db57a 509
andrewboyson 13:9cd54f7db57a 510 }
andrewboyson 13:9cd54f7db57a 511
andrewboyson 13:9cd54f7db57a 512 void DnsNameEncode(char* pName, char** pp)
andrewboyson 13:9cd54f7db57a 513 {
andrewboyson 13:9cd54f7db57a 514 char* p = *pp; //Get a convenient pointer to the next byte
andrewboyson 13:9cd54f7db57a 515
andrewboyson 13:9cd54f7db57a 516 char* pLen = p; //Record the position of the first length byte
andrewboyson 13:9cd54f7db57a 517 p++; //Move to the start of the first field
andrewboyson 13:9cd54f7db57a 518
andrewboyson 13:9cd54f7db57a 519 while (true)
andrewboyson 13:9cd54f7db57a 520 {
andrewboyson 13:9cd54f7db57a 521 char c = *pName;
andrewboyson 13:9cd54f7db57a 522 switch (c)
andrewboyson 13:9cd54f7db57a 523 {
andrewboyson 13:9cd54f7db57a 524 case 0:
andrewboyson 13:9cd54f7db57a 525 *pLen = p - pLen - 1;
andrewboyson 13:9cd54f7db57a 526 *p = 0;
andrewboyson 13:9cd54f7db57a 527 p++;
andrewboyson 13:9cd54f7db57a 528 *pp = p; //Save the convenient pointer back into the pointer to pointer
andrewboyson 13:9cd54f7db57a 529 return;
andrewboyson 13:9cd54f7db57a 530 case '.':
andrewboyson 13:9cd54f7db57a 531 *pLen = p - pLen - 1;
andrewboyson 13:9cd54f7db57a 532 pLen = p;
andrewboyson 13:9cd54f7db57a 533 p++;
andrewboyson 13:9cd54f7db57a 534 break;
andrewboyson 13:9cd54f7db57a 535 default:
andrewboyson 13:9cd54f7db57a 536 *p = c;
andrewboyson 13:9cd54f7db57a 537 p++;
andrewboyson 13:9cd54f7db57a 538 break;
andrewboyson 13:9cd54f7db57a 539 }
andrewboyson 13:9cd54f7db57a 540 pName++;
andrewboyson 13:9cd54f7db57a 541 }
andrewboyson 13:9cd54f7db57a 542 }