Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Tue Dec 29 19:14:35 2020 +0000
Revision:
178:52714fef5ca1
Parent:
177:2cd7fde8bfe5
Child:
189:e1c7990486c4
Included host name in DHCP request option 12 to allow my Sky router to display the host name instead of 'UNKNOWN'. Also removed different host names for IPv4 and IPv6.

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 44:83ce5ace337b 73 bool nodeIsLocl6 = DnsNameCompareIp6(p, SlaacLinkLocalIp);
andrewboyson 172:9bc3c7b2cca1 74 bool nodeIsUniq6 = DnsNameCompareIp6(p, SlaacUniqueLocalIp);
andrewboyson 44:83ce5ace337b 75 bool nodeIsGlob6 = DnsNameCompareIp6(p, SlaacGlobalIp);
andrewboyson 44:83ce5ace337b 76 p += nameLength; //Skip past the name
andrewboyson 44:83ce5ace337b 77
andrewboyson 37:793b39683406 78 //Type
andrewboyson 44:83ce5ace337b 79 p++ ; //skip the first byte of the type
andrewboyson 44:83ce5ace337b 80 char recordType = *p++; //read the record type
andrewboyson 37:793b39683406 81
andrewboyson 37:793b39683406 82 //Class
andrewboyson 44:83ce5ace337b 83 if (*p++ & 0x80) mdnsUnicastReply = true; //check the class 15th bit (UNICAST-RESPONSE)
andrewboyson 44:83ce5ace337b 84 p++; //skip the class
andrewboyson 44:83ce5ace337b 85
andrewboyson 44:83ce5ace337b 86 //Handle the questions
andrewboyson 178:52714fef5ca1 87 if (nodeIsName && recordType == DNS_RECORD_A ) answers[answerCount++] = RECORD_A;
andrewboyson 178:52714fef5ca1 88 if (nodeIsName && recordType == DNS_RECORD_AAAA)
andrewboyson 177:2cd7fde8bfe5 89 {
andrewboyson 178:52714fef5ca1 90 answers[answerCount++] = RECORD_AAAA_LINK_LOCAL;
andrewboyson 178:52714fef5ca1 91 if (SlaacUniqueLocalIp[0]) answers[answerCount++] = RECORD_AAAA_UNIQUE_LOCAL;
andrewboyson 178:52714fef5ca1 92 if (SlaacGlobalIp [0]) answers[answerCount++] = RECORD_AAAA_GLOBAL;
andrewboyson 177:2cd7fde8bfe5 93 }
andrewboyson 178:52714fef5ca1 94 if (nodeIsAddr4 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR4;
andrewboyson 178:52714fef5ca1 95 if (nodeIsLocl6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_LINK_LOCAL;
andrewboyson 178:52714fef5ca1 96 if (nodeIsUniq6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_UNIQUE_LOCAL;
andrewboyson 178:52714fef5ca1 97 if (nodeIsGlob6 && recordType == DNS_RECORD_PTR ) answers[answerCount++] = RECORD_PTR6_GLOBAL;
andrewboyson 13:9cd54f7db57a 98 }
andrewboyson 32:679654f2d023 99 return 0;
andrewboyson 32:679654f2d023 100 }
andrewboyson 32:679654f2d023 101 static int addAnswers(int dnsProtocol)
andrewboyson 59:e0e556c8bd46 102 {
andrewboyson 44:83ce5ace337b 103 //Go through each answer
andrewboyson 33:714a0345e59b 104 DnsHdrAncount = 0;
andrewboyson 44:83ce5ace337b 105 for (int i = 0; i < answerCount; i++)
andrewboyson 44:83ce5ace337b 106 {
andrewboyson 37:793b39683406 107 //Bomb out if we are tending to overrun the buffer
andrewboyson 61:aad055f1b0d1 108 if (p - DnsHdrData > DnsHdrDataLength)
andrewboyson 32:679654f2d023 109 {
andrewboyson 37:793b39683406 110 if (DnsServerTrace) LogTimeF("DnsServer-addAnswers - reply is getting too big\r\n");
andrewboyson 32:679654f2d023 111 return -1;
andrewboyson 32:679654f2d023 112 }
andrewboyson 43:bc028d5a6424 113
andrewboyson 37:793b39683406 114 //Encode the node name
andrewboyson 44:83ce5ace337b 115 switch (answers[i])
andrewboyson 32:679654f2d023 116 {
andrewboyson 178:52714fef5ca1 117 case RECORD_A: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 118 case RECORD_AAAA_LINK_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 119 case RECORD_AAAA_UNIQUE_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 120 case RECORD_AAAA_GLOBAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 172:9bc3c7b2cca1 121 case RECORD_PTR4: DnsNameEncodeIp4(DhcpLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 122 case RECORD_PTR6_LINK_LOCAL: DnsNameEncodeIp6(SlaacLinkLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 123 case RECORD_PTR6_UNIQUE_LOCAL: DnsNameEncodeIp6(SlaacUniqueLocalIp, &p); break;
andrewboyson 172:9bc3c7b2cca1 124 case RECORD_PTR6_GLOBAL: DnsNameEncodeIp6(SlaacGlobalIp, &p); break;
andrewboyson 13:9cd54f7db57a 125 }
andrewboyson 37:793b39683406 126
andrewboyson 44:83ce5ace337b 127 //Add the 16 bit type
andrewboyson 44:83ce5ace337b 128 *p++ = 0;
andrewboyson 44:83ce5ace337b 129 switch (answers[i])
andrewboyson 44:83ce5ace337b 130 {
andrewboyson 172:9bc3c7b2cca1 131 case RECORD_A: *p++ = DNS_RECORD_A; break;
andrewboyson 172:9bc3c7b2cca1 132 case RECORD_AAAA_LINK_LOCAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 133 case RECORD_AAAA_UNIQUE_LOCAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 134 case RECORD_AAAA_GLOBAL: *p++ = DNS_RECORD_AAAA; break;
andrewboyson 172:9bc3c7b2cca1 135 case RECORD_PTR4: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 136 case RECORD_PTR6_LINK_LOCAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 137 case RECORD_PTR6_UNIQUE_LOCAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 172:9bc3c7b2cca1 138 case RECORD_PTR6_GLOBAL: *p++ = DNS_RECORD_PTR; break;
andrewboyson 44:83ce5ace337b 139 }
andrewboyson 37:793b39683406 140
andrewboyson 37:793b39683406 141 //Add the class
andrewboyson 37:793b39683406 142 char mdns = dnsProtocol == DNS_PROTOCOL_MDNS ? 0x80 : 0; //Set the 15th bit (CACHE_FLUSH) of the class to 1 if MDNS
andrewboyson 32:679654f2d023 143 *p++ = mdns; *p++ = 1; //16 bit Class LSB QCLASS_IN = 1 - internet
andrewboyson 37:793b39683406 144
andrewboyson 37:793b39683406 145 //Add the TTL
andrewboyson 32:679654f2d023 146 *p++ = 0; *p++ = 0; *p++ = 4; *p++ = 0; //32 bit TTL seconds - 1024
andrewboyson 37:793b39683406 147
andrewboyson 37:793b39683406 148
andrewboyson 37:793b39683406 149 //Add the 16 bit payload length
andrewboyson 44:83ce5ace337b 150 *p++ = 0;
andrewboyson 44:83ce5ace337b 151 switch (answers[i])
andrewboyson 37:793b39683406 152 {
andrewboyson 178:52714fef5ca1 153 case RECORD_A: *p++ = 4; break;
andrewboyson 178:52714fef5ca1 154 case RECORD_AAAA_LINK_LOCAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 155 case RECORD_AAAA_UNIQUE_LOCAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 156 case RECORD_AAAA_GLOBAL: *p++ = 16; break;
andrewboyson 178:52714fef5ca1 157 case RECORD_PTR4: *p++ = myFullNameLength + 2; break; //add a byte for the initial length and another for the terminating zero length
andrewboyson 178:52714fef5ca1 158 case RECORD_PTR6_LINK_LOCAL: *p++ = myFullNameLength + 2; break;
andrewboyson 178:52714fef5ca1 159 case RECORD_PTR6_UNIQUE_LOCAL: *p++ = myFullNameLength + 2; break;
andrewboyson 178:52714fef5ca1 160 case RECORD_PTR6_GLOBAL: *p++ = myFullNameLength + 2; break;
andrewboyson 37:793b39683406 161 }
andrewboyson 37:793b39683406 162
andrewboyson 37:793b39683406 163 //Add the payload
andrewboyson 44:83ce5ace337b 164 switch (answers[i])
andrewboyson 37:793b39683406 165 {
andrewboyson 172:9bc3c7b2cca1 166 case RECORD_A: memcpy(p, &DhcpLocalIp, 4); p += 4; break;
andrewboyson 172:9bc3c7b2cca1 167 case RECORD_AAAA_LINK_LOCAL: memcpy(p, SlaacLinkLocalIp, 16); p += 16; break;
andrewboyson 172:9bc3c7b2cca1 168 case RECORD_AAAA_UNIQUE_LOCAL: memcpy(p, SlaacUniqueLocalIp, 16); p += 16; break;
andrewboyson 172:9bc3c7b2cca1 169 case RECORD_AAAA_GLOBAL: memcpy(p, SlaacGlobalIp, 16); p += 16; break;
andrewboyson 178:52714fef5ca1 170 case RECORD_PTR4: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 171 case RECORD_PTR6_LINK_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 172 case RECORD_PTR6_UNIQUE_LOCAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 178:52714fef5ca1 173 case RECORD_PTR6_GLOBAL: DnsNameEncodePtr(myFullName, &p); break;
andrewboyson 37:793b39683406 174 }
andrewboyson 44:83ce5ace337b 175 //Increment the number of good answers to send
andrewboyson 44:83ce5ace337b 176 DnsHdrAncount++;
andrewboyson 13:9cd54f7db57a 177 }
andrewboyson 32:679654f2d023 178 return 0;
andrewboyson 32:679654f2d023 179 }
andrewboyson 32:679654f2d023 180
andrewboyson 59:e0e556c8bd46 181 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 182 {
andrewboyson 178:52714fef5ca1 183 myFullNameLength = DnsLabelMakeFullNameFromName(dnsProtocol, NET_NAME, sizeof(myFullName), myFullName);
andrewboyson 32:679654f2d023 184
andrewboyson 37:793b39683406 185 if (readQuestions()) return DO_NOTHING;
andrewboyson 44:83ce5ace337b 186 if (!answerCount) return DO_NOTHING;
andrewboyson 37:793b39683406 187
andrewboyson 57:e0fb648acf48 188 if (DnsServerTrace || NetTraceHostGetMatched())
andrewboyson 37:793b39683406 189 {
andrewboyson 43:bc028d5a6424 190 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 191 LogTimeF("DnsServer received query\r\n");
andrewboyson 43:bc028d5a6424 192 if (NetTraceStack) traceback();
andrewboyson 37:793b39683406 193 DnsHdrLog(dnsProtocol);
andrewboyson 37:793b39683406 194 }
andrewboyson 37:793b39683406 195
andrewboyson 59:e0e556c8bd46 196 char* pRx = DnsHdrData;
andrewboyson 59:e0e556c8bd46 197 char* pEndRx = p;
andrewboyson 59:e0e556c8bd46 198 int qdcount = DnsHdrQdcount;
andrewboyson 59:e0e556c8bd46 199 int nscount = DnsHdrNscount;
andrewboyson 59:e0e556c8bd46 200 int arcount = DnsHdrArcount;
andrewboyson 59:e0e556c8bd46 201
andrewboyson 59:e0e556c8bd46 202 DnsHdrSetup(pPacketTx, *pSizeTx);
andrewboyson 59:e0e556c8bd46 203 p = DnsHdrData;
andrewboyson 59:e0e556c8bd46 204
andrewboyson 59:e0e556c8bd46 205 //Add the questions if this is not MDNS
andrewboyson 59:e0e556c8bd46 206 if (dnsProtocol == DNS_PROTOCOL_MDNS)
andrewboyson 59:e0e556c8bd46 207 {
andrewboyson 59:e0e556c8bd46 208 DnsHdrQdcount = 0;
andrewboyson 59:e0e556c8bd46 209 DnsHdrNscount = 0;
andrewboyson 59:e0e556c8bd46 210 DnsHdrArcount = 0;
andrewboyson 59:e0e556c8bd46 211 }
andrewboyson 59:e0e556c8bd46 212 else
andrewboyson 59:e0e556c8bd46 213 {
andrewboyson 59:e0e556c8bd46 214 DnsHdrQdcount = qdcount;
andrewboyson 59:e0e556c8bd46 215 DnsHdrNscount = nscount;
andrewboyson 59:e0e556c8bd46 216 DnsHdrArcount = arcount;
andrewboyson 59:e0e556c8bd46 217 while (pRx < pEndRx) *p++ = *pRx++;
andrewboyson 59:e0e556c8bd46 218 }
andrewboyson 59:e0e556c8bd46 219
andrewboyson 59:e0e556c8bd46 220
andrewboyson 37:793b39683406 221 if (addAnswers(dnsProtocol)) return DO_NOTHING;
andrewboyson 13:9cd54f7db57a 222
andrewboyson 59:e0e556c8bd46 223 DnsHdrIsReply = true;
andrewboyson 59:e0e556c8bd46 224 DnsHdrIsAuthoritative = false;
andrewboyson 169:336d499dc560 225 if (dnsProtocol == DNS_PROTOCOL_MDNS) DnsHdrIsAuthoritative = true; //See rfc6762 18.4
andrewboyson 59:e0e556c8bd46 226 DnsHdrIsRecursiveQuery = false;
andrewboyson 59:e0e556c8bd46 227
andrewboyson 13:9cd54f7db57a 228 DnsHdrWrite();
andrewboyson 13:9cd54f7db57a 229
andrewboyson 59:e0e556c8bd46 230 *pSizeTx = p - DnsHdrPacket;
andrewboyson 13:9cd54f7db57a 231
andrewboyson 57:e0fb648acf48 232 if (DnsServerTrace || NetTraceHostGetMatched()) DnsHdrLog(dnsProtocol);
andrewboyson 13:9cd54f7db57a 233
andrewboyson 37:793b39683406 234 int dest;
andrewboyson 37:793b39683406 235 if (dnsProtocol == DNS_PROTOCOL_MDNS && !mdnsUnicastReply) dest = MULTICAST_MDNS;
andrewboyson 37:793b39683406 236 else dest = UNICAST;
andrewboyson 37:793b39683406 237
andrewboyson 160:6a1d1d368f80 238 return ActionMakeFromDestAndTrace(dest, (NetTraceStack && DnsServerTrace) || NetTraceHostGetMatched());
andrewboyson 13:9cd54f7db57a 239 }