Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Jan 21 13:34:33 2021 +0000
Revision:
189:e1c7990486c4
Parent:
178:52714fef5ca1
Child:
190:c4415a7253f5
Added test for name from Ipv4 address

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 128:79052cb4a41c 4 #include "dns.h"
andrewboyson 128:79052cb4a41c 5 #include "dnshdr.h"
andrewboyson 128:79052cb4a41c 6 #include "dnsname.h"
andrewboyson 128:79052cb4a41c 7 #include "dnslabel.h"
andrewboyson 128:79052cb4a41c 8 #include "net.h"
andrewboyson 178:52714fef5ca1 9 #include "net-this.h"
andrewboyson 128:79052cb4a41c 10 #include "action.h"
andrewboyson 128:79052cb4a41c 11 #include "log.h"
andrewboyson 128:79052cb4a41c 12 #include "dhcp.h"
andrewboyson 128:79052cb4a41c 13 #include "slaac.h"
andrewboyson 128:79052cb4a41c 14 #include "ip4.h"
andrewboyson 128:79052cb4a41c 15 #include "ip6.h"
andrewboyson 13:9cd54f7db57a 16
andrewboyson 37:793b39683406 17 bool DnsServerTrace = false;
andrewboyson 37:793b39683406 18
andrewboyson 172:9bc3c7b2cca1 19 #define RECORD_NONE 0
andrewboyson 172:9bc3c7b2cca1 20 #define RECORD_PTR4 1
andrewboyson 172:9bc3c7b2cca1 21 #define RECORD_PTR6_LINK_LOCAL 2
andrewboyson 172:9bc3c7b2cca1 22 #define RECORD_PTR6_UNIQUE_LOCAL 3
andrewboyson 172:9bc3c7b2cca1 23 #define RECORD_PTR6_GLOBAL 4
andrewboyson 172:9bc3c7b2cca1 24 #define RECORD_A 5
andrewboyson 172:9bc3c7b2cca1 25 #define RECORD_AAAA_LINK_LOCAL 6
andrewboyson 172:9bc3c7b2cca1 26 #define RECORD_AAAA_UNIQUE_LOCAL 7
andrewboyson 172:9bc3c7b2cca1 27 #define RECORD_AAAA_GLOBAL 8
andrewboyson 44:83ce5ace337b 28
andrewboyson 44:83ce5ace337b 29 #define MAX_ANSWERS 4
andrewboyson 13:9cd54f7db57a 30
andrewboyson 32:679654f2d023 31 //Set by 'initialise'
andrewboyson 36:900e24b27bfb 32 static char* p; //Position relative to DnsHdrData and is updated while both reading questions and writing answers
andrewboyson 178:52714fef5ca1 33 static char myFullName[100]; //The name, adjusted to include the domain if needed by the protocol, used when reading and when writing
andrewboyson 178:52714fef5ca1 34 static int myFullNameLength;
andrewboyson 32:679654f2d023 35
andrewboyson 32:679654f2d023 36 //Set by readQuestions and used by answerQuestions
andrewboyson 44:83ce5ace337b 37 static int answers[MAX_ANSWERS];
andrewboyson 44:83ce5ace337b 38 static int answerCount = 0;
andrewboyson 36:900e24b27bfb 39 static bool mdnsUnicastReply;
andrewboyson 32:679654f2d023 40
andrewboyson 32:679654f2d023 41 static int readQuestions()
andrewboyson 32:679654f2d023 42 {
andrewboyson 37:793b39683406 43 p = DnsHdrData;
andrewboyson 32:679654f2d023 44 mdnsUnicastReply = false;
andrewboyson 13:9cd54f7db57a 45
andrewboyson 13:9cd54f7db57a 46 //Get the questions
andrewboyson 44:83ce5ace337b 47 answerCount = 0;
andrewboyson 44:83ce5ace337b 48 for (int i = 0; i < DnsHdrQdcount; i++)
andrewboyson 13:9cd54f7db57a 49 {
andrewboyson 44:83ce5ace337b 50 //Bomb out if there are too many answers
andrewboyson 44:83ce5ace337b 51 if (answerCount >= MAX_ANSWERS)
andrewboyson 37:793b39683406 52 {
andrewboyson 44:83ce5ace337b 53 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - exceeded %d answers\r\n", MAX_ANSWERS);
andrewboyson 37:793b39683406 54 break;
andrewboyson 37:793b39683406 55 }
andrewboyson 37:793b39683406 56
andrewboyson 37:793b39683406 57 //Bomb out if we are tending to overrun the buffer
andrewboyson 61:aad055f1b0d1 58 if (p - DnsHdrData > DnsHdrDataLength)
andrewboyson 37:793b39683406 59 {
andrewboyson 61:aad055f1b0d1 60 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions - overrunning the buffer of %d bytes\r\n", DnsHdrDataLength);
andrewboyson 37:793b39683406 61 return -1;
andrewboyson 37:793b39683406 62 }
andrewboyson 37:793b39683406 63
andrewboyson 37:793b39683406 64 //Node name
andrewboyson 13:9cd54f7db57a 65 int nameLength = DnsNameLength(p);
andrewboyson 37:793b39683406 66 if (!nameLength)
andrewboyson 37:793b39683406 67 {
andrewboyson 37:793b39683406 68 if (DnsServerTrace) LogTimeF("DnsServer-readQuestions namelength is zero\r\n");
andrewboyson 37:793b39683406 69 return -1;
andrewboyson 37:793b39683406 70 }
andrewboyson 178:52714fef5ca1 71 bool nodeIsName = DnsNameComparePtr(p, myFullName);
andrewboyson 44:83ce5ace337b 72 bool nodeIsAddr4 = DnsNameCompareIp4(p, DhcpLocalIp);
andrewboyson 189:e1c7990486c4 73 if (nodeIsAddr4) LogTimeF("DnsServer received request for name from my Ip4 address\r\n");
andrewboyson 44:83ce5ace337b 74 bool nodeIsLocl6 = DnsNameCompareIp6(p, SlaacLinkLocalIp);
andrewboyson 172:9bc3c7b2cca1 75 bool nodeIsUniq6 = DnsNameCompareIp6(p, SlaacUniqueLocalIp);
andrewboyson 44:83ce5ace337b 76 bool nodeIsGlob6 = DnsNameCompareIp6(p, SlaacGlobalIp);
andrewboyson 44:83ce5ace337b 77 p += nameLength; //Skip past the name
andrewboyson 44:83ce5ace337b 78
andrewboyson 37:793b39683406 79 //Type
andrewboyson 44:83ce5ace337b 80 p++ ; //skip the first byte of the type
andrewboyson 44:83ce5ace337b 81 char recordType = *p++; //read the record type
andrewboyson 37:793b39683406 82
andrewboyson 37:793b39683406 83 //Class
andrewboyson 44:83ce5ace337b 84 if (*p++ & 0x80) mdnsUnicastReply = true; //check the class 15th bit (UNICAST-RESPONSE)
andrewboyson 44:83ce5ace337b 85 p++; //skip the class
andrewboyson 44:83ce5ace337b 86
andrewboyson 44:83ce5ace337b 87 //Handle the questions
andrewboyson 178:52714fef5ca1 88 if (nodeIsName && recordType == DNS_RECORD_A ) answers[answerCount++] = RECORD_A;
andrewboyson 178:52714fef5ca1 89 if (nodeIsName && recordType == DNS_RECORD_AAAA)
andrewboyson 177:2cd7fde8bfe5 90 {
andrewboyson 178:52714fef5ca1 91 answers[answerCount++] = RECORD_AAAA_LINK_LOCAL;
andrewboyson 178:52714fef5ca1 92 if (SlaacUniqueLocalIp[0]) answers[answerCount++] = RECORD_AAAA_UNIQUE_LOCAL;
andrewboyson 178:52714fef5ca1 93 if (SlaacGlobalIp [0]) answers[answerCount++] = RECORD_AAAA_GLOBAL;
andrewboyson 177:2cd7fde8bfe5 94 }
andrewboyson 178:52714fef5ca1 95 if (nodeIsAddr4 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR4;
andrewboyson 178:52714fef5ca1 96 if (nodeIsLocl6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_LINK_LOCAL;
andrewboyson 178:52714fef5ca1 97 if (nodeIsUniq6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_UNIQUE_LOCAL;
andrewboyson 178:52714fef5ca1 98 if (nodeIsGlob6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_GLOBAL;
andrewboyson 13:9cd54f7db57a 99 }
andrewboyson 32:679654f2d023 100 return 0;
andrewboyson 32:679654f2d023 101 }
andrewboyson 32:679654f2d023 102 static int addAnswers(int dnsProtocol)
andrewboyson 59:e0e556c8bd46 103 {
andrewboyson 44:83ce5ace337b 104 //Go through each answer
andrewboyson 33:714a0345e59b 105 DnsHdrAncount = 0;
andrewboyson 44:83ce5ace337b 106 for (int i = 0; i < answerCount; i++)
andrewboyson 44:83ce5ace337b 107 {
andrewboyson 37:793b39683406 108 //Bomb out if we are tending to overrun the buffer
andrewboyson 61:aad055f1b0d1 109 if (p - DnsHdrData > DnsHdrDataLength)
andrewboyson 32:679654f2d023 110 {
andrewboyson 37:793b39683406 111 if (DnsServerTrace) LogTimeF("DnsServer-addAnswers - reply is getting too big\r\n");
andrewboyson 32:679654f2d023 112 return -1;
andrewboyson 32:679654f2d023 113 }
andrewboyson 43:bc028d5a6424 114
andrewboyson 37:793b39683406 115 //Encode the node name
andrewboyson 44:83ce5ace337b 116 switch (answers[i])
andrewboyson 32:679654f2d023 117 {
andrewboyson 178:52714fef5ca1 118 case RECORD_A: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 119 case RECORD_AAAA_LINK_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 120 case RECORD_AAAA_UNIQUE_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 121 case RECORD_AAAA_GLOBAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 172:9bc3c7b2cca1 122 case RECORD_PTR4: DnsNameEncodeIp4(DhcpLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 123 case RECORD_PTR6_LINK_LOCAL: DnsNameEncodeIp6(SlaacLinkLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 124 case RECORD_PTR6_UNIQUE_LOCAL: DnsNameEncodeIp6(SlaacUniqueLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 125 case RECORD_PTR6_GLOBAL: DnsNameEncodeIp6(SlaacGlobalIp, &p); break;
andrewboyson 13:9cd54f7db57a 126 }
andrewboyson 37:793b39683406 127
andrewboyson 44:83ce5ace337b 128 //Add the 16 bit type
andrewboyson 44:83ce5ace337b 129 *p++ = 0;
andrewboyson 44:83ce5ace337b 130 switch (answers[i])
andrewboyson 44:83ce5ace337b 131 {
andrewboyson 172:9bc3c7b2cca1 132 case RECORD_A: *p++ = DNS_RECORD_A; break;
andrewboyson 172:9bc3c7b2cca1 133 case RECORD_AAAA_LINK_LOCAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 134 case RECORD_AAAA_UNIQUE_LOCAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 135 case RECORD_AAAA_GLOBAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 136 case RECORD_PTR4: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 137 case RECORD_PTR6_LINK_LOCAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 138 case RECORD_PTR6_UNIQUE_LOCAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 139 case RECORD_PTR6_GLOBAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 44:83ce5ace337b 140 }
andrewboyson 37:793b39683406 141
andrewboyson 37:793b39683406 142 //Add the class
andrewboyson 37:793b39683406 143 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 144 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 37:793b39683406 145
andrewboyson 37:793b39683406 146 //Add the TTL
andrewboyson 32:679654f2d023 147 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 37:793b39683406 148
andrewboyson 37:793b39683406 149
andrewboyson 37:793b39683406 150 //Add the 16 bit payload length
andrewboyson 44:83ce5ace337b 151 *p++ = 0;
andrewboyson 44:83ce5ace337b 152 switch (answers[i])
andrewboyson 37:793b39683406 153 {
andrewboyson 178:52714fef5ca1 154 case RECORD_A: *p++ = 4; break;
andrewboyson 178:52714fef5ca1 155 case RECORD_AAAA_LINK_LOCAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 156 case RECORD_AAAA_UNIQUE_LOCAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 157 case RECORD_AAAA_GLOBAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 158 case RECORD_PTR4: *p++ = myFullNameLength + 2; break; //add a byte for the initial length and another for the terminating zero length
andrewboyson 178:52714fef5ca1 159 case RECORD_PTR6_LINK_LOCAL: *p++ = myFullNameLength + 2; break;
andrewboyson 178:52714fef5ca1 160 case RECORD_PTR6_UNIQUE_LOCAL: *p++ = myFullNameLength + 2; break;
andrewboyson 178:52714fef5ca1 161 case RECORD_PTR6_GLOBAL: *p++ = myFullNameLength + 2; break;
andrewboyson 37:793b39683406 162 }
andrewboyson 37:793b39683406 163
andrewboyson 37:793b39683406 164 //Add the payload
andrewboyson 44:83ce5ace337b 165 switch (answers[i])
andrewboyson 37:793b39683406 166 {
andrewboyson 172:9bc3c7b2cca1 167 case RECORD_A: memcpy(p, &DhcpLocalIp, 4); p += 4; break;
andrewboyson 172:9bc3c7b2cca1 168 case RECORD_AAAA_LINK_LOCAL: memcpy(p, SlaacLinkLocalIp, 16); p += 16; break;
andrewboyson 172:9bc3c7b2cca1 169 case RECORD_AAAA_UNIQUE_LOCAL: memcpy(p, SlaacUniqueLocalIp, 16); p += 16; break;
andrewboyson 172:9bc3c7b2cca1 170 case RECORD_AAAA_GLOBAL: memcpy(p, SlaacGlobalIp, 16); p += 16; break;
andrewboyson 178:52714fef5ca1 171 case RECORD_PTR4: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 172 case RECORD_PTR6_LINK_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 173 case RECORD_PTR6_UNIQUE_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 174 case RECORD_PTR6_GLOBAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 37:793b39683406 175 }
andrewboyson 44:83ce5ace337b 176 //Increment the number of good answers to send
andrewboyson 44:83ce5ace337b 177 DnsHdrAncount++;
andrewboyson 13:9cd54f7db57a 178 }
andrewboyson 32:679654f2d023 179 return 0;
andrewboyson 32:679654f2d023 180 }
andrewboyson 32:679654f2d023 181
andrewboyson 59:e0e556c8bd46 182 int DnsServerHandleQuery(void (*traceback)(void), int dnsProtocol, void* pPacketTx, int *pSizeTx) //Received an mdns or llmnr query on port 5353 or 5355
andrewboyson 59:e0e556c8bd46 183 {
andrewboyson 178:52714fef5ca1 184 myFullNameLength = DnsLabelMakeFullNameFromName(dnsProtocol, NET_NAME, sizeof(myFullName), myFullName);
andrewboyson 32:679654f2d023 185
andrewboyson 37:793b39683406 186 if (readQuestions()) return DO_NOTHING;
andrewboyson 44:83ce5ace337b 187 if (!answerCount) return DO_NOTHING;
andrewboyson 37:793b39683406 188
andrewboyson 57:e0fb648acf48 189 if (DnsServerTrace || NetTraceHostGetMatched())
andrewboyson 37:793b39683406 190 {
andrewboyson 43:bc028d5a6424 191 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 192 LogTimeF("DnsServer received query\r\n");
andrewboyson 43:bc028d5a6424 193 if (NetTraceStack) traceback();
andrewboyson 37:793b39683406 194 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 195 }
andrewboyson 37:793b39683406 196
andrewboyson 59:e0e556c8bd46 197 char* pRx = DnsHdrData;
andrewboyson 59:e0e556c8bd46 198 char* pEndRx = p;
andrewboyson 59:e0e556c8bd46 199 int qdcount = DnsHdrQdcount;
andrewboyson 59:e0e556c8bd46 200 int nscount = DnsHdrNscount;
andrewboyson 59:e0e556c8bd46 201 int arcount = DnsHdrArcount;
andrewboyson 59:e0e556c8bd46 202
andrewboyson 59:e0e556c8bd46 203 DnsHdrSetup(pPacketTx, *pSizeTx);
andrewboyson 59:e0e556c8bd46 204 p = DnsHdrData;
andrewboyson 59:e0e556c8bd46 205
andrewboyson 59:e0e556c8bd46 206 //Add the questions if this is not MDNS
andrewboyson 59:e0e556c8bd46 207 if (dnsProtocol == DNS_PROTOCOL_MDNS)
andrewboyson 59:e0e556c8bd46 208 {
andrewboyson 59:e0e556c8bd46 209 DnsHdrQdcount = 0;
andrewboyson 59:e0e556c8bd46 210 DnsHdrNscount = 0;
andrewboyson 59:e0e556c8bd46 211 DnsHdrArcount = 0;
andrewboyson 59:e0e556c8bd46 212 }
andrewboyson 59:e0e556c8bd46 213 else
andrewboyson 59:e0e556c8bd46 214 {
andrewboyson 59:e0e556c8bd46 215 DnsHdrQdcount = qdcount;
andrewboyson 59:e0e556c8bd46 216 DnsHdrNscount = nscount;
andrewboyson 59:e0e556c8bd46 217 DnsHdrArcount = arcount;
andrewboyson 59:e0e556c8bd46 218 while (pRx < pEndRx) *p++ = *pRx++;
andrewboyson 59:e0e556c8bd46 219 }
andrewboyson 59:e0e556c8bd46 220
andrewboyson 59:e0e556c8bd46 221
andrewboyson 37:793b39683406 222 if (addAnswers(dnsProtocol)) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 223
andrewboyson 59:e0e556c8bd46 224 DnsHdrIsReply = true;
andrewboyson 59:e0e556c8bd46 225 DnsHdrIsAuthoritative = false;
andrewboyson 169:336d499dc560 226 if (dnsProtocol == DNS_PROTOCOL_MDNS) DnsHdrIsAuthoritative = true; //See rfc6762 18.4
andrewboyson 59:e0e556c8bd46 227 DnsHdrIsRecursiveQuery = false;
andrewboyson 59:e0e556c8bd46 228
andrewboyson 13:9cd54f7db57a 229 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 230
andrewboyson 59:e0e556c8bd46 231 *pSizeTx = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 232
andrewboyson 57:e0fb648acf48 233 if (DnsServerTrace || NetTraceHostGetMatched()) DnsHdrLog(dnsProtocol);
andrewboyson 13:9cd54f7db57a 234
andrewboyson 37:793b39683406 235 int dest;
andrewboyson 37:793b39683406 236 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) dest = MULTICAST_MDNS;
andrewboyson 37:793b39683406 237 else dest = UNICAST;
andrewboyson 37:793b39683406 238
andrewboyson 160:6a1d1d368f80 239 return ActionMakeFromDestAndTrace(dest, (NetTraceStack && DnsServerTrace) || NetTraceHostGetMatched());
andrewboyson 13:9cd54f7db57a 240 }