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 Jan 21 14:56:55 2021 +0000
Revision:
190:c4415a7253f5
Parent:
160:6a1d1d368f80
Child:
191:33392a61182e
Corrected a bug in DnsLabel whereby a ip4 encoded name was not recognised. This has been there a long time and came to light because MDNS was failing to return a name from an Ip4 address.

Who changed what in which revision?

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