Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Dec 14 20:55:40 2017 +0000
Revision:
59:e0e556c8bd46
Parent:
57:e0fb648acf48
Added buffer length to help avoid over runs

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